--- /dev/null
+# xcode noise
+build/*
+*.pbxuser
+*.perspective
+*.perspectivev3
+*.mode1v3
+*.mode2v3
+
+# old skool
+.svn
+
+# osx noise
+.DS_Store
--- /dev/null
+[submodule "three20"]
+ path = three20
+ url = http://github.com/facebook/three20.git
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleDisplayName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.quanganhdo.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSRequiresIPhoneOS</key>
+ <false/>
+ <key>CFBundleURLTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleURLSchemes</key>
+ <array>
+ <string>atutor</string>
+ </array>
+ <key>CFBundleURLName</key>
+ <string>com.quanganhdo.atutor</string>
+ </dict>
+ </array>
+</dict>
+</plist>
--- /dev/null
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1D3623260D0F684500981E51 /* ATutorAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* ATutorAppDelegate.m */; };
+ 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; };
+ 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
+ 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
+ 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; };
+ CD26D9E511E8D30700003274 /* ContactsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = CD26D9E411E8D30700003274 /* ContactsDataSource.m */; };
+ CD26DA9C11E8E66800003274 /* ContactItemCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CD26DA9B11E8E66800003274 /* ContactItemCell.m */; };
+ CD720BF8120B75FC006EC605 /* IASKAppSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BDB120B75FB006EC605 /* IASKAppSettingsViewController.m */; };
+ CD720BF9120B75FC006EC605 /* IASKSpecifierValuesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BDD120B75FB006EC605 /* IASKSpecifierValuesViewController.m */; };
+ CD720BFA120B75FC006EC605 /* IASKSettingsReader.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BE0120B75FB006EC605 /* IASKSettingsReader.m */; };
+ CD720BFB120B75FC006EC605 /* IASKSpecifier.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BE2120B75FB006EC605 /* IASKSpecifier.m */; };
+ CD720BFC120B75FC006EC605 /* IASKPSSliderSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BE5120B75FB006EC605 /* IASKPSSliderSpecifierViewCell.m */; };
+ CD720BFD120B75FC006EC605 /* IASKPSTextFieldSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BE7120B75FB006EC605 /* IASKPSTextFieldSpecifierViewCell.m */; };
+ CD720BFE120B75FC006EC605 /* IASKPSTitleValueSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BE9120B75FB006EC605 /* IASKPSTitleValueSpecifierViewCell.m */; };
+ CD720BFF120B75FC006EC605 /* IASKPSToggleSwitchSpecifierViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BEB120B75FB006EC605 /* IASKPSToggleSwitchSpecifierViewCell.m */; };
+ CD720C00120B75FC006EC605 /* IASKSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BED120B75FB006EC605 /* IASKSlider.m */; };
+ CD720C01120B75FC006EC605 /* IASKSwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BEF120B75FB006EC605 /* IASKSwitch.m */; };
+ CD720C02120B75FC006EC605 /* IASKTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = CD720BF1120B75FB006EC605 /* IASKTextField.m */; };
+ CD720C03120B75FC006EC605 /* IASKAppSettingsView.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD720BF3120B75FB006EC605 /* IASKAppSettingsView.xib */; };
+ CD720C04120B75FC006EC605 /* IASKPSSliderSpecifierViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD720BF4120B75FB006EC605 /* IASKPSSliderSpecifierViewCell.xib */; };
+ CD720C05120B75FC006EC605 /* IASKPSTextFieldSpecifierViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD720BF5120B75FB006EC605 /* IASKPSTextFieldSpecifierViewCell.xib */; };
+ CD720C06120B75FC006EC605 /* IASKPSToggleSwitchSpecifierViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD720BF6120B75FB006EC605 /* IASKPSToggleSwitchSpecifierViewCell.xib */; };
+ CD720C07120B75FC006EC605 /* IASKSpecifierValuesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD720BF7120B75FC006EC605 /* IASKSpecifierValuesView.xib */; };
+ CD7A89F31204B60F00140865 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = CD7A89F21204B60F00140865 /* Settings.bundle */; };
+ CD8235CB11E3D66A00819570 /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD8235CA11E3D66A00819570 /* AddressBook.framework */; };
+ CD8235CD11E3D66A00819570 /* AddressBookUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD8235CC11E3D66A00819570 /* AddressBookUI.framework */; };
+ CD8235E011E3DD7500819570 /* ContactViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CD8235DF11E3DD7500819570 /* ContactViewController.m */; };
+ CD8F0EF211B2CFCF00D38970 /* QAWebController.m in Sources */ = {isa = PBXBuildFile; fileRef = CD8F0EF111B2CFCF00D38970 /* QAWebController.m */; };
+ CD8F0F7211B2D79A00D38970 /* CommonFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = CD8F0F7111B2D79A00D38970 /* CommonFunctions.m */; };
+ CD8F0F7E11B2D7A600D38970 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD8F0F7D11B2D7A600D38970 /* SystemConfiguration.framework */; };
+ CD90256E11B0C0B500519439 /* SFHFKeychainUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90253411B0C0B500519439 /* SFHFKeychainUtils.m */; };
+ CD90256F11B0C0B500519439 /* Base64Transcoder.c in Sources */ = {isa = PBXBuildFile; fileRef = CD90253711B0C0B500519439 /* Base64Transcoder.c */; };
+ CD90257011B0C0B500519439 /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = CD90253911B0C0B500519439 /* hmac.c */; };
+ CD90257111B0C0B500519439 /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = CD90253B11B0C0B500519439 /* sha1.c */; };
+ CD90257211B0C0B500519439 /* NSString+URLEncoding.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90253F11B0C0B500519439 /* NSString+URLEncoding.m */; };
+ CD90257311B0C0B500519439 /* OAAsynchronousDataFetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90254111B0C0B500519439 /* OAAsynchronousDataFetcher.m */; };
+ CD90257411B0C0B500519439 /* OAConsumer.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90254311B0C0B500519439 /* OAConsumer.m */; };
+ CD90257511B0C0B500519439 /* OADataFetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90254511B0C0B500519439 /* OADataFetcher.m */; };
+ CD90257611B0C0B500519439 /* OAMutableURLRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90254711B0C0B500519439 /* OAMutableURLRequest.m */; };
+ CD90257711B0C0B500519439 /* OARequestParameter.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90254911B0C0B500519439 /* OARequestParameter.m */; };
+ CD90257811B0C0B500519439 /* OAServiceTicket.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90254B11B0C0B500519439 /* OAServiceTicket.m */; };
+ CD90257911B0C0B500519439 /* OAToken.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90254D11B0C0B500519439 /* OAToken.m */; };
+ CD90257A11B0C0B500519439 /* OAToken_KeychainExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90254F11B0C0B500519439 /* OAToken_KeychainExtensions.m */; };
+ CD90257B11B0C0B500519439 /* OAHMAC_SHA1SignatureProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90255211B0C0B500519439 /* OAHMAC_SHA1SignatureProvider.m */; };
+ CD90257C11B0C0B500519439 /* OAPlaintextSignatureProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90255411B0C0B500519439 /* OAPlaintextSignatureProvider.m */; };
+ CD90258011B0C0B500519439 /* CDataScanner.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90255F11B0C0B500519439 /* CDataScanner.m */; };
+ CD90258111B0C0B500519439 /* CDataScanner_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90256211B0C0B500519439 /* CDataScanner_Extensions.m */; };
+ CD90258211B0C0B500519439 /* NSCharacterSet_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90256411B0C0B500519439 /* NSCharacterSet_Extensions.m */; };
+ CD90258311B0C0B500519439 /* NSDictionary_JSONExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90256611B0C0B500519439 /* NSDictionary_JSONExtensions.m */; };
+ CD90258411B0C0B500519439 /* CJSONDeserializer.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90256911B0C0B500519439 /* CJSONDeserializer.m */; };
+ CD90258511B0C0B500519439 /* CJSONScanner.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90256B11B0C0B500519439 /* CJSONScanner.m */; };
+ CD90258611B0C0B500519439 /* CJSONSerializer.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90256D11B0C0B500519439 /* CJSONSerializer.m */; };
+ CD9025D911B1438600519439 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD9025D811B1438600519439 /* Security.framework */; };
+ CD90260B11B14D2400519439 /* OSProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90260A11B14D2400519439 /* OSProvider.m */; };
+ CD90260F11B14DD300519439 /* OSConsumer.m in Sources */ = {isa = PBXBuildFile; fileRef = CD90260E11B14DD300519439 /* OSConsumer.m */; };
+ CDA8E3C011BD323500B53FCF /* ActivitiesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CDA8E3BF11BD323500B53FCF /* ActivitiesViewController.m */; };
+ CDA8E3CE11BD32F500B53FCF /* ATutorHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = CDA8E3CD11BD32F500B53FCF /* ATutorHelper.m */; };
+ CDDEEEB4120F2C240016E33F /* GroupsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CDDEEEB3120F2C240016E33F /* GroupsViewController.m */; };
+ CDE2828711ABAB8B00A7F0EE /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDE2828611ABAB8B00A7F0EE /* QuartzCore.framework */; };
+ CDE2832011ABAF5100A7F0EE /* LauncherViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CDE2831F11ABAF5100A7F0EE /* LauncherViewController.m */; };
+ CDE2834811ABB0A500A7F0EE /* StyleSheet.m in Sources */ = {isa = PBXBuildFile; fileRef = CDE2834711ABB0A500A7F0EE /* StyleSheet.m */; };
+ CDE2836111ABB71F00A7F0EE /* Activities.png in Resources */ = {isa = PBXBuildFile; fileRef = CDE2835D11ABB71F00A7F0EE /* Activities.png */; };
+ CDE2836211ABB71F00A7F0EE /* Contacts.png in Resources */ = {isa = PBXBuildFile; fileRef = CDE2835E11ABB71F00A7F0EE /* Contacts.png */; };
+ CDE2836311ABB71F00A7F0EE /* Gadgets.png in Resources */ = {isa = PBXBuildFile; fileRef = CDE2835F11ABB71F00A7F0EE /* Gadgets.png */; };
+ CDE2836411ABB71F00A7F0EE /* Groups.png in Resources */ = {isa = PBXBuildFile; fileRef = CDE2836011ABB71F00A7F0EE /* Groups.png */; };
+ CDF0DEE611DF6F9000B2500F /* Contact.m in Sources */ = {isa = PBXBuildFile; fileRef = CDF0DEE511DF6F9000B2500F /* Contact.m */; };
+ CDF0DF0111DF72A100B2500F /* ContactsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CDF0DF0011DF72A100B2500F /* ContactsViewController.m */; };
+ CDF0E03511DF7E5300B2500F /* libThree20.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF0DFDF11DF7E1900B2500F /* libThree20.a */; };
+ CDF0E03611DF7E5400B2500F /* libThree20Core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF0E00A11DF7E4100B2500F /* libThree20Core.a */; };
+ CDF0E03711DF7E5400B2500F /* libThree20Network.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF0E01211DF7E4100B2500F /* libThree20Network.a */; };
+ CDF0E03811DF7E5500B2500F /* libThree20Style.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF0E01A11DF7E4100B2500F /* libThree20Style.a */; };
+ CDF0E03911DF7E5500B2500F /* libThree20UI.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF0E03211DF7E4100B2500F /* libThree20UI.a */; };
+ CDF0E03A11DF7E5900B2500F /* libThree20UICommon.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF0E02211DF7E4100B2500F /* libThree20UICommon.a */; };
+ CDF0E03B11DF7E5900B2500F /* libThree20UINavigator.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF0E02A11DF7E4100B2500F /* libThree20UINavigator.a */; };
+ CDF0E05111DF7EAC00B2500F /* Three20.bundle in Resources */ = {isa = PBXBuildFile; fileRef = CDF0E05011DF7EAC00B2500F /* Three20.bundle */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ CDF0DFDE11DF7E1900B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0DFB111DF7E1900B2500F /* Three20.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = BEF31F3A0F352DF5000DE5D2;
+ remoteInfo = Three20;
+ };
+ CDF0DFE011DF7E1900B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0DFB111DF7E1900B2500F /* Three20.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = EB9E6C6210B6A8F800DE563C;
+ remoteInfo = UnitTests;
+ };
+ CDF0E00911DF7E4100B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0DFF311DF7E4100B2500F /* Three20Core.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = BEF31F3A0F352DF5000DE5D2;
+ remoteInfo = Three20Core;
+ };
+ CDF0E00B11DF7E4100B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0DFF311DF7E4100B2500F /* Three20Core.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = EB9E6C6210B6A8F800DE563C;
+ remoteInfo = UnitTests;
+ };
+ CDF0E01111DF7E4100B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0DFF611DF7E4100B2500F /* Three20Network.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = BEF31F3A0F352DF5000DE5D2;
+ remoteInfo = Three20Network;
+ };
+ CDF0E01311DF7E4100B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0DFF611DF7E4100B2500F /* Three20Network.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = EB9E6C6210B6A8F800DE563C;
+ remoteInfo = UnitTests;
+ };
+ CDF0E01911DF7E4100B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0DFF911DF7E4100B2500F /* Three20Style.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = BEF31F3A0F352DF5000DE5D2;
+ remoteInfo = Three20Style;
+ };
+ CDF0E01B11DF7E4100B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0DFF911DF7E4100B2500F /* Three20Style.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = EB9E6C6210B6A8F800DE563C;
+ remoteInfo = UnitTests;
+ };
+ CDF0E02111DF7E4100B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0DFFC11DF7E4100B2500F /* Three20UICommon.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = BEF31F3A0F352DF5000DE5D2;
+ remoteInfo = Three20UICommon;
+ };
+ CDF0E02311DF7E4100B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0DFFC11DF7E4100B2500F /* Three20UICommon.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = EB9E6C6210B6A8F800DE563C;
+ remoteInfo = UnitTests;
+ };
+ CDF0E02911DF7E4100B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0DFFF11DF7E4100B2500F /* Three20UINavigator.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = BEF31F3A0F352DF5000DE5D2;
+ remoteInfo = Three20UINavigator;
+ };
+ CDF0E02B11DF7E4100B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0DFFF11DF7E4100B2500F /* Three20UINavigator.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = EB9E6C6210B6A8F800DE563C;
+ remoteInfo = UnitTests;
+ };
+ CDF0E03111DF7E4100B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0E00211DF7E4100B2500F /* Three20UI.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = BEF31F3A0F352DF5000DE5D2;
+ remoteInfo = Three20UI;
+ };
+ CDF0E03311DF7E4100B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0E00211DF7E4100B2500F /* Three20UI.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = EB9E6C6210B6A8F800DE563C;
+ remoteInfo = UnitTests;
+ };
+ CDF0E04211DF7E8D00B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0DFF311DF7E4100B2500F /* Three20Core.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = BEF31F390F352DF5000DE5D2;
+ remoteInfo = Three20Core;
+ };
+ CDF0E04411DF7E8D00B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0E00211DF7E4100B2500F /* Three20UI.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = BEF31F390F352DF5000DE5D2;
+ remoteInfo = Three20UI;
+ };
+ CDF0E04611DF7E8D00B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0DFF911DF7E4100B2500F /* Three20Style.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = BEF31F390F352DF5000DE5D2;
+ remoteInfo = Three20Style;
+ };
+ CDF0E04811DF7E8D00B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0DFF611DF7E4100B2500F /* Three20Network.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = BEF31F390F352DF5000DE5D2;
+ remoteInfo = Three20Network;
+ };
+ CDF0E04A11DF7E8D00B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0DFFF11DF7E4100B2500F /* Three20UINavigator.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = BEF31F390F352DF5000DE5D2;
+ remoteInfo = Three20UINavigator;
+ };
+ CDF0E04C11DF7E8D00B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0DFFC11DF7E4100B2500F /* Three20UICommon.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = BEF31F390F352DF5000DE5D2;
+ remoteInfo = Three20UICommon;
+ };
+ CDF0E04E11DF7E8D00B2500F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = CDF0DFB111DF7E1900B2500F /* Three20.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = BEF31F390F352DF5000DE5D2;
+ remoteInfo = Three20;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 1D3623240D0F684500981E51 /* ATutorAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ATutorAppDelegate.h; sourceTree = "<group>"; };
+ 1D3623250D0F684500981E51 /* ATutorAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ATutorAppDelegate.m; sourceTree = "<group>"; };
+ 1D6058910D05DD3D006BFB54 /* ATutor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ATutor.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 288765FC0DF74451002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+ 32CA4F630368D1EE00C91783 /* ATutor_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ATutor_Prefix.pch; sourceTree = "<group>"; };
+ 8D1107310486CEB800E47090 /* ATutor-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "ATutor-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; };
+ CD26D9E311E8D30700003274 /* ContactsDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactsDataSource.h; sourceTree = "<group>"; };
+ CD26D9E411E8D30700003274 /* ContactsDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactsDataSource.m; sourceTree = "<group>"; };
+ CD26DA9A11E8E66800003274 /* ContactItemCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactItemCell.h; sourceTree = "<group>"; };
+ CD26DA9B11E8E66800003274 /* ContactItemCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactItemCell.m; sourceTree = "<group>"; };
+ CD720BDA120B75FB006EC605 /* IASKAppSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKAppSettingsViewController.h; sourceTree = "<group>"; };
+ CD720BDB120B75FB006EC605 /* IASKAppSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKAppSettingsViewController.m; sourceTree = "<group>"; };
+ CD720BDC120B75FB006EC605 /* IASKSpecifierValuesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSpecifierValuesViewController.h; sourceTree = "<group>"; };
+ CD720BDD120B75FB006EC605 /* IASKSpecifierValuesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSpecifierValuesViewController.m; sourceTree = "<group>"; };
+ CD720BDF120B75FB006EC605 /* IASKSettingsReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSettingsReader.h; sourceTree = "<group>"; };
+ CD720BE0120B75FB006EC605 /* IASKSettingsReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSettingsReader.m; sourceTree = "<group>"; };
+ CD720BE1120B75FB006EC605 /* IASKSpecifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSpecifier.h; sourceTree = "<group>"; };
+ CD720BE2120B75FB006EC605 /* IASKSpecifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSpecifier.m; sourceTree = "<group>"; };
+ CD720BE4120B75FB006EC605 /* IASKPSSliderSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSSliderSpecifierViewCell.h; sourceTree = "<group>"; };
+ CD720BE5120B75FB006EC605 /* IASKPSSliderSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSSliderSpecifierViewCell.m; sourceTree = "<group>"; };
+ CD720BE6120B75FB006EC605 /* IASKPSTextFieldSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSTextFieldSpecifierViewCell.h; sourceTree = "<group>"; };
+ CD720BE7120B75FB006EC605 /* IASKPSTextFieldSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSTextFieldSpecifierViewCell.m; sourceTree = "<group>"; };
+ CD720BE8120B75FB006EC605 /* IASKPSTitleValueSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSTitleValueSpecifierViewCell.h; sourceTree = "<group>"; };
+ CD720BE9120B75FB006EC605 /* IASKPSTitleValueSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSTitleValueSpecifierViewCell.m; sourceTree = "<group>"; };
+ CD720BEA120B75FB006EC605 /* IASKPSToggleSwitchSpecifierViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKPSToggleSwitchSpecifierViewCell.h; sourceTree = "<group>"; };
+ CD720BEB120B75FB006EC605 /* IASKPSToggleSwitchSpecifierViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKPSToggleSwitchSpecifierViewCell.m; sourceTree = "<group>"; };
+ CD720BEC120B75FB006EC605 /* IASKSlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSlider.h; sourceTree = "<group>"; };
+ CD720BED120B75FB006EC605 /* IASKSlider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSlider.m; sourceTree = "<group>"; };
+ CD720BEE120B75FB006EC605 /* IASKSwitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKSwitch.h; sourceTree = "<group>"; };
+ CD720BEF120B75FB006EC605 /* IASKSwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKSwitch.m; sourceTree = "<group>"; };
+ CD720BF0120B75FB006EC605 /* IASKTextField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IASKTextField.h; sourceTree = "<group>"; };
+ CD720BF1120B75FB006EC605 /* IASKTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IASKTextField.m; sourceTree = "<group>"; };
+ CD720BF3120B75FB006EC605 /* IASKAppSettingsView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IASKAppSettingsView.xib; sourceTree = "<group>"; };
+ CD720BF4120B75FB006EC605 /* IASKPSSliderSpecifierViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IASKPSSliderSpecifierViewCell.xib; sourceTree = "<group>"; };
+ CD720BF5120B75FB006EC605 /* IASKPSTextFieldSpecifierViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IASKPSTextFieldSpecifierViewCell.xib; sourceTree = "<group>"; };
+ CD720BF6120B75FB006EC605 /* IASKPSToggleSwitchSpecifierViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IASKPSToggleSwitchSpecifierViewCell.xib; sourceTree = "<group>"; };
+ CD720BF7120B75FC006EC605 /* IASKSpecifierValuesView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IASKSpecifierValuesView.xib; sourceTree = "<group>"; };
+ CD7A89F21204B60F00140865 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
+ CD8235CA11E3D66A00819570 /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = iphoneos3.1.3/System/Library/Frameworks/AddressBook.framework; sourceTree = "<group>"; };
+ CD8235CC11E3D66A00819570 /* AddressBookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBookUI.framework; path = iphoneos3.1.3/System/Library/Frameworks/AddressBookUI.framework; sourceTree = "<group>"; };
+ CD8235DE11E3DD7500819570 /* ContactViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactViewController.h; sourceTree = "<group>"; };
+ CD8235DF11E3DD7500819570 /* ContactViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactViewController.m; sourceTree = "<group>"; };
+ CD8F0EF011B2CFCF00D38970 /* QAWebController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QAWebController.h; sourceTree = "<group>"; };
+ CD8F0EF111B2CFCF00D38970 /* QAWebController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QAWebController.m; sourceTree = "<group>"; };
+ CD8F0F7011B2D79A00D38970 /* CommonFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonFunctions.h; sourceTree = "<group>"; };
+ CD8F0F7111B2D79A00D38970 /* CommonFunctions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CommonFunctions.m; sourceTree = "<group>"; };
+ CD8F0F7D11B2D7A600D38970 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
+ CD90253311B0C0B500519439 /* SFHFKeychainUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SFHFKeychainUtils.h; sourceTree = "<group>"; };
+ CD90253411B0C0B500519439 /* SFHFKeychainUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SFHFKeychainUtils.m; sourceTree = "<group>"; };
+ CD90253711B0C0B500519439 /* Base64Transcoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Base64Transcoder.c; sourceTree = "<group>"; };
+ CD90253811B0C0B500519439 /* Base64Transcoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Base64Transcoder.h; sourceTree = "<group>"; };
+ CD90253911B0C0B500519439 /* hmac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hmac.c; sourceTree = "<group>"; };
+ CD90253A11B0C0B500519439 /* hmac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hmac.h; sourceTree = "<group>"; };
+ CD90253B11B0C0B500519439 /* sha1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sha1.c; sourceTree = "<group>"; };
+ CD90253C11B0C0B500519439 /* sha1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha1.h; sourceTree = "<group>"; };
+ CD90253E11B0C0B500519439 /* NSString+URLEncoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+URLEncoding.h"; sourceTree = "<group>"; };
+ CD90253F11B0C0B500519439 /* NSString+URLEncoding.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+URLEncoding.m"; sourceTree = "<group>"; };
+ CD90254011B0C0B500519439 /* OAAsynchronousDataFetcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAAsynchronousDataFetcher.h; sourceTree = "<group>"; };
+ CD90254111B0C0B500519439 /* OAAsynchronousDataFetcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAAsynchronousDataFetcher.m; sourceTree = "<group>"; };
+ CD90254211B0C0B500519439 /* OAConsumer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAConsumer.h; sourceTree = "<group>"; };
+ CD90254311B0C0B500519439 /* OAConsumer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAConsumer.m; sourceTree = "<group>"; };
+ CD90254411B0C0B500519439 /* OADataFetcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OADataFetcher.h; sourceTree = "<group>"; };
+ CD90254511B0C0B500519439 /* OADataFetcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OADataFetcher.m; sourceTree = "<group>"; };
+ CD90254611B0C0B500519439 /* OAMutableURLRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAMutableURLRequest.h; sourceTree = "<group>"; };
+ CD90254711B0C0B500519439 /* OAMutableURLRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAMutableURLRequest.m; sourceTree = "<group>"; };
+ CD90254811B0C0B500519439 /* OARequestParameter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OARequestParameter.h; sourceTree = "<group>"; };
+ CD90254911B0C0B500519439 /* OARequestParameter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OARequestParameter.m; sourceTree = "<group>"; };
+ CD90254A11B0C0B500519439 /* OAServiceTicket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAServiceTicket.h; sourceTree = "<group>"; };
+ CD90254B11B0C0B500519439 /* OAServiceTicket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAServiceTicket.m; sourceTree = "<group>"; };
+ CD90254C11B0C0B500519439 /* OAToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAToken.h; sourceTree = "<group>"; };
+ CD90254D11B0C0B500519439 /* OAToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAToken.m; sourceTree = "<group>"; };
+ CD90254E11B0C0B500519439 /* OAToken_KeychainExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAToken_KeychainExtensions.h; sourceTree = "<group>"; };
+ CD90254F11B0C0B500519439 /* OAToken_KeychainExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAToken_KeychainExtensions.m; sourceTree = "<group>"; };
+ CD90255111B0C0B500519439 /* OAHMAC_SHA1SignatureProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAHMAC_SHA1SignatureProvider.h; sourceTree = "<group>"; };
+ CD90255211B0C0B500519439 /* OAHMAC_SHA1SignatureProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAHMAC_SHA1SignatureProvider.m; sourceTree = "<group>"; };
+ CD90255311B0C0B500519439 /* OAPlaintextSignatureProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAPlaintextSignatureProvider.h; sourceTree = "<group>"; };
+ CD90255411B0C0B500519439 /* OAPlaintextSignatureProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAPlaintextSignatureProvider.m; sourceTree = "<group>"; };
+ CD90255511B0C0B500519439 /* OASignatureProviding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OASignatureProviding.h; sourceTree = "<group>"; };
+ CD90255E11B0C0B500519439 /* CDataScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDataScanner.h; sourceTree = "<group>"; };
+ CD90255F11B0C0B500519439 /* CDataScanner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDataScanner.m; sourceTree = "<group>"; };
+ CD90256111B0C0B500519439 /* CDataScanner_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDataScanner_Extensions.h; sourceTree = "<group>"; };
+ CD90256211B0C0B500519439 /* CDataScanner_Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDataScanner_Extensions.m; sourceTree = "<group>"; };
+ CD90256311B0C0B500519439 /* NSCharacterSet_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSCharacterSet_Extensions.h; sourceTree = "<group>"; };
+ CD90256411B0C0B500519439 /* NSCharacterSet_Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSCharacterSet_Extensions.m; sourceTree = "<group>"; };
+ CD90256511B0C0B500519439 /* NSDictionary_JSONExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSDictionary_JSONExtensions.h; sourceTree = "<group>"; };
+ CD90256611B0C0B500519439 /* NSDictionary_JSONExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSDictionary_JSONExtensions.m; sourceTree = "<group>"; };
+ CD90256811B0C0B500519439 /* CJSONDeserializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CJSONDeserializer.h; sourceTree = "<group>"; };
+ CD90256911B0C0B500519439 /* CJSONDeserializer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CJSONDeserializer.m; sourceTree = "<group>"; };
+ CD90256A11B0C0B500519439 /* CJSONScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CJSONScanner.h; sourceTree = "<group>"; };
+ CD90256B11B0C0B500519439 /* CJSONScanner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CJSONScanner.m; sourceTree = "<group>"; };
+ CD90256C11B0C0B500519439 /* CJSONSerializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CJSONSerializer.h; sourceTree = "<group>"; };
+ CD90256D11B0C0B500519439 /* CJSONSerializer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CJSONSerializer.m; sourceTree = "<group>"; };
+ CD9025D811B1438600519439 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
+ CD90260911B14D2400519439 /* OSProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSProvider.h; sourceTree = "<group>"; };
+ CD90260A11B14D2400519439 /* OSProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OSProvider.m; sourceTree = "<group>"; };
+ CD90260D11B14DD300519439 /* OSConsumer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSConsumer.h; sourceTree = "<group>"; };
+ CD90260E11B14DD300519439 /* OSConsumer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OSConsumer.m; sourceTree = "<group>"; };
+ CDA8E3BE11BD323500B53FCF /* ActivitiesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActivitiesViewController.h; sourceTree = "<group>"; };
+ CDA8E3BF11BD323500B53FCF /* ActivitiesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ActivitiesViewController.m; sourceTree = "<group>"; };
+ CDA8E3CC11BD32F500B53FCF /* ATutorHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ATutorHelper.h; sourceTree = "<group>"; };
+ CDA8E3CD11BD32F500B53FCF /* ATutorHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ATutorHelper.m; sourceTree = "<group>"; };
+ CDDEEEB2120F2C240016E33F /* GroupsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GroupsViewController.h; sourceTree = "<group>"; };
+ CDDEEEB3120F2C240016E33F /* GroupsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GroupsViewController.m; sourceTree = "<group>"; };
+ CDE2828611ABAB8B00A7F0EE /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+ CDE2831E11ABAF5100A7F0EE /* LauncherViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LauncherViewController.h; sourceTree = "<group>"; };
+ CDE2831F11ABAF5100A7F0EE /* LauncherViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LauncherViewController.m; sourceTree = "<group>"; };
+ CDE2834611ABB0A500A7F0EE /* StyleSheet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleSheet.h; sourceTree = "<group>"; };
+ CDE2834711ABB0A500A7F0EE /* StyleSheet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StyleSheet.m; sourceTree = "<group>"; };
+ CDE2835D11ABB71F00A7F0EE /* Activities.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Activities.png; sourceTree = "<group>"; };
+ CDE2835E11ABB71F00A7F0EE /* Contacts.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Contacts.png; sourceTree = "<group>"; };
+ CDE2835F11ABB71F00A7F0EE /* Gadgets.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Gadgets.png; sourceTree = "<group>"; };
+ CDE2836011ABB71F00A7F0EE /* Groups.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Groups.png; sourceTree = "<group>"; };
+ CDF0DEE411DF6F9000B2500F /* Contact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Contact.h; sourceTree = "<group>"; };
+ CDF0DEE511DF6F9000B2500F /* Contact.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Contact.m; sourceTree = "<group>"; };
+ CDF0DEFF11DF72A100B2500F /* ContactsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactsViewController.h; sourceTree = "<group>"; };
+ CDF0DF0011DF72A100B2500F /* ContactsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactsViewController.m; sourceTree = "<group>"; };
+ CDF0DFB111DF7E1900B2500F /* Three20.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Three20.xcodeproj; path = three20/src/Three20/Three20.xcodeproj; sourceTree = SOURCE_ROOT; };
+ CDF0DFF311DF7E4100B2500F /* Three20Core.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Three20Core.xcodeproj; path = three20/src/Three20Core/Three20Core.xcodeproj; sourceTree = SOURCE_ROOT; };
+ CDF0DFF611DF7E4100B2500F /* Three20Network.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Three20Network.xcodeproj; path = three20/src/Three20Network/Three20Network.xcodeproj; sourceTree = SOURCE_ROOT; };
+ CDF0DFF911DF7E4100B2500F /* Three20Style.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Three20Style.xcodeproj; path = three20/src/Three20Style/Three20Style.xcodeproj; sourceTree = SOURCE_ROOT; };
+ CDF0DFFC11DF7E4100B2500F /* Three20UICommon.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Three20UICommon.xcodeproj; path = three20/src/Three20UICommon/Three20UICommon.xcodeproj; sourceTree = SOURCE_ROOT; };
+ CDF0DFFF11DF7E4100B2500F /* Three20UINavigator.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Three20UINavigator.xcodeproj; path = three20/src/Three20UINavigator/Three20UINavigator.xcodeproj; sourceTree = SOURCE_ROOT; };
+ CDF0E00211DF7E4100B2500F /* Three20UI.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Three20UI.xcodeproj; path = three20/src/Three20UI/Three20UI.xcodeproj; sourceTree = SOURCE_ROOT; };
+ CDF0E05011DF7EAC00B2500F /* Three20.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = Three20.bundle; path = three20/src/Three20.bundle; sourceTree = SOURCE_ROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 1D60588F0D05DD3D006BFB54 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */,
+ 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */,
+ 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */,
+ CDE2828711ABAB8B00A7F0EE /* QuartzCore.framework in Frameworks */,
+ CD9025D911B1438600519439 /* Security.framework in Frameworks */,
+ CD8F0F7E11B2D7A600D38970 /* SystemConfiguration.framework in Frameworks */,
+ CDF0E03511DF7E5300B2500F /* libThree20.a in Frameworks */,
+ CDF0E03611DF7E5400B2500F /* libThree20Core.a in Frameworks */,
+ CDF0E03711DF7E5400B2500F /* libThree20Network.a in Frameworks */,
+ CDF0E03811DF7E5500B2500F /* libThree20Style.a in Frameworks */,
+ CDF0E03911DF7E5500B2500F /* libThree20UI.a in Frameworks */,
+ CDF0E03A11DF7E5900B2500F /* libThree20UICommon.a in Frameworks */,
+ CDF0E03B11DF7E5900B2500F /* libThree20UINavigator.a in Frameworks */,
+ CD8235CB11E3D66A00819570 /* AddressBook.framework in Frameworks */,
+ CD8235CD11E3D66A00819570 /* AddressBookUI.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 080E96DDFE201D6D7F000001 /* Classes */ = {
+ isa = PBXGroup;
+ children = (
+ 1D3623240D0F684500981E51 /* ATutorAppDelegate.h */,
+ 1D3623250D0F684500981E51 /* ATutorAppDelegate.m */,
+ CDE2831D11ABAF3B00A7F0EE /* View Controllers & Stuff */,
+ CD90260C11B14D2C00519439 /* Models */,
+ CDA8E3CB11BD32E700B53FCF /* Helpers */,
+ CDE2834511ABB09400A7F0EE /* Miscellaneous */,
+ );
+ path = Classes;
+ sourceTree = "<group>";
+ };
+ 19C28FACFE9D520D11CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 1D6058910D05DD3D006BFB54 /* ATutor.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
+ isa = PBXGroup;
+ children = (
+ 080E96DDFE201D6D7F000001 /* Classes */,
+ 29B97315FDCFA39411CA2CEA /* Other Sources */,
+ 29B97317FDCFA39411CA2CEA /* Resources */,
+ 29B97323FDCFA39411CA2CEA /* Frameworks */,
+ 19C28FACFE9D520D11CA2CBB /* Products */,
+ );
+ name = CustomTemplate;
+ sourceTree = "<group>";
+ };
+ 29B97315FDCFA39411CA2CEA /* Other Sources */ = {
+ isa = PBXGroup;
+ children = (
+ CD720BD8120B75FB006EC605 /* InAppSettingsKit */,
+ CD90253211B0C0B500519439 /* KeychainUtils */,
+ CD90253511B0C0B500519439 /* OAuth */,
+ CD90255D11B0C0B500519439 /* TouchJSON */,
+ CDE2822A11ABAB4D00A7F0EE /* three20 */,
+ 32CA4F630368D1EE00C91783 /* ATutor_Prefix.pch */,
+ 29B97316FDCFA39411CA2CEA /* main.m */,
+ );
+ name = "Other Sources";
+ sourceTree = "<group>";
+ };
+ 29B97317FDCFA39411CA2CEA /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ CD7A89F21204B60F00140865 /* Settings.bundle */,
+ CDE2835B11ABB70100A7F0EE /* Graphics */,
+ 8D1107310486CEB800E47090 /* ATutor-Info.plist */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ 29B97323FDCFA39411CA2CEA /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ CD8235CA11E3D66A00819570 /* AddressBook.framework */,
+ CD8235CC11E3D66A00819570 /* AddressBookUI.framework */,
+ CD8F0F7D11B2D7A600D38970 /* SystemConfiguration.framework */,
+ CD9025D811B1438600519439 /* Security.framework */,
+ CDE2828611ABAB8B00A7F0EE /* QuartzCore.framework */,
+ 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */,
+ 1D30AB110D05D00D00671497 /* Foundation.framework */,
+ 288765FC0DF74451002DB57D /* CoreGraphics.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ CD26D9DF11E8D2C900003274 /* Contacts */ = {
+ isa = PBXGroup;
+ children = (
+ CDF0DEFF11DF72A100B2500F /* ContactsViewController.h */,
+ CDF0DF0011DF72A100B2500F /* ContactsViewController.m */,
+ CD8235DE11E3DD7500819570 /* ContactViewController.h */,
+ CD8235DF11E3DD7500819570 /* ContactViewController.m */,
+ CD26D9E311E8D30700003274 /* ContactsDataSource.h */,
+ CD26D9E411E8D30700003274 /* ContactsDataSource.m */,
+ CD26DA9A11E8E66800003274 /* ContactItemCell.h */,
+ CD26DA9B11E8E66800003274 /* ContactItemCell.m */,
+ );
+ name = Contacts;
+ sourceTree = "<group>";
+ };
+ CD26D9E011E8D2CE00003274 /* Activities */ = {
+ isa = PBXGroup;
+ children = (
+ CDA8E3BE11BD323500B53FCF /* ActivitiesViewController.h */,
+ CDA8E3BF11BD323500B53FCF /* ActivitiesViewController.m */,
+ );
+ name = Activities;
+ sourceTree = "<group>";
+ };
+ CD26D9E111E8D2DB00003274 /* Generic */ = {
+ isa = PBXGroup;
+ children = (
+ CD8F0EF011B2CFCF00D38970 /* QAWebController.h */,
+ CD8F0EF111B2CFCF00D38970 /* QAWebController.m */,
+ CDE2831E11ABAF5100A7F0EE /* LauncherViewController.h */,
+ CDE2831F11ABAF5100A7F0EE /* LauncherViewController.m */,
+ );
+ name = Generic;
+ sourceTree = "<group>";
+ };
+ CD720BD8120B75FB006EC605 /* InAppSettingsKit */ = {
+ isa = PBXGroup;
+ children = (
+ CD720BD9120B75FB006EC605 /* Controllers */,
+ CD720BDE120B75FB006EC605 /* Models */,
+ CD720BE3120B75FB006EC605 /* Views */,
+ CD720BF2120B75FB006EC605 /* Xibs */,
+ );
+ path = InAppSettingsKit;
+ sourceTree = "<group>";
+ };
+ CD720BD9120B75FB006EC605 /* Controllers */ = {
+ isa = PBXGroup;
+ children = (
+ CD720BDA120B75FB006EC605 /* IASKAppSettingsViewController.h */,
+ CD720BDB120B75FB006EC605 /* IASKAppSettingsViewController.m */,
+ CD720BDC120B75FB006EC605 /* IASKSpecifierValuesViewController.h */,
+ CD720BDD120B75FB006EC605 /* IASKSpecifierValuesViewController.m */,
+ );
+ path = Controllers;
+ sourceTree = "<group>";
+ };
+ CD720BDE120B75FB006EC605 /* Models */ = {
+ isa = PBXGroup;
+ children = (
+ CD720BDF120B75FB006EC605 /* IASKSettingsReader.h */,
+ CD720BE0120B75FB006EC605 /* IASKSettingsReader.m */,
+ CD720BE1120B75FB006EC605 /* IASKSpecifier.h */,
+ CD720BE2120B75FB006EC605 /* IASKSpecifier.m */,
+ );
+ path = Models;
+ sourceTree = "<group>";
+ };
+ CD720BE3120B75FB006EC605 /* Views */ = {
+ isa = PBXGroup;
+ children = (
+ CD720BE4120B75FB006EC605 /* IASKPSSliderSpecifierViewCell.h */,
+ CD720BE5120B75FB006EC605 /* IASKPSSliderSpecifierViewCell.m */,
+ CD720BE6120B75FB006EC605 /* IASKPSTextFieldSpecifierViewCell.h */,
+ CD720BE7120B75FB006EC605 /* IASKPSTextFieldSpecifierViewCell.m */,
+ CD720BE8120B75FB006EC605 /* IASKPSTitleValueSpecifierViewCell.h */,
+ CD720BE9120B75FB006EC605 /* IASKPSTitleValueSpecifierViewCell.m */,
+ CD720BEA120B75FB006EC605 /* IASKPSToggleSwitchSpecifierViewCell.h */,
+ CD720BEB120B75FB006EC605 /* IASKPSToggleSwitchSpecifierViewCell.m */,
+ CD720BEC120B75FB006EC605 /* IASKSlider.h */,
+ CD720BED120B75FB006EC605 /* IASKSlider.m */,
+ CD720BEE120B75FB006EC605 /* IASKSwitch.h */,
+ CD720BEF120B75FB006EC605 /* IASKSwitch.m */,
+ CD720BF0120B75FB006EC605 /* IASKTextField.h */,
+ CD720BF1120B75FB006EC605 /* IASKTextField.m */,
+ );
+ path = Views;
+ sourceTree = "<group>";
+ };
+ CD720BF2120B75FB006EC605 /* Xibs */ = {
+ isa = PBXGroup;
+ children = (
+ CD720BF3120B75FB006EC605 /* IASKAppSettingsView.xib */,
+ CD720BF4120B75FB006EC605 /* IASKPSSliderSpecifierViewCell.xib */,
+ CD720BF5120B75FB006EC605 /* IASKPSTextFieldSpecifierViewCell.xib */,
+ CD720BF6120B75FB006EC605 /* IASKPSToggleSwitchSpecifierViewCell.xib */,
+ CD720BF7120B75FC006EC605 /* IASKSpecifierValuesView.xib */,
+ );
+ path = Xibs;
+ sourceTree = "<group>";
+ };
+ CD90253211B0C0B500519439 /* KeychainUtils */ = {
+ isa = PBXGroup;
+ children = (
+ CD90253311B0C0B500519439 /* SFHFKeychainUtils.h */,
+ CD90253411B0C0B500519439 /* SFHFKeychainUtils.m */,
+ );
+ path = KeychainUtils;
+ sourceTree = "<group>";
+ };
+ CD90253511B0C0B500519439 /* OAuth */ = {
+ isa = PBXGroup;
+ children = (
+ CD90253611B0C0B500519439 /* Crypto */,
+ CD90253D11B0C0B500519439 /* Extensions */,
+ CD90254011B0C0B500519439 /* OAAsynchronousDataFetcher.h */,
+ CD90254111B0C0B500519439 /* OAAsynchronousDataFetcher.m */,
+ CD90254211B0C0B500519439 /* OAConsumer.h */,
+ CD90254311B0C0B500519439 /* OAConsumer.m */,
+ CD90254411B0C0B500519439 /* OADataFetcher.h */,
+ CD90254511B0C0B500519439 /* OADataFetcher.m */,
+ CD90254611B0C0B500519439 /* OAMutableURLRequest.h */,
+ CD90254711B0C0B500519439 /* OAMutableURLRequest.m */,
+ CD90254811B0C0B500519439 /* OARequestParameter.h */,
+ CD90254911B0C0B500519439 /* OARequestParameter.m */,
+ CD90254A11B0C0B500519439 /* OAServiceTicket.h */,
+ CD90254B11B0C0B500519439 /* OAServiceTicket.m */,
+ CD90254C11B0C0B500519439 /* OAToken.h */,
+ CD90254D11B0C0B500519439 /* OAToken.m */,
+ CD90254E11B0C0B500519439 /* OAToken_KeychainExtensions.h */,
+ CD90254F11B0C0B500519439 /* OAToken_KeychainExtensions.m */,
+ CD90255011B0C0B500519439 /* Signature Providers */,
+ );
+ path = OAuth;
+ sourceTree = "<group>";
+ };
+ CD90253611B0C0B500519439 /* Crypto */ = {
+ isa = PBXGroup;
+ children = (
+ CD90253711B0C0B500519439 /* Base64Transcoder.c */,
+ CD90253811B0C0B500519439 /* Base64Transcoder.h */,
+ CD90253911B0C0B500519439 /* hmac.c */,
+ CD90253A11B0C0B500519439 /* hmac.h */,
+ CD90253B11B0C0B500519439 /* sha1.c */,
+ CD90253C11B0C0B500519439 /* sha1.h */,
+ );
+ path = Crypto;
+ sourceTree = "<group>";
+ };
+ CD90253D11B0C0B500519439 /* Extensions */ = {
+ isa = PBXGroup;
+ children = (
+ CD90253E11B0C0B500519439 /* NSString+URLEncoding.h */,
+ CD90253F11B0C0B500519439 /* NSString+URLEncoding.m */,
+ );
+ path = Extensions;
+ sourceTree = "<group>";
+ };
+ CD90255011B0C0B500519439 /* Signature Providers */ = {
+ isa = PBXGroup;
+ children = (
+ CD90255111B0C0B500519439 /* OAHMAC_SHA1SignatureProvider.h */,
+ CD90255211B0C0B500519439 /* OAHMAC_SHA1SignatureProvider.m */,
+ CD90255311B0C0B500519439 /* OAPlaintextSignatureProvider.h */,
+ CD90255411B0C0B500519439 /* OAPlaintextSignatureProvider.m */,
+ CD90255511B0C0B500519439 /* OASignatureProviding.h */,
+ );
+ path = "Signature Providers";
+ sourceTree = "<group>";
+ };
+ CD90255D11B0C0B500519439 /* TouchJSON */ = {
+ isa = PBXGroup;
+ children = (
+ CD90255E11B0C0B500519439 /* CDataScanner.h */,
+ CD90255F11B0C0B500519439 /* CDataScanner.m */,
+ CD90256011B0C0B500519439 /* Extensions */,
+ CD90256711B0C0B500519439 /* JSON */,
+ );
+ path = TouchJSON;
+ sourceTree = "<group>";
+ };
+ CD90256011B0C0B500519439 /* Extensions */ = {
+ isa = PBXGroup;
+ children = (
+ CD90256111B0C0B500519439 /* CDataScanner_Extensions.h */,
+ CD90256211B0C0B500519439 /* CDataScanner_Extensions.m */,
+ CD90256311B0C0B500519439 /* NSCharacterSet_Extensions.h */,
+ CD90256411B0C0B500519439 /* NSCharacterSet_Extensions.m */,
+ CD90256511B0C0B500519439 /* NSDictionary_JSONExtensions.h */,
+ CD90256611B0C0B500519439 /* NSDictionary_JSONExtensions.m */,
+ );
+ path = Extensions;
+ sourceTree = "<group>";
+ };
+ CD90256711B0C0B500519439 /* JSON */ = {
+ isa = PBXGroup;
+ children = (
+ CD90256811B0C0B500519439 /* CJSONDeserializer.h */,
+ CD90256911B0C0B500519439 /* CJSONDeserializer.m */,
+ CD90256A11B0C0B500519439 /* CJSONScanner.h */,
+ CD90256B11B0C0B500519439 /* CJSONScanner.m */,
+ CD90256C11B0C0B500519439 /* CJSONSerializer.h */,
+ CD90256D11B0C0B500519439 /* CJSONSerializer.m */,
+ );
+ path = JSON;
+ sourceTree = "<group>";
+ };
+ CD90260C11B14D2C00519439 /* Models */ = {
+ isa = PBXGroup;
+ children = (
+ CD90260911B14D2400519439 /* OSProvider.h */,
+ CD90260A11B14D2400519439 /* OSProvider.m */,
+ CD90260D11B14DD300519439 /* OSConsumer.h */,
+ CD90260E11B14DD300519439 /* OSConsumer.m */,
+ CDF0DEE411DF6F9000B2500F /* Contact.h */,
+ CDF0DEE511DF6F9000B2500F /* Contact.m */,
+ );
+ name = Models;
+ sourceTree = "<group>";
+ };
+ CDA8E3CB11BD32E700B53FCF /* Helpers */ = {
+ isa = PBXGroup;
+ children = (
+ CDA8E3CC11BD32F500B53FCF /* ATutorHelper.h */,
+ CDA8E3CD11BD32F500B53FCF /* ATutorHelper.m */,
+ );
+ name = Helpers;
+ sourceTree = "<group>";
+ };
+ CDDEEEB1120F2C110016E33F /* Groups */ = {
+ isa = PBXGroup;
+ children = (
+ CDDEEEB2120F2C240016E33F /* GroupsViewController.h */,
+ CDDEEEB3120F2C240016E33F /* GroupsViewController.m */,
+ );
+ name = Groups;
+ sourceTree = "<group>";
+ };
+ CDE2822A11ABAB4D00A7F0EE /* three20 */ = {
+ isa = PBXGroup;
+ children = (
+ CDF0E05011DF7EAC00B2500F /* Three20.bundle */,
+ CDF0DFF311DF7E4100B2500F /* Three20Core.xcodeproj */,
+ CDF0DFF611DF7E4100B2500F /* Three20Network.xcodeproj */,
+ CDF0DFF911DF7E4100B2500F /* Three20Style.xcodeproj */,
+ CDF0DFFC11DF7E4100B2500F /* Three20UICommon.xcodeproj */,
+ CDF0DFFF11DF7E4100B2500F /* Three20UINavigator.xcodeproj */,
+ CDF0E00211DF7E4100B2500F /* Three20UI.xcodeproj */,
+ CDF0DFB111DF7E1900B2500F /* Three20.xcodeproj */,
+ );
+ name = three20;
+ sourceTree = "<group>";
+ };
+ CDE2831D11ABAF3B00A7F0EE /* View Controllers & Stuff */ = {
+ isa = PBXGroup;
+ children = (
+ CD26D9E111E8D2DB00003274 /* Generic */,
+ CD26D9E011E8D2CE00003274 /* Activities */,
+ CD26D9DF11E8D2C900003274 /* Contacts */,
+ CDDEEEB1120F2C110016E33F /* Groups */,
+ );
+ name = "View Controllers & Stuff";
+ sourceTree = "<group>";
+ };
+ CDE2834511ABB09400A7F0EE /* Miscellaneous */ = {
+ isa = PBXGroup;
+ children = (
+ CDE2834611ABB0A500A7F0EE /* StyleSheet.h */,
+ CDE2834711ABB0A500A7F0EE /* StyleSheet.m */,
+ CD8F0F7011B2D79A00D38970 /* CommonFunctions.h */,
+ CD8F0F7111B2D79A00D38970 /* CommonFunctions.m */,
+ );
+ name = Miscellaneous;
+ sourceTree = "<group>";
+ };
+ CDE2835B11ABB70100A7F0EE /* Graphics */ = {
+ isa = PBXGroup;
+ children = (
+ CDE2835C11ABB70500A7F0EE /* Launcher Icons */,
+ );
+ name = Graphics;
+ sourceTree = "<group>";
+ };
+ CDE2835C11ABB70500A7F0EE /* Launcher Icons */ = {
+ isa = PBXGroup;
+ children = (
+ CDE2835D11ABB71F00A7F0EE /* Activities.png */,
+ CDE2835E11ABB71F00A7F0EE /* Contacts.png */,
+ CDE2835F11ABB71F00A7F0EE /* Gadgets.png */,
+ CDE2836011ABB71F00A7F0EE /* Groups.png */,
+ );
+ name = "Launcher Icons";
+ sourceTree = "<group>";
+ };
+ CDF0DFDA11DF7E1900B2500F /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ CDF0DFDF11DF7E1900B2500F /* libThree20.a */,
+ CDF0DFE111DF7E1900B2500F /* UnitTests.octest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ CDF0E00511DF7E4100B2500F /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ CDF0E00A11DF7E4100B2500F /* libThree20Core.a */,
+ CDF0E00C11DF7E4100B2500F /* CoreUnitTests.octest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ CDF0E00D11DF7E4100B2500F /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ CDF0E01211DF7E4100B2500F /* libThree20Network.a */,
+ CDF0E01411DF7E4100B2500F /* UnitTests.octest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ CDF0E01511DF7E4100B2500F /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ CDF0E01A11DF7E4100B2500F /* libThree20Style.a */,
+ CDF0E01C11DF7E4100B2500F /* UnitTests.octest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ CDF0E01D11DF7E4100B2500F /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ CDF0E02211DF7E4100B2500F /* libThree20UICommon.a */,
+ CDF0E02411DF7E4100B2500F /* UnitTests.octest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ CDF0E02511DF7E4100B2500F /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ CDF0E02A11DF7E4100B2500F /* libThree20UINavigator.a */,
+ CDF0E02C11DF7E4100B2500F /* UnitTests.octest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ CDF0E02D11DF7E4100B2500F /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ CDF0E03211DF7E4100B2500F /* libThree20UI.a */,
+ CDF0E03411DF7E4100B2500F /* UnitTests.octest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 1D6058900D05DD3D006BFB54 /* ATutor */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "ATutor" */;
+ buildPhases = (
+ 1D60588D0D05DD3D006BFB54 /* Resources */,
+ 1D60588E0D05DD3D006BFB54 /* Sources */,
+ 1D60588F0D05DD3D006BFB54 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ CDF0E04311DF7E8D00B2500F /* PBXTargetDependency */,
+ CDF0E04511DF7E8D00B2500F /* PBXTargetDependency */,
+ CDF0E04711DF7E8D00B2500F /* PBXTargetDependency */,
+ CDF0E04911DF7E8D00B2500F /* PBXTargetDependency */,
+ CDF0E04B11DF7E8D00B2500F /* PBXTargetDependency */,
+ CDF0E04D11DF7E8D00B2500F /* PBXTargetDependency */,
+ CDF0E04F11DF7E8D00B2500F /* PBXTargetDependency */,
+ );
+ name = ATutor;
+ productName = ATutor;
+ productReference = 1D6058910D05DD3D006BFB54 /* ATutor.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 29B97313FDCFA39411CA2CEA /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ATutor" */;
+ compatibilityVersion = "Xcode 3.1";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ );
+ mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
+ projectDirPath = "";
+ projectReferences = (
+ {
+ ProductGroup = CDF0DFDA11DF7E1900B2500F /* Products */;
+ ProjectRef = CDF0DFB111DF7E1900B2500F /* Three20.xcodeproj */;
+ },
+ {
+ ProductGroup = CDF0E00511DF7E4100B2500F /* Products */;
+ ProjectRef = CDF0DFF311DF7E4100B2500F /* Three20Core.xcodeproj */;
+ },
+ {
+ ProductGroup = CDF0E00D11DF7E4100B2500F /* Products */;
+ ProjectRef = CDF0DFF611DF7E4100B2500F /* Three20Network.xcodeproj */;
+ },
+ {
+ ProductGroup = CDF0E01511DF7E4100B2500F /* Products */;
+ ProjectRef = CDF0DFF911DF7E4100B2500F /* Three20Style.xcodeproj */;
+ },
+ {
+ ProductGroup = CDF0E02D11DF7E4100B2500F /* Products */;
+ ProjectRef = CDF0E00211DF7E4100B2500F /* Three20UI.xcodeproj */;
+ },
+ {
+ ProductGroup = CDF0E01D11DF7E4100B2500F /* Products */;
+ ProjectRef = CDF0DFFC11DF7E4100B2500F /* Three20UICommon.xcodeproj */;
+ },
+ {
+ ProductGroup = CDF0E02511DF7E4100B2500F /* Products */;
+ ProjectRef = CDF0DFFF11DF7E4100B2500F /* Three20UINavigator.xcodeproj */;
+ },
+ );
+ projectRoot = "";
+ targets = (
+ 1D6058900D05DD3D006BFB54 /* ATutor */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+ CDF0DFDF11DF7E1900B2500F /* libThree20.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libThree20.a;
+ remoteRef = CDF0DFDE11DF7E1900B2500F /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ CDF0DFE111DF7E1900B2500F /* UnitTests.octest */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.cfbundle;
+ path = UnitTests.octest;
+ remoteRef = CDF0DFE011DF7E1900B2500F /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ CDF0E00A11DF7E4100B2500F /* libThree20Core.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libThree20Core.a;
+ remoteRef = CDF0E00911DF7E4100B2500F /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ CDF0E00C11DF7E4100B2500F /* CoreUnitTests.octest */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.cfbundle;
+ path = CoreUnitTests.octest;
+ remoteRef = CDF0E00B11DF7E4100B2500F /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ CDF0E01211DF7E4100B2500F /* libThree20Network.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libThree20Network.a;
+ remoteRef = CDF0E01111DF7E4100B2500F /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ CDF0E01411DF7E4100B2500F /* UnitTests.octest */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.cfbundle;
+ path = UnitTests.octest;
+ remoteRef = CDF0E01311DF7E4100B2500F /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ CDF0E01A11DF7E4100B2500F /* libThree20Style.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libThree20Style.a;
+ remoteRef = CDF0E01911DF7E4100B2500F /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ CDF0E01C11DF7E4100B2500F /* UnitTests.octest */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.cfbundle;
+ path = UnitTests.octest;
+ remoteRef = CDF0E01B11DF7E4100B2500F /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ CDF0E02211DF7E4100B2500F /* libThree20UICommon.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libThree20UICommon.a;
+ remoteRef = CDF0E02111DF7E4100B2500F /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ CDF0E02411DF7E4100B2500F /* UnitTests.octest */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.cfbundle;
+ path = UnitTests.octest;
+ remoteRef = CDF0E02311DF7E4100B2500F /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ CDF0E02A11DF7E4100B2500F /* libThree20UINavigator.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libThree20UINavigator.a;
+ remoteRef = CDF0E02911DF7E4100B2500F /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ CDF0E02C11DF7E4100B2500F /* UnitTests.octest */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.cfbundle;
+ path = UnitTests.octest;
+ remoteRef = CDF0E02B11DF7E4100B2500F /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ CDF0E03211DF7E4100B2500F /* libThree20UI.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libThree20UI.a;
+ remoteRef = CDF0E03111DF7E4100B2500F /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ CDF0E03411DF7E4100B2500F /* UnitTests.octest */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.cfbundle;
+ path = UnitTests.octest;
+ remoteRef = CDF0E03311DF7E4100B2500F /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+/* End PBXReferenceProxy section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 1D60588D0D05DD3D006BFB54 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ CDE2836111ABB71F00A7F0EE /* Activities.png in Resources */,
+ CDE2836211ABB71F00A7F0EE /* Contacts.png in Resources */,
+ CDE2836311ABB71F00A7F0EE /* Gadgets.png in Resources */,
+ CDE2836411ABB71F00A7F0EE /* Groups.png in Resources */,
+ CDF0E05111DF7EAC00B2500F /* Three20.bundle in Resources */,
+ CD7A89F31204B60F00140865 /* Settings.bundle in Resources */,
+ CD720C03120B75FC006EC605 /* IASKAppSettingsView.xib in Resources */,
+ CD720C04120B75FC006EC605 /* IASKPSSliderSpecifierViewCell.xib in Resources */,
+ CD720C05120B75FC006EC605 /* IASKPSTextFieldSpecifierViewCell.xib in Resources */,
+ CD720C06120B75FC006EC605 /* IASKPSToggleSwitchSpecifierViewCell.xib in Resources */,
+ CD720C07120B75FC006EC605 /* IASKSpecifierValuesView.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 1D60588E0D05DD3D006BFB54 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 1D60589B0D05DD56006BFB54 /* main.m in Sources */,
+ 1D3623260D0F684500981E51 /* ATutorAppDelegate.m in Sources */,
+ CDE2832011ABAF5100A7F0EE /* LauncherViewController.m in Sources */,
+ CDE2834811ABB0A500A7F0EE /* StyleSheet.m in Sources */,
+ CD90256E11B0C0B500519439 /* SFHFKeychainUtils.m in Sources */,
+ CD90256F11B0C0B500519439 /* Base64Transcoder.c in Sources */,
+ CD90257011B0C0B500519439 /* hmac.c in Sources */,
+ CD90257111B0C0B500519439 /* sha1.c in Sources */,
+ CD90257211B0C0B500519439 /* NSString+URLEncoding.m in Sources */,
+ CD90257311B0C0B500519439 /* OAAsynchronousDataFetcher.m in Sources */,
+ CD90257411B0C0B500519439 /* OAConsumer.m in Sources */,
+ CD90257511B0C0B500519439 /* OADataFetcher.m in Sources */,
+ CD90257611B0C0B500519439 /* OAMutableURLRequest.m in Sources */,
+ CD90257711B0C0B500519439 /* OARequestParameter.m in Sources */,
+ CD90257811B0C0B500519439 /* OAServiceTicket.m in Sources */,
+ CD90257911B0C0B500519439 /* OAToken.m in Sources */,
+ CD90257A11B0C0B500519439 /* OAToken_KeychainExtensions.m in Sources */,
+ CD90257B11B0C0B500519439 /* OAHMAC_SHA1SignatureProvider.m in Sources */,
+ CD90257C11B0C0B500519439 /* OAPlaintextSignatureProvider.m in Sources */,
+ CD90258011B0C0B500519439 /* CDataScanner.m in Sources */,
+ CD90258111B0C0B500519439 /* CDataScanner_Extensions.m in Sources */,
+ CD90258211B0C0B500519439 /* NSCharacterSet_Extensions.m in Sources */,
+ CD90258311B0C0B500519439 /* NSDictionary_JSONExtensions.m in Sources */,
+ CD90258411B0C0B500519439 /* CJSONDeserializer.m in Sources */,
+ CD90258511B0C0B500519439 /* CJSONScanner.m in Sources */,
+ CD90258611B0C0B500519439 /* CJSONSerializer.m in Sources */,
+ CD90260B11B14D2400519439 /* OSProvider.m in Sources */,
+ CD90260F11B14DD300519439 /* OSConsumer.m in Sources */,
+ CD8F0EF211B2CFCF00D38970 /* QAWebController.m in Sources */,
+ CD8F0F7211B2D79A00D38970 /* CommonFunctions.m in Sources */,
+ CDA8E3C011BD323500B53FCF /* ActivitiesViewController.m in Sources */,
+ CDA8E3CE11BD32F500B53FCF /* ATutorHelper.m in Sources */,
+ CDF0DEE611DF6F9000B2500F /* Contact.m in Sources */,
+ CDF0DF0111DF72A100B2500F /* ContactsViewController.m in Sources */,
+ CD8235E011E3DD7500819570 /* ContactViewController.m in Sources */,
+ CD26D9E511E8D30700003274 /* ContactsDataSource.m in Sources */,
+ CD26DA9C11E8E66800003274 /* ContactItemCell.m in Sources */,
+ CD720BF8120B75FC006EC605 /* IASKAppSettingsViewController.m in Sources */,
+ CD720BF9120B75FC006EC605 /* IASKSpecifierValuesViewController.m in Sources */,
+ CD720BFA120B75FC006EC605 /* IASKSettingsReader.m in Sources */,
+ CD720BFB120B75FC006EC605 /* IASKSpecifier.m in Sources */,
+ CD720BFC120B75FC006EC605 /* IASKPSSliderSpecifierViewCell.m in Sources */,
+ CD720BFD120B75FC006EC605 /* IASKPSTextFieldSpecifierViewCell.m in Sources */,
+ CD720BFE120B75FC006EC605 /* IASKPSTitleValueSpecifierViewCell.m in Sources */,
+ CD720BFF120B75FC006EC605 /* IASKPSToggleSwitchSpecifierViewCell.m in Sources */,
+ CD720C00120B75FC006EC605 /* IASKSlider.m in Sources */,
+ CD720C01120B75FC006EC605 /* IASKSwitch.m in Sources */,
+ CD720C02120B75FC006EC605 /* IASKTextField.m in Sources */,
+ CDDEEEB4120F2C240016E33F /* GroupsViewController.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ CDF0E04311DF7E8D00B2500F /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = Three20Core;
+ targetProxy = CDF0E04211DF7E8D00B2500F /* PBXContainerItemProxy */;
+ };
+ CDF0E04511DF7E8D00B2500F /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = Three20UI;
+ targetProxy = CDF0E04411DF7E8D00B2500F /* PBXContainerItemProxy */;
+ };
+ CDF0E04711DF7E8D00B2500F /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = Three20Style;
+ targetProxy = CDF0E04611DF7E8D00B2500F /* PBXContainerItemProxy */;
+ };
+ CDF0E04911DF7E8D00B2500F /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = Three20Network;
+ targetProxy = CDF0E04811DF7E8D00B2500F /* PBXContainerItemProxy */;
+ };
+ CDF0E04B11DF7E8D00B2500F /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = Three20UINavigator;
+ targetProxy = CDF0E04A11DF7E8D00B2500F /* PBXContainerItemProxy */;
+ };
+ CDF0E04D11DF7E8D00B2500F /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = Three20UICommon;
+ targetProxy = CDF0E04C11DF7E8D00B2500F /* PBXContainerItemProxy */;
+ };
+ CDF0E04F11DF7E8D00B2500F /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = Three20;
+ targetProxy = CDF0E04E11DF7E8D00B2500F /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 1D6058940D05DD3E006BFB54 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = ATutor_Prefix.pch;
+ HEADER_SEARCH_PATHS = three20/Build/Products/three20;
+ INFOPLIST_FILE = "ATutor-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 3.0;
+ OTHER_LDFLAGS = (
+ "-ObjC",
+ "-all_load",
+ );
+ PRODUCT_NAME = ATutor;
+ SDKROOT = iphoneos4.1;
+ };
+ name = Debug;
+ };
+ 1D6058950D05DD3E006BFB54 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = ATutor_Prefix.pch;
+ HEADER_SEARCH_PATHS = three20/Build/Products/three20;
+ INFOPLIST_FILE = "ATutor-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 3.0;
+ OTHER_LDFLAGS = (
+ "-ObjC",
+ "-all_load",
+ );
+ PRODUCT_NAME = ATutor;
+ SDKROOT = iphoneos4.1;
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ C01FCF4F08A954540054247B /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ PREBINDING = NO;
+ SDKROOT = iphoneos3.1.3;
+ };
+ name = Debug;
+ };
+ C01FCF5008A954540054247B /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
+ PREBINDING = NO;
+ SDKROOT = iphoneos3.1.3;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "ATutor" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1D6058940D05DD3E006BFB54 /* Debug */,
+ 1D6058950D05DD3E006BFB54 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ATutor" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C01FCF4F08A954540054247B /* Debug */,
+ C01FCF5008A954540054247B /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
+}
--- /dev/null
+//
+// Prefix header for all source files of the 'ATutor' target in the 'ATutor' project
+//
+
+#ifdef __OBJC__
+ #import <Foundation/Foundation.h>
+ #import <UIKit/UIKit.h>
+#endif
+
+// Service name
+#define kATutor @"atutor"
+
+#define kConsumerKey @"key"
+#define kConsumerSecret @"secret"
+
+// E.g. @"http://localhost:8888/atutor/docs" & @"http://localhost:8888/shindig/php"
+#define kATutorURL [[NSUserDefaults standardUserDefaults] stringForKey:@"atutorURL"]
+#define kShindigURL [[NSUserDefaults standardUserDefaults] stringForKey:@"shindigURL"]
\ No newline at end of file
--- /dev/null
+//
+// ATutorAppDelegate.h
+// ATutor
+//
+// Created by Quang Anh Do on 25/05/2010.
+// Copyright Quang Anh Do 2010. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "LauncherViewController.h"
+#import "QAWebController.h"
+#import "ATutorHelper.h"
+#import "IASKAppSettingsViewController.h"
+
+@class OSConsumer;
+
+@interface ATutorAppDelegate : NSObject <UIApplicationDelegate, ATutorHelperDelegate, IASKSettingsDelegate> {
+ UIWindow *window;
+ OSConsumer *consumer;
+ LauncherViewController *launcher;
+ QAWebController *webController;
+ ATutorHelper *helper;
+ IASKAppSettingsViewController *settingsViewController;
+}
+
+@property (nonatomic, retain) IBOutlet UIWindow *window;
+@property (nonatomic, retain) OSConsumer *consumer;
+@property (nonatomic, retain) LauncherViewController *launcher;
+@property (nonatomic, retain) TTWebController *webController;
+@property (nonatomic, retain) ATutorHelper *helper;
+@property (nonatomic, retain) IASKAppSettingsViewController *settingsViewController;
+
+@end
+
--- /dev/null
+//
+// ATutorAppDelegate.m
+// ATutor
+//
+// Created by Quang Anh Do on 25/05/2010.
+// Copyright Quang Anh Do 2010. All rights reserved.
+//
+
+#import "ATutorAppDelegate.h"
+#import "StyleSheet.h"
+#import "OSConsumer.h"
+#import "OSProvider.h"
+
+#import "ActivitiesViewController.h"
+#import "ContactsViewController.h"
+#import "ContactViewController.h"
+#import "GroupsViewController.h"
+#import "CommonFunctions.h"
+
+@interface ATutorAppDelegate (Private)
+
+- (void)wireUpNavigator;
+
+@end
+
+
+@implementation ATutorAppDelegate
+
+@synthesize window;
+@synthesize consumer;
+@synthesize launcher;
+@synthesize webController;
+@synthesize helper;
+@synthesize settingsViewController;
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ // Set service consumer
+ consumer = [[OSConsumer alloc] init];
+
+ // Set global stylesheet
+ [TTDefaultStyleSheet setGlobalStyleSheet:[[[StyleSheet alloc] init] autorelease]];
+
+ // Set web controller handler
+ launcher = [[LauncherViewController alloc] init];
+
+ webController = [[QAWebController alloc] init];
+ webController.oAuthDelegate = launcher;
+
+ // Set up settings VC
+ settingsViewController = [[IASKAppSettingsViewController alloc] initWithNibName:@"IASKAppSettingsView"
+ bundle:nil];
+ [settingsViewController setDelegate:self];
+
+ // Wire things up
+ [self wireUpNavigator];
+
+ // Home screen
+ [[TTNavigator navigator] openURLAction:[TTURLAction actionWithURLPath:@"atutor://launcher"]];
+
+ // Prepare helper
+ helper = [[ATutorHelper alloc] init];
+ [helper setDelegate:self];
+
+ if (!kATutorURL || !kShindigURL) {
+ NSLog(@"Settings required");
+ [[TTNavigator navigator] openURLAction:[[TTURLAction actionWithURLPath:@"atutor://settings"] applyAnimated:YES]];
+ } else {
+ [helper fetchContactList];
+ }
+
+ return YES;
+}
+
+- (void)dealloc {
+ [window release];
+ [consumer release];
+ [launcher release];
+ [webController release];
+ [helper release];
+ [settingsViewController release];
+
+ [super dealloc];
+}
+
+#pragma mark -
+#pragma mark Misc
+
+- (void)wireUpNavigator {
+ TTNavigator *navigator = [TTNavigator navigator];
+ navigator.window = window;
+ navigator.persistenceMode = TTNavigatorPersistenceModeNone;
+
+ TTURLMap *map = navigator.URLMap;
+ [map from:@"*" toViewController:webController];
+ [map from:@"atutor://launcher" toViewController:launcher];
+ [map from:@"atutor://activities" toViewController:[ActivitiesViewController class]];
+ [map from:@"atutor://contacts" toViewController:[ContactsViewController class]];
+ [map from:@"atutor://contact/(initWithId:)" toViewController:[ContactViewController class]];
+ [map from:@"atutor://contact/(initWithId:)/(name:)" toViewController:[ContactViewController class]];
+ [map from:@"atutor://groups" toViewController:[GroupsViewController class]];
+ [map from:@"atutor://settings" toViewController:settingsViewController];
+}
+
+#pragma mark -
+#pragma mark Helper delegate
+
+- (void)doneFetchingContactList {
+ [[TTNavigator navigator] openURLAction:[TTURLAction actionWithURLPath:@"atutor://launcher"]];
+}
+
+#pragma mark -
+#pragma mark IASK delegate
+
+- (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController *)sender {
+ NSLog(@"Settings updated, refresh consumer");
+ consumer.currentProvider = [OSProvider getATutorProviderWithKey:kConsumerKey withSecret:kConsumerSecret];
+}
+
+@end
--- /dev/null
+//
+// ATutorHelper.h
+// ATutor
+//
+// Created by Quang Anh Do on 07/06/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "OSConsumer.h"
+
+@protocol ATutorHelperDelegate;
+
+@interface ATutorHelper : NSObject {
+ OSConsumer *consumer;
+
+ int numberOfContacts;
+ NSMutableArray *contacts;
+ NSMutableArray *contactMapping;
+
+ id delegate;
+}
+
+@property (nonatomic, retain) OSConsumer *consumer;
+@property int numberOfContacts;
+@property (nonatomic, retain) NSMutableArray *contacts;
+@property (nonatomic, retain) NSMutableArray *contactMapping;
+@property (nonatomic, assign) id<ATutorHelperDelegate> delegate;
+
+- (void)fetchContactList;
+- (void)fetchOwnProfile;
+
+@end
+
+@protocol ATutorHelperDelegate
+
+- (void)doneFetchingContactList;
+
+@end
\ No newline at end of file
--- /dev/null
+//
+// ATutorHelper.m
+// ATutor
+//
+// Created by Quang Anh Do on 07/06/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import "ATutorHelper.h"
+#import "ATutorAppDelegate.h"
+#import "OARequestParameter.h"
+#import "CommonFunctions.h"
+#import "OAServiceTicket.h"
+#import "NSDictionary_JSONExtensions.h"
+#import "Contact.h"
+
+@interface ATutorHelper (Private)
+
+- (void)peopleCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response;
+- (void)personCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response;
+- (NSDictionary *)matchDisplayNameWithId:(NSArray *)data;
+
+@end
+
+
+@implementation ATutorHelper
+
+@synthesize consumer;
+@synthesize numberOfContacts;
+@synthesize contacts;
+@synthesize contactMapping;
+@synthesize delegate;
+
+- (void)dealloc {
+ [consumer dealloc];
+ [contacts dealloc];
+ [contactMapping dealloc];
+ [delegate release];
+
+ [super dealloc];
+}
+
+- (id)init {
+ if (self = [super init]) {
+ self.consumer = [(ATutorAppDelegate *)[[UIApplication sharedApplication] delegate] consumer];
+ self.numberOfContacts = 0;
+ self.contacts = [[NSMutableArray alloc] init];
+ self.contactMapping = [[NSMutableArray alloc] init];
+ }
+
+ return self;
+}
+
+- (void)fetchContactList {
+ NSLog(@"=-=-=-=-=-=-=-=-Fetching contact list-=-=-=-=-=-=-=-=");
+
+ [consumer getDataForUrl:@"/people/@me/@contacts"
+ andParameters:[NSArray arrayWithObjects:[OARequestParameter requestParameterWithName:@"count" value:@"100"],
+ [OARequestParameter requestParameterWithName:@"startIndex" value:[NSString stringWithFormat:@"%d", numberOfContacts]],
+ [OARequestParameter requestParameterWithName:@"sortBy" value:@"displayName"],
+ nil]
+ delegate:self
+ didFinishSelector:@selector(peopleCallback:didFinishWithResponse:)];
+}
+
+- (void)fetchOwnProfile {
+ NSLog(@"=-=-=-=-=-=-=-=-Fetching own profile-=-=-=-=-=-=-=-=");
+
+ [consumer getDataForUrl:@"/people/@me/@self"
+ andParameters:nil
+ delegate:self
+ didFinishSelector:@selector(personCallback:didFinishWithResponse:)];
+}
+
+- (void)peopleCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response {
+ if (ticket.didSucceed) {
+ NSError *error = nil;
+ NSDictionary *data = [NSDictionary dictionaryWithJSONData:[response dataUsingEncoding:NSUTF8StringEncoding] error:&error];
+ NSArray *entries = [data objectForKey:@"entry"];
+
+ // Mapping
+ [contactMapping addObjectsFromArray:entries];
+ numberOfContacts += [entries count];
+
+ for (NSDictionary *entry in entries) {
+ [contacts addObject:[Contact contactWithDictionary:entry]];
+ }
+
+ // Continue fetching or not?
+ if (numberOfContacts < [[data objectForKey:@"totalResults"] intValue]) { // Fetch friend
+ [self fetchContactList];
+ } else { // Fetch own profile
+ [self fetchOwnProfile];
+ }
+ } else {
+ alertMessage(@"Error", @"Unable to fetch your contact list");
+ }
+}
+
+- (void)personCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response {
+ if (ticket.didSucceed) {
+ NSError *error = nil;
+ NSDictionary *data = [NSDictionary dictionaryWithJSONData:[response dataUsingEncoding:NSUTF8StringEncoding] error:&error];
+ NSDictionary *entry = [data objectForKey:@"entry"];
+
+ // Mapping
+ [contactMapping addObject:entry];
+ numberOfContacts++;
+
+ [contacts addObject:[Contact contactWithDictionary:entry]];
+
+ // Wrap things up
+ NSLog(@"Archiving contact list");
+
+ [NSKeyedArchiver archiveRootObject:[self matchDisplayNameWithId:contactMapping]
+ toFile:[applicationDocumentsDirectory() stringByAppendingPathComponent:@"contact_mapping.plist"]];
+
+ [NSKeyedArchiver archiveRootObject:contacts
+ toFile:[applicationDocumentsDirectory() stringByAppendingPathComponent:@"contacts.plist"]];
+
+ // Good to go
+ if (delegate && [delegate respondsToSelector:@selector(doneFetchingContactList)]) {
+ [delegate performSelector:@selector(doneFetchingContactList)];
+ }
+ } else {
+ alertMessage(@"Error", @"Unable to fetch your profile");
+ }
+}
+
+- (NSDictionary *)matchDisplayNameWithId:(NSArray *)data {
+ NSMutableDictionary *retVal = [[NSMutableDictionary alloc] init];
+
+ for (NSDictionary *contact in data) {
+ [retVal setObject:[contact objectForKey:@"displayName"]
+ forKey:[contact objectForKey:@"id"]];
+ }
+
+ return [retVal autorelease];
+}
+
+@end
--- /dev/null
+//
+// ActivitiesViewController.h
+// ATutor
+//
+// Created by Quang Anh Do on 07/06/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <Three20/Three20.h>
+
+
+@interface ActivitiesViewController : TTTableViewController {
+
+}
+
+@end
--- /dev/null
+//
+// ActivitiesViewController.m
+// ATutor
+//
+// Created by Quang Anh Do on 07/06/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import "ActivitiesViewController.h"
+#import "CommonFunctions.h"
+#import "OSConsumer.h"
+#import "OAServiceTicket.h"
+#import "NSDictionary_JSONExtensions.h"
+#import "ATutorAppDelegate.h"
+
+@interface LauncherViewController (Private)
+
+- (void)activitiesCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response;
+
+@end
+
+@implementation ActivitiesViewController
+
+- (id)init {
+ if (self = [super init]) {
+ self.title = TTLocalizedString(@"Activities", @"");
+ self.autoresizesForKeyboard = YES;
+ self.variableHeightRows = YES;
+
+ OSConsumer *consumer = [(ATutorAppDelegate *)[[UIApplication sharedApplication] delegate] consumer];
+ [consumer getDataForUrl:@"/activities/@me/@contacts"
+ andParameters:nil
+ delegate:self
+ didFinishSelector:@selector(activitiesCallback:didFinishWithResponse:)];
+ }
+
+ return self;
+}
+
+- (void)loadView {
+ [super loadView];
+
+ self.tableView.allowsSelection = NO;
+}
+
+- (void)activitiesCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response {
+ if (ticket.didSucceed) {
+ // Load contact list
+ NSDictionary *contactList = [NSKeyedUnarchiver unarchiveObjectWithFile:[applicationDocumentsDirectory() stringByAppendingPathComponent:@"contact_mapping.plist"]];
+ NSLog(@"Contact list: %@", contactList);
+
+ // Build data source
+ NSError *error = nil;
+ NSDictionary *data = [NSDictionary dictionaryWithJSONData:[response dataUsingEncoding:NSUTF8StringEncoding] error:&error];
+
+ int numberOfItems = [[data objectForKey:@"totalResults"] intValue] % [[data objectForKey:@"itemsPerPage"] intValue];
+
+ TTListDataSource *dataSource = [[[TTListDataSource alloc] init] autorelease];
+ for (int i = 0; i < numberOfItems; i++) {
+ NSDictionary *entry = [[data objectForKey:@"entry"] objectAtIndex:i];
+
+ NSString *contact = [NSString stringWithFormat:@"<a href='%@'>%@</a>",
+ linkToContact([[entry objectForKey:@"userId"] integerValue], [contactList objectForKey:[entry objectForKey:@"userId"]]), // link
+ [contactList objectForKey:[entry objectForKey:@"userId"]]]; // name
+ NSString *xhtml = [NSString stringWithFormat:@"%@ - %@ %@",
+ niceTimeString([entry objectForKey:@"postedTime"]), // time
+ contact, // contact
+ rewriteURLStrings([entry objectForKey:@"title"]) // title
+ ];
+
+ TTStyledText *text = [TTStyledText textFromXHTML:xhtml];
+
+ [dataSource.items addObject:[TTTableStyledTextItem itemWithText:text URL:nil]];
+ }
+
+ self.dataSource = dataSource;
+ } else {
+ alertMessage(@"Error", @"Unable to process your request");
+ }
+}
+
+@end
--- /dev/null
+//
+// CommonFunctions.h
+// ATutor
+//
+// Created by Quang Anh Do on 30/05/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <Three20/Three20.h>
+
+
+@interface CommonFunctions : NSObject {
+
+}
+
+void alertMessage(NSString *title, NSString *message);
+BOOL dataSourceAvailable();
+NSString *applicationDocumentsDirectory();
+
+BOOL isLoggedIn();
+
+NSString *shortLinkToContact(int id);
+NSString *linkToContact(int id, NSString *name);
+NSString *rewriteURLStrings(NSString *content);
+NSString *niceTimeString(NSString *timeString);
+
+@end
--- /dev/null
+//
+// CommonFunctions.m
+// ATutor
+//
+// Created by Quang Anh Do on 30/05/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import "CommonFunctions.h"
+
+#import <SystemConfiguration/SystemConfiguration.h>
+#import "SFHFKeychainUtils.h"
+
+@implementation CommonFunctions
+
+void alertMessage(NSString *title, NSString *message) {
+ UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:TTLocalizedString(title, @"")
+ message:TTLocalizedString(message, @"")
+ delegate:nil cancelButtonTitle:TTLocalizedString(@"OK", @"") otherButtonTitles:nil];
+ [alertView show];
+ [alertView release];
+}
+
+BOOL dataSourceAvailable() {
+ Boolean success;
+ const char *host_name = "www.google.com";
+
+ SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, host_name);
+ SCNetworkReachabilityFlags flags;
+ success = SCNetworkReachabilityGetFlags(reachability, &flags);
+ BOOL _isDataSourceAvailable = success && (flags & kSCNetworkFlagsReachable) && !(flags & kSCNetworkFlagsConnectionRequired);
+ CFRelease(reachability);
+
+ return _isDataSourceAvailable;
+}
+
+NSString *applicationDocumentsDirectory() {
+ return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
+}
+
+BOOL isLoggedIn() {
+ return ![[SFHFKeychainUtils getPasswordForUsername:@"accessToken" andServiceName:kATutor error:nil] isEqualToString:@""]
+ && ![[SFHFKeychainUtils getPasswordForUsername:@"requestToken" andServiceName:kATutor error:nil] isEqualToString:@""];
+}
+
+NSString *shortLinkToContact(int id) {
+ return [NSString stringWithFormat:@"atutor://contact/%d", id];
+}
+
+NSString *linkToContact(int id, NSString *name) {
+ return [NSString stringWithFormat:@"atutor://contact/%d/%@", id, [name stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
+}
+
+NSString *rewriteURLStrings(NSString *content) {
+ NSMutableString *retVal = [NSMutableString stringWithString:content];
+
+ // Links to contacts
+ [retVal replaceOccurrencesOfString:[NSString stringWithFormat:@"%@/mods/_standard/social/sprofile.php?id=", kATutorURL]
+ withString:@"atutor://contact/"
+ options:NSCaseInsensitiveSearch
+ range:NSMakeRange(0, [retVal length])];
+
+ return retVal;
+}
+
+NSString *niceTimeString(NSString *timeString) {
+ NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
+ [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
+
+ NSDate *date = [dateFormatter dateFromString:timeString];
+ [dateFormatter setDateStyle:NSDateFormatterShortStyle];
+
+ return [dateFormatter stringFromDate:date];
+}
+
+@end
--- /dev/null
+//
+// Contact.h
+// ATutor
+//
+// Created by Quang Anh Do on 03/07/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+@interface Contact : NSObject {
+ int identifier;
+ NSString *displayName;
+}
+
+@property int identifier;
+@property (nonatomic, retain) NSString *displayName;
+
++ (Contact *)contactWithDictionary:(NSDictionary *)dictionary;
+
+@end
--- /dev/null
+//
+// Contact.m
+// ATutor
+//
+// Created by Quang Anh Do on 03/07/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import "Contact.h"
+
+
+@implementation Contact
+
+@synthesize identifier;
+@synthesize displayName;
+
+
+/* dealloc */
+- (void) dealloc {
+ [displayName release];
+
+ [super dealloc];
+}
+
++ (Contact *)contactWithDictionary:(NSDictionary *)dictionary {
+ Contact *contact = [[self alloc] init];
+ contact.identifier = [[dictionary objectForKey:@"id"] intValue];
+ contact.displayName = [dictionary objectForKey:@"displayName"];
+
+ return [contact autorelease];
+}
+
+#pragma mark -
+#pragma mark Keyed Archiving
+
+/* Keyed Archiving */
+//
+- (void) encodeWithCoder: (NSCoder *)encoder {
+ [encoder encodeInt: [self identifier] forKey: @"identifier"];
+ [encoder encodeObject: [self displayName] forKey: @"displayName"];
+}
+
+- (id) initWithCoder: (NSCoder *)decoder {
+ self = [super init];
+ if (self) {
+ [self setIdentifier: [decoder decodeIntForKey: @"identifier"]];
+ [self setDisplayName: [decoder decodeObjectForKey: @"displayName"]];
+ }
+ return self;
+}
+
+@end
--- /dev/null
+//
+// ContactItemCell.h
+// ATutor
+//
+// Created by Quang Anh Do on 10/07/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <Three20/Three20.h>
+
+
+@interface ContactItemCell : TTTableTextItemCell {
+
+}
+
+@end
--- /dev/null
+//
+// ContactItemCell.m
+// ATutor
+//
+// Created by Quang Anh Do on 10/07/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import "ContactItemCell.h"
+
+
+@implementation ContactItemCell
+
+- (void)setObject:(id)object {
+ [super setObject:object];
+
+ self.accessoryType = UITableViewCellAccessoryNone;
+}
+
+@end
--- /dev/null
+//
+// ContactViewController.h
+// ATutor
+//
+// Created by Quang Anh Do on 06/07/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <AddressBook/AddressBook.h>
+#import <AddressBookUI/AddressBookUI.h>
+
+
+@interface ContactViewController : UIViewController {
+ ABAddressBookRef addressBook;
+}
+
+- (id)initWithId:(int)identifier;
+- (id)initWithId:(int)identifier name:(NSString *)name;
+
+@end
--- /dev/null
+//
+// ContactViewController.m
+// ATutor
+//
+// Created by Quang Anh Do on 06/07/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import "ContactViewController.h"
+#import "CommonFunctions.h"
+
+@implementation ContactViewController
+
+- (void)dealloc {
+ CFRelease(addressBook);
+
+ [super dealloc];
+}
+
+- (id)initWithId:(int)identifier {
+ NSDictionary *contactList = [NSKeyedUnarchiver unarchiveObjectWithFile:[applicationDocumentsDirectory() stringByAppendingPathComponent:@"contact_mapping.plist"]];
+
+ return [self initWithId:identifier
+ name:[contactList objectForKey:[NSString stringWithFormat:@"%d", identifier]]];
+}
+
+- (id)initWithId:(int)identifier name:(NSString *)name {
+ addressBook = ABAddressBookCreate();
+
+ ABRecordRef person = NULL;
+ CFArrayRef matches = ABAddressBookCopyPeopleWithName(addressBook, (CFStringRef)name);
+
+ if (matches && CFArrayGetCount(matches)) {
+ person = (id)CFArrayGetValueAtIndex(matches, 0);
+
+ ABMultiValueRef urls = ABRecordCopyValue(person, kABPersonURLProperty);
+ ABMutableMultiValueRef mutableURLs = NULL;
+ if (urls) {
+ mutableURLs = ABMultiValueCreateMutableCopy(urls);
+ CFRelease(urls);
+ } else {
+ mutableURLs = ABMultiValueCreateMutable(kABStringPropertyType);
+ }
+ ABMultiValueAddValueAndLabel(mutableURLs, shortLinkToContact(identifier), CFSTR("ATutor"), NULL);
+ CFRelease(mutableURLs);
+ } else {
+ person = ABPersonCreate();
+ ABRecordSetValue(person, kABPersonFirstNameProperty, name, NULL);
+
+ ABMutableMultiValueRef urls = ABMultiValueCreateMutable(kABMultiStringPropertyType);
+ ABMultiValueAddValueAndLabel(urls, shortLinkToContact(identifier), CFSTR("ATutor"), NULL);
+ ABRecordSetValue(person, kABPersonURLProperty, urls, NULL);
+ CFRelease(urls);
+ [(id)person autorelease];
+ }
+
+ if (ABRecordGetRecordID(person) != kABRecordInvalidID) {
+ self = [[ABPersonViewController alloc] init];
+ [(ABPersonViewController *)self setAllowsEditing:YES];
+ [(ABPersonViewController *)self setDisplayedPerson:person];
+ } else {
+ self = [[ABUnknownPersonViewController alloc] init];
+ [(ABUnknownPersonViewController *)self setAllowsActions:YES];
+ [(ABUnknownPersonViewController *)self setAllowsAddingToAddressBook:YES];
+ [(ABUnknownPersonViewController *)self setDisplayedPerson:person];
+ }
+
+ if (matches) CFRelease(matches);
+
+ return self;
+}
+
+@end
--- /dev/null
+//
+// ContactsDataSource.h
+// ATutor
+//
+// Created by Quang Anh Do on 10/07/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <Three20/Three20.h>
+
+
+@interface ContactsDataSource : TTSectionedDataSource {
+
+}
+
+@end
--- /dev/null
+//
+// ContactsDataSource.m
+// ATutor
+//
+// Created by Quang Anh Do on 10/07/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import "ContactsDataSource.h"
+#import "CommonFunctions.h"
+#import "Contact.h"
+#import "ContactItemCell.h"
+
+
+@implementation ContactsDataSource
+
+- (id)init {
+ if (self = [super init]) {
+ NSDictionary *contactList = [NSKeyedUnarchiver unarchiveObjectWithFile:[applicationDocumentsDirectory() stringByAppendingPathComponent:@"contacts.plist"]];
+
+ NSMutableDictionary *nameIndexes = [NSMutableDictionary dictionary];
+
+ for (Contact *contact in contactList) {
+ // Setup contact item
+ NSString *urlString = linkToContact(contact.identifier, contact.displayName);
+ TTTableTextItem *contactItem = [TTTableTextItem itemWithText:contact.displayName URL:urlString];
+
+ // Setup name indexes for section headers
+ NSString *firstLetter = [contact.displayName substringToIndex:1];
+ NSMutableArray *existingArray;
+ if (existingArray = [nameIndexes valueForKey:firstLetter]) {
+ [existingArray addObject:contactItem];
+ } else {
+ NSMutableArray *tempArray = [NSMutableArray array];
+ [nameIndexes setObject:tempArray forKey:firstLetter];
+ [tempArray addObject:contactItem];
+ }
+
+ [self.items addObject:contactItem];
+ }
+
+ // Final touches
+ self.sections = [[[nameIndexes allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] mutableCopy];
+ self.items = [NSMutableArray array];
+
+ for (NSString *index in self.sections) {
+ [self.items addObject:[nameIndexes objectForKey:index]];
+ }
+
+ TTTableSummaryItem *countItem = [TTTableSummaryItem itemWithText:[NSString stringWithFormat:@"%d Contacts", [contactList count]] URL:NULL];
+ [[self.items lastObject] addObject:countItem];
+ }
+
+ return self;
+}
+
+- (NSArray*)sectionIndexTitlesForTableView:(UITableView*)tableView {
+ return [TTSectionedDataSource lettersForSectionsWithSearch:NO summary:YES];
+}
+
+- (Class)tableView:(UITableView*)tableView cellClassForObject:(id)object {
+ return [ContactItemCell class];
+}
+
+@end
--- /dev/null
+//
+// ContactsViewController.h
+// ATutor
+//
+// Created by Quang Anh Do on 03/07/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import <Three20/Three20.h>
+
+@interface ContactsViewController : TTTableViewController {
+
+}
+
+@end
--- /dev/null
+//
+// ContactsViewController.m
+// ATutor
+//
+// Created by Quang Anh Do on 03/07/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import "ContactsViewController.h"
+#import "Contact.h"
+#import "CommonFunctions.h"
+#import "ContactsDataSource.h"
+
+@implementation ContactsViewController
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+- (id)init {
+ if (self = [super init]) {
+ self.title = TTLocalizedString(@"Contacts", @"");
+ self.autoresizesForKeyboard = YES;
+ }
+
+ return self;
+}
+
+- (void)loadView {
+ [super loadView];
+
+ self.dataSource = [[ContactsDataSource alloc] init];
+}
+
+@end
--- /dev/null
+//
+// GroupsViewController.h
+// ATutor
+//
+// Created by Quang Anh Do on 08/08/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <Three20/Three20.h>
+
+
+@interface GroupsViewController : TTTableViewController {
+
+}
+
+@end
--- /dev/null
+//
+// GroupsViewController.m
+// ATutor
+//
+// Created by Quang Anh Do on 08/08/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import "GroupsViewController.h"
+#import "CommonFunctions.h"
+#import "OSConsumer.h"
+#import "OAServiceTicket.h"
+#import "NSDictionary_JSONExtensions.h"
+#import "ATutorAppDelegate.h"
+
+@interface GroupsViewController (Private)
+
+- (void)groupsCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response;
+
+@end
+
+@implementation GroupsViewController
+
+- (id)init {
+ if (self = [super init]) {
+ self.title = TTLocalizedString(@"Groups", @"");
+ self.autoresizesForKeyboard = YES;
+ self.variableHeightRows = YES;
+
+ OSConsumer *consumer = [(ATutorAppDelegate *)[[UIApplication sharedApplication] delegate] consumer];
+ [consumer getDataForUrl:@"/groups/@me"
+ andParameters:nil
+ delegate:self
+ didFinishSelector:@selector(groupsCallback:didFinishWithResponse:)];
+ }
+
+ return self;
+}
+
+- (void)loadView {
+ [super loadView];
+
+ self.tableView.allowsSelection = NO;
+}
+
+- (void)groupsCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response {
+ if (ticket.didSucceed) {
+
+ } else {
+ alertMessage(@"Error", @"The service groups is not implemented");
+ }
+}
+
+@end
--- /dev/null
+//
+// LauncherViewController.h
+// ATutor
+//
+// Created by Quang Anh Do on 25/05/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import <Three20/Three20.h>
+#import "QAWebController.h"
+#import "OSConsumer.h"
+
+@interface LauncherViewController : TTViewController <TTLauncherViewDelegate, QAWebControllerDelegate> {
+ TTLauncherView *launcherView;
+ UIBarButtonItem *logoutButton;
+ OSConsumer *consumer;
+}
+
+@property (nonatomic, retain) TTLauncherView *launcherView;
+@property (nonatomic, retain) UIBarButtonItem *logoutButton;
+@property (nonatomic, retain) OSConsumer *consumer;
+
+- (void)restorePages;
+
+@end
--- /dev/null
+//
+// LauncherViewController.m
+// ATutor
+//
+// Created by Quang Anh Do on 25/05/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import "LauncherViewController.h"
+#import "ATutorAppDelegate.h"
+#import "CommonFunctions.h"
+
+@interface LauncherViewController (Private)
+
+- (BOOL)isLoggedIn;
+- (void)logout;
+
+@end
+
+@implementation LauncherViewController
+
+@synthesize launcherView;
+@synthesize logoutButton;
+@synthesize consumer;
+
+- (id)init {
+ if (self = [super init]) {
+ self.consumer = [(ATutorAppDelegate *)[[UIApplication sharedApplication] delegate] consumer];
+ }
+
+ return self;
+}
+
+- (void)dealloc {
+ [launcherView release];
+ [logoutButton release];
+ [consumer release];
+
+ [super dealloc];
+}
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ logoutButton = [[UIBarButtonItem alloc] initWithTitle:TTLocalizedString(@"Logout", @"")
+ style:UIBarButtonItemStyleBordered
+ target:self action:@selector(logout)];
+
+ self.title = TTLocalizedString(@"ATutor Social", @"");
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+ [super viewWillAppear:animated];
+ self.navigationItem.rightBarButtonItem = [self isLoggedIn] ? logoutButton : nil;
+}
+
+- (void)didReceiveMemoryWarning {
+ // Releases the view if it doesn't have a superview.
+ [super didReceiveMemoryWarning];
+
+ // Release any cached data, images, etc that aren't in use.
+}
+
+- (void)viewDidUnload {
+ [super viewDidUnload];
+ // Release any retained subviews of the main view.
+ // e.g. self.myOutlet = nil;
+}
+
+- (void)loadView {
+ [super loadView];
+
+ launcherView = [[TTLauncherView alloc] initWithFrame:self.view.bounds];
+
+ launcherView.delegate = self;
+ launcherView.backgroundColor = [UIColor colorWithRed:0.875 green:0.871 blue:0.925 alpha:1.000];
+ launcherView.columnCount = 2;
+
+ // Attempt to restore data if exists
+ [self restorePages];
+
+ [self.view addSubview:launcherView];
+}
+
+#pragma mark -
+#pragma mark TTLauncherViewDelegate
+
+- (void)launcherViewDidBeginEditing:(TTLauncherView*)launcher {
+ [self.navigationItem setRightBarButtonItem:[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
+ target:launcherView
+ action:@selector(endEditing)] autorelease]
+ animated:YES];
+}
+
+- (void)launcherViewDidEndEditing:(TTLauncherView*)launcher {
+ [self.navigationItem setRightBarButtonItem:logoutButton animated:YES];
+
+ // Persist data the ugly way
+ NSData *pages = [NSKeyedArchiver archivedDataWithRootObject:launcherView.pages];
+ [[NSUserDefaults standardUserDefaults] setObject:pages forKey:@"launcher.pages"];
+}
+
+- (void)launcherView:(TTLauncherView*)launcher didSelectItem:(TTLauncherItem*)item {
+ if ([item.title isEqualToString:TTLocalizedString(@"Activities", @"")]) {
+ [[TTNavigator navigator] openURLAction:[[TTURLAction actionWithURLPath:@"atutor://activities"] applyAnimated:YES]];
+ } else if ([item.title isEqualToString:TTLocalizedString(@"Contacts", @"")]) {
+ [[TTNavigator navigator] openURLAction:[[TTURLAction actionWithURLPath:@"atutor://contacts"] applyAnimated:YES]];
+ } else if ([item.title isEqualToString:TTLocalizedString(@"Gadgets", @"")]) {
+ [[TTNavigator navigator] openURLs:
+ [NSString stringWithFormat:@"%@/mods/_standard/social/applications.php", kATutorURL], nil];
+ } else if ([item.title isEqualToString:TTLocalizedString(@"Groups", @"")]) {
+ [[TTNavigator navigator] openURLAction:[[TTURLAction actionWithURLPath:@"atutor://groups"] applyAnimated:YES]];
+ }
+}
+
+#pragma mark -
+#pragma mark QAWebControllerDelegate
+
+- (void)didFinishAuthorizationInWebViewController:(QAWebController *)webViewController {
+ [consumer finishAuthProcess];
+
+ [[(ATutorAppDelegate *)[[UIApplication sharedApplication] delegate] helper] fetchContactList];
+}
+
+#pragma mark -
+#pragma mark Misc
+
+- (void)restorePages {
+ NSData *pages = [[NSUserDefaults standardUserDefaults] objectForKey:@"launcher.pages"];
+ if (pages != nil) {
+ launcherView.pages = [NSKeyedUnarchiver unarchiveObjectWithData:pages];
+ } else {
+ for (NSString *module in [NSArray arrayWithObjects:@"Activities", @"Contacts", @"Gadgets", @"Groups", nil]) {
+ [launcherView addItem:[[[TTLauncherItem alloc] initWithTitle:TTLocalizedString(module, @"")
+ image:[NSString stringWithFormat:@"bundle://%@.png", module]
+ URL:[NSString stringWithFormat:@"atutor://modules/%@", module]
+ canDelete:NO] autorelease]
+ animated:NO];
+ }
+ }
+}
+
+- (BOOL)isLoggedIn {
+ return consumer.accessToken != nil;
+}
+
+- (void)logout {
+ [consumer clearAuthentication];
+
+ [self.navigationItem setRightBarButtonItem:nil animated:YES];
+
+ alertMessage(@"", @"You have been logged out");
+}
+
+@end
--- /dev/null
+//
+// OSConsumer.h
+// ATutor
+//
+// Created by Quang Anh Do on 29/05/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@class OSProvider;
+@class OAConsumer;
+@class OAToken;
+
+@interface OSConsumer : NSObject {
+ OAConsumer *consumer;
+ OAToken *accessToken;
+ OSProvider *currentProvider;
+}
+
+@property (nonatomic, retain) OAToken *accessToken;
+@property (nonatomic, retain) OAConsumer *consumer;
+@property (nonatomic, retain) OSProvider *currentProvider;
+
+- (id)initWithProvider:(OSProvider *)provider;
+- (void)getDataForUrl:(NSString *)relativeUrl
+ andParameters:(NSArray*)params
+ delegate:(id)delegate
+ didFinishSelector:(SEL)didFinishSelector;
+- (void)startAuthProcess;
+- (void)finishAuthProcess;
+- (void)clearAuthentication;
+
+@end
--- /dev/null
+//
+// OSConsumer.m
+// ATutor
+//
+// Created by Quang Anh Do on 29/05/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import "OSConsumer.h"
+#import "OSProvider.h"
+#import "SFHFKeychainUtils.h"
+#import "OAMutableURLRequest.h"
+#import "OAServiceTicket.h"
+#import "OAConsumer.h"
+#import "OADataFetcher.h"
+#import "OAToken.h"
+#import "OAToken_KeychainExtensions.h"
+#import <Three20/Three20.h>
+
+@interface OSConsumer (Private)
+- (void)setupConsumer;
+- (void)getRequestToken;
+- (void)requestTokenCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response;
+- (void)getAccessToken;
+- (void)accessTokenCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response;
+@end
+
+@implementation OSConsumer
+
+@synthesize consumer, accessToken, currentProvider;
+
+- (void)dealloc {
+ [consumer release];
+ [accessToken release];
+ [currentProvider release];
+
+ [super dealloc];
+}
+
+- (id)init {
+ return [self initWithProvider:[OSProvider getATutorProviderWithKey:kConsumerKey withSecret:kConsumerSecret]];
+}
+
+- (id)initWithProvider:(OSProvider *)provider {
+ if (self = [super init]) {
+ self.accessToken = [[[OAToken alloc] initWithKeychainUsingAppName:kATutor tokenType:@"accessToken"] autorelease];
+ self.currentProvider = provider;
+
+ [self setupConsumer];
+ }
+
+ return self;
+}
+
+- (void)startAuthProcess {
+ [self getRequestToken];
+}
+
+- (void)finishAuthProcess {
+ [self getAccessToken];
+}
+
+// Should be called within a handleOpenUrl method.
+// This method assumes the request token was authorized and will retrieve the access token
+- (void)clearAuthentication {
+ [SFHFKeychainUtils storeUsername:@"accessToken" andPassword:@"" forServiceName:kATutor updateExisting:TRUE error:nil];
+ [SFHFKeychainUtils storeUsername:@"requestToken" andPassword:@"" forServiceName:kATutor updateExisting:TRUE error:nil];
+
+ self.accessToken = nil;
+}
+
+- (void)getDataForUrl:(NSString *)relativeUrl andParameters:(NSArray*)params
+ delegate:(id)delegate didFinishSelector:(SEL)didFinishSelector {
+ if (!accessToken) {
+ [self startAuthProcess];
+ return;
+ }
+
+ NSLog(@"Getting data with access token: %@ : %@", [accessToken key], [accessToken secret]);
+
+ NSString *url = [[currentProvider endpointUrl] stringByAppendingString:relativeUrl];
+ OAMutableURLRequest *request = [[[OAMutableURLRequest alloc]
+ initWithURL:[NSURL URLWithString:url]
+ parameters:params
+ consumer:consumer token:accessToken] autorelease];
+ [request setHTTPMethod:@"GET"];
+
+ [OADataFetcher fetchDataWithRequest:request delegate:delegate
+ didFinishSelector:didFinishSelector];
+}
+
+#pragma mark -
+#pragma mark Private
+
+- (void)setupConsumer {
+ self.consumer = [[[OAConsumer alloc] initWithKey:[currentProvider consumerKey]
+ secret:[currentProvider consumerSecret]] autorelease];
+}
+
+- (void)getRequestToken {
+ OAMutableURLRequest *request = [[[OAMutableURLRequest alloc]
+ initWithURL:[NSURL URLWithString:[currentProvider requestUrl]]
+ parameters:[currentProvider extraRequestUrlParams]
+ consumer:consumer
+ token:nil] autorelease];
+ [request setHTTPMethod:@"GET"];
+
+ [OADataFetcher fetchDataWithRequest:request
+ delegate:self
+ didFinishSelector:@selector(requestTokenCallback:didFinishWithResponse:)];
+}
+
+- (void)requestTokenCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response {
+ if (ticket.didSucceed) {
+ NSLog(@"%@", response);
+ OAToken *requestToken = [[OAToken alloc] initWithHTTPResponseBody:response];
+ [requestToken storeInDefaultKeychainWithAppName:kATutor tokenType:@"requestToken"];
+ NSLog(@"Stored this secret and key: %@ : %@", [requestToken key], [requestToken secret]);
+
+ NSString *urlString = [NSString stringWithFormat:@"%@?oauth_callback=internal://finish-auth&oauth_token=%@",
+ [currentProvider authorizeUrl], [requestToken key]];
+
+ NSLog(@"Request string: %@", urlString);
+
+ [[TTNavigator navigator] openURLAction:[[TTURLAction actionWithURLPath:urlString] applyAnimated:YES]];
+ } else {
+ NSString *error = [NSString stringWithFormat:@"Got error while requesting request token. %@", response];
+ NSLog(@"Error retriving request token: %@", error);
+
+ @throw [NSException exceptionWithName:@"RequestTokenException" reason:error userInfo:nil];
+ }
+}
+
+- (void)getAccessToken {
+ OAToken *requestToken = [[OAToken alloc] initWithKeychainUsingAppName:kATutor
+ tokenType:@"requestToken"];
+ NSLog(@"Getting access token for request token: %@ : %@", [requestToken key], [requestToken secret]);
+
+ OAMutableURLRequest *request = [[[OAMutableURLRequest alloc]
+ initWithURL:[NSURL URLWithString:[currentProvider accessUrl]]
+ consumer:consumer token:requestToken] autorelease];
+ [request setHTTPMethod:@"GET"];
+
+ [OADataFetcher fetchDataWithRequest:request delegate:self
+ didFinishSelector:@selector(accessTokenCallback:didFinishWithResponse:)];
+}
+
+- (void)accessTokenCallback:(OAServiceTicket *)ticket didFinishWithResponse:(id)response {
+ if (ticket.didSucceed) {
+ self.accessToken = [[[OAToken alloc] initWithHTTPResponseBody:response] autorelease];
+ [accessToken storeInDefaultKeychainWithAppName:kATutor tokenType:@"accessToken"];
+
+ NSLog(@"Got an access token: %@ : %@", [accessToken key], [accessToken secret]);
+
+ } else {
+ NSString *error = [NSString stringWithFormat:@"Got error while requesting access token. %@", response];
+ NSLog(@"Error retriving access token: %@", error);
+
+ @throw [NSException exceptionWithName:@"AccessTokenException" reason:error userInfo:nil];
+ }
+}
+
+@end
--- /dev/null
+//
+// OSProvider.h
+// ATutor
+//
+// Created by Quang Anh Do on 29/05/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+@interface OSProvider : NSObject {
+ NSString *requestUrl;
+ NSString *authorizeUrl;
+ NSString *accessUrl;
+ NSString *endpointUrl;
+
+ NSArray *extraRequestUrlParams;
+ BOOL isOpenSocial;
+
+ NSString *consumerKey;
+ NSString *consumerSecret;
+
+ NSString *name;
+}
+
+@property(retain) NSString *requestUrl;
+@property(retain) NSString *authorizeUrl;
+@property(retain) NSString *accessUrl;
+@property(retain) NSString *endpointUrl;
+
+@property(retain) NSArray *extraRequestUrlParams;
+@property BOOL isOpenSocial;
+
+@property(retain) NSString *consumerKey;
+@property(retain) NSString *consumerSecret;
+
+@property(retain) NSString *name;
+
++ (OSProvider *)getATutorProviderWithKey:(NSString *)key withSecret:(NSString *)secret;
+
+@end
--- /dev/null
+//
+// OSProvider.m
+// ATutor
+//
+// Created by Quang Anh Do on 29/05/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import "OSProvider.h"
+#import "OARequestParameter.h"
+
+
+@implementation OSProvider
+
+@synthesize requestUrl, authorizeUrl, accessUrl, endpointUrl, extraRequestUrlParams, isOpenSocial, consumerKey, consumerSecret, name;
+
+- (void)dealloc {
+ [requestUrl release];
+ [authorizeUrl release];
+ [accessUrl release];
+ [endpointUrl release];
+ [consumerKey release];
+ [consumerSecret release];
+ [name release];
+
+ [super dealloc];
+}
+
++ (OSProvider *)getATutorProviderWithKey:(NSString *)key withSecret:(NSString *)secret {
+ OSProvider *atutor = [[[OSProvider alloc] init] autorelease];
+ atutor.requestUrl = [NSString stringWithFormat:@"%@/mods/_standard/social/lib/oauth/request_token.php", kATutorURL];
+ atutor.authorizeUrl = [NSString stringWithFormat:@"%@/mods/_standard/social/lib/oauth/authorize.php", kATutorURL];
+ atutor.accessUrl = [NSString stringWithFormat:@"%@/mods/_standard/social/lib/oauth/access_token.php", kATutorURL];
+ atutor.endpointUrl = [NSString stringWithFormat:@"%@/social/rest", kShindigURL];
+
+ atutor.isOpenSocial = YES;
+
+ atutor.consumerKey = key;
+ atutor.consumerSecret = secret;
+
+ atutor.name = @"ATutor";
+
+ return atutor;
+}
+
+@end
--- /dev/null
+//
+// QAWebController.h
+// ATutor
+//
+// Created by Quang Anh Do on 30/05/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import <Three20/Three20.h>
+
+@protocol QAWebControllerDelegate;
+
+@interface QAWebController : TTWebController {
+ id oAuthDelegate;
+}
+
+@property (nonatomic, assign) id<QAWebControllerDelegate> oAuthDelegate;
+
+@end
+
+@protocol QAWebControllerDelegate
+
+- (void)didFinishAuthorizationInWebViewController:(QAWebController *)webViewController;
+
+@end
+
--- /dev/null
+ //
+// QAWebController.m
+// ATutor
+//
+// Created by Quang Anh Do on 30/05/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import "QAWebController.h"
+
+
+@implementation QAWebController
+
+@synthesize oAuthDelegate;
+
+- (void)dealloc {
+ [oAuthDelegate release];
+
+ [super dealloc];
+}
+
+- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
+ // Ignore normal URLs
+ if (![[[request URL] scheme] isEqualToString:@"internal"]) {
+ return [super webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
+ }
+
+ // OAuth
+ if ([[[request URL] host] isEqualToString:@"finish-auth"]) {
+ if (oAuthDelegate && [oAuthDelegate respondsToSelector:@selector(didFinishAuthorizationInWebViewController:)]) {
+ [oAuthDelegate performSelector:@selector(didFinishAuthorizationInWebViewController:) withObject:self];
+ }
+ }
+
+ return YES;
+}
+
+@end
--- /dev/null
+//
+// StyleSheet.h
+// ATutor
+//
+// Created by Quang Anh Do on 25/05/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <Three20/Three20.h>
+
+@interface StyleSheet : TTDefaultStyleSheet {
+
+}
+
+@end
--- /dev/null
+//
+// StyleSheet.m
+// ATutor
+//
+// Created by Quang Anh Do on 25/05/2010.
+// Copyright 2010 Quang Anh Do. All rights reserved.
+//
+
+#import "StyleSheet.h"
+
+
+@implementation StyleSheet
+
+- (TTStyle*)launcherButton:(UIControlState)state {
+ return
+ [TTPartStyle styleWithName:@"image" style:TTSTYLESTATE(launcherButtonImage:, state) next:
+ [TTTextStyle styleWithFont:[UIFont boldSystemFontOfSize:11] color:[UIColor blackColor]
+ minimumFontSize:11 shadowColor:nil
+ shadowOffset:CGSizeZero next:nil]];
+}
+
+- (TTStyle*)launcherPageDot:(UIControlState)state {
+ if (state != UIControlStateSelected) {
+ return [self pageDotWithColor:[UIColor whiteColor]];
+ } else {
+ return [self pageDotWithColor:[UIColor colorWithRed:0.227 green:0.455 blue:0.647 alpha:1.000]];
+ }
+}
+
+@end
--- /dev/null
+//
+// IASKAppSettingsViewController.h
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <UIKit/UIKit.h>
+
+@class IASKSettingsReader;
+@class IASKAppSettingsViewController;
+
+@protocol IASKSettingsDelegate
+- (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController*)sender;
+@end
+
+
+@interface IASKAppSettingsViewController : UIViewController <UITextFieldDelegate, UINavigationControllerDelegate> {
+ id<IASKSettingsDelegate> _delegate;
+ IBOutlet UITableView *_tableView;
+
+ NSMutableArray *_viewList;
+ NSIndexPath *_currentIndexPath;
+ NSIndexPath *_topmostRowBeforeKeyboardWasShown;
+
+ IASKSettingsReader *_settingsReader;
+ NSString *_file;
+
+ id _currentFirstResponder;
+
+ BOOL _showCreditsFooter;
+ BOOL _showDoneButton;
+}
+
+@property (nonatomic, assign) id delegate;
+@property (nonatomic, retain) NSIndexPath *currentIndexPath;
+@property (nonatomic, retain) IASKSettingsReader *settingsReader;
+@property (nonatomic, copy) NSString *file;
+@property (nonatomic, retain) id currentFirstResponder;
+@property (nonatomic, assign) BOOL showCreditsFooter;
+@property (nonatomic, assign) BOOL showDoneButton;
+
+- (IBAction)dismiss:(id)sender;
+
+// subclassing: optionally override these methods to customize appearance and functionality
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
+- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath;
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
+
+@end
--- /dev/null
+//
+// IASKAppSettingsViewController.m
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009-2010:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+
+#import "IASKAppSettingsViewController.h"
+#import "IASKSettingsReader.h"
+#import "IASKPSToggleSwitchSpecifierViewCell.h"
+#import "IASKPSSliderSpecifierViewCell.h"
+#import "IASKPSTextFieldSpecifierViewCell.h"
+#import "IASKPSTitleValueSpecifierViewCell.h"
+#import "IASKSwitch.h"
+#import "IASKSlider.h"
+#import "IASKSpecifier.h"
+#import "IASKSpecifierValuesViewController.h"
+#import "IASKTextField.h"
+
+static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
+static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
+static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
+
+static NSString *kIASKCredits = @"Powered by InAppSettingsKit"; // Leave this as-is!!!
+
+#define kIASKSpecifierValuesViewControllerIndex 0
+#define kIASKSpecifierChildViewControllerIndex 1
+
+#define kIASKCreditsViewWidth 285
+
+@interface IASKAppSettingsViewController ()
+- (void)_textChanged:(id)sender;
+- (void)_keyboardWillShow:(NSNotification*)notification;
+- (void)_keyboardWillHide:(NSNotification*)notification;
+@end
+
+@implementation IASKAppSettingsViewController
+
+@synthesize delegate = _delegate;
+@synthesize currentIndexPath=_currentIndexPath;
+@synthesize settingsReader = _settingsReader;
+@synthesize file = _file;
+@synthesize currentFirstResponder = _currentFirstResponder;
+@synthesize showCreditsFooter = _showCreditsFooter;
+@synthesize showDoneButton = _showDoneButton;
+
+#pragma mark accessors
+- (IASKSettingsReader*)settingsReader {
+ if (!_settingsReader) {
+ _settingsReader = [[IASKSettingsReader alloc] initWithFile:self.file];
+ }
+ return _settingsReader;
+}
+
+- (NSString*)file {
+ if (!_file) {
+ return @"Root";
+ }
+ return [[_file retain] autorelease];
+}
+
+- (void)setFile:(NSString *)file {
+ if (file != _file) {
+ [_file release];
+ _file = [file copy];
+ }
+
+ self.settingsReader = nil; // automatically initializes itself
+}
+
+#pragma mark standard view controller methods
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
+ if ([super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
+ // If set to YES, will display credits for InAppSettingsKit creators
+ _showCreditsFooter = YES;
+
+ // If set to YES, will add a DONE button at the right of the navigation bar
+ _showDoneButton = NO;
+ }
+ return self;
+}
+
+- (void)awakeFromNib {
+ // If set to YES, will display credits for InAppSettingsKit creators
+ _showCreditsFooter = YES;
+
+ // If set to YES, will add a DONE button at the right of the navigation bar
+ // if loaded via NIB, it's likely we sit in a TabBar- or NavigationController
+ // and thus don't need the Done button
+ _showDoneButton = NO;
+}
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ // Add views
+ _viewList = [[NSMutableArray alloc] init];
+ [_viewList addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"IASKSpecifierValuesView", @"ViewName",nil]];
+ [_viewList addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"IASKAppSettingsView", @"ViewName",nil]];
+
+}
+
+- (void)viewDidUnload {
+ // Release any retained subviews of the main view.
+ // e.g. self.myOutlet = nil;
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+ if (_tableView) {
+ [_tableView reloadData];
+ _tableView.frame = self.view.bounds;
+ }
+
+ self.navigationItem.rightBarButtonItem = nil;
+ self.navigationController.delegate = nil;
+ if ([self.file isEqualToString:@"Root"]) {
+ self.navigationController.delegate = self;
+ if (_showDoneButton) {
+ UIBarButtonItem *buttonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
+ target:self
+ action:@selector(dismiss:)];
+ self.navigationItem.rightBarButtonItem = buttonItem;
+ [buttonItem release];
+ }
+ if (!self.title) {
+ self.title = NSLocalizedString(@"Settings", @"");
+ }
+ }
+ [super viewWillAppear:animated];
+}
+
+- (void)viewDidAppear:(BOOL)animated {
+ [_tableView flashScrollIndicators];
+// _tableView.frame = self.view.bounds;
+ [super viewDidAppear:animated];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(_keyboardWillShow:)
+ name:UIKeyboardWillShowNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(_keyboardWillHide:)
+ name:UIKeyboardWillHideNotification
+ object:nil];
+}
+
+- (void)viewWillDisappear:(BOOL)animated {
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
+ if ([self.currentFirstResponder canResignFirstResponder]) {
+ [self.currentFirstResponder resignFirstResponder];
+ }
+ [super viewWillDisappear:animated];
+}
+
+- (void)viewDidDisappear:(BOOL)animated {
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
+ [super viewDidDisappear:animated];
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
+ return (interfaceOrientation == UIInterfaceOrientationPortrait) || (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
+}
+
+- (void)didReceiveMemoryWarning {
+ // Releases the view if it doesn't have a superview.
+ [super didReceiveMemoryWarning];
+
+ // Release any cached data, images, etc that aren't in use.
+}
+
+- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
+ if (![viewController isKindOfClass:[IASKAppSettingsViewController class]] && ![viewController isKindOfClass:[IASKSpecifierValuesViewController class]]) {
+ [self dismiss:nil];
+ }
+}
+
+- (void)dealloc {
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ [_viewList release];
+ [_currentIndexPath release];
+ [_file release];
+ _file = nil;
+
+ [_currentFirstResponder release];
+ _currentFirstResponder = nil;
+
+ self.settingsReader = nil;
+ _delegate = nil;
+
+ [super dealloc];
+}
+
+
+#pragma mark -
+#pragma mark Actions
+
+- (IBAction)dismiss:(id)sender {
+ if ([self.currentFirstResponder canResignFirstResponder]) {
+ [self.currentFirstResponder resignFirstResponder];
+ }
+
+ self.navigationController.delegate = nil;
+
+ if (self.delegate && [self.delegate conformsToProtocol:@protocol(IASKSettingsDelegate)]) {
+ [self.delegate settingsViewControllerDidEnd:self];
+ }
+}
+
+- (void)toggledValue:(id)sender {
+ IASKSwitch *toggle = (IASKSwitch*)sender;
+ IASKSpecifier *spec = [_settingsReader specifierForKey:[toggle key]];
+
+ if ([toggle isOn]) {
+ if ([spec trueValue] != nil) {
+ [[NSUserDefaults standardUserDefaults] setObject:[spec trueValue] forKey:[toggle key]];
+ }
+ else {
+ [[NSUserDefaults standardUserDefaults] setBool:YES forKey:[toggle key]];
+ }
+ }
+ else {
+ if ([spec falseValue] != nil) {
+ [[NSUserDefaults standardUserDefaults] setObject:[spec falseValue] forKey:[toggle key]];
+ }
+ else {
+ [[NSUserDefaults standardUserDefaults] setBool:NO forKey:[toggle key]];
+ }
+ }
+ [[NSNotificationCenter defaultCenter] postNotificationName:kIASKAppSettingChanged object:[toggle key]];
+}
+
+- (void)sliderChangedValue:(id)sender {
+ IASKSlider *slider = (IASKSlider*)sender;
+ [[NSUserDefaults standardUserDefaults] setFloat:[slider value] forKey:[slider key]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:kIASKAppSettingChanged object:[slider key]];
+}
+
+
+#pragma mark -
+#pragma mark UITableView Functions
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+ return [self.settingsReader numberOfSections];
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+ return [self.settingsReader numberOfRowsForSection:section];
+}
+
+- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
+ return [self.settingsReader titleForSection:section];
+}
+
+- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
+ if (!_showCreditsFooter || section != [self.settingsReader numberOfSections]-1) return nil;
+
+ // Show the credits only in the last section's footer
+ UILabel *credits = [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, kIASKCreditsViewWidth, 0)] autorelease];
+ [credits setOpaque:NO];
+ [credits setNumberOfLines:0];
+ [credits setFont:[UIFont systemFontOfSize:14.0f]];
+ [credits setTextAlignment:UITextAlignmentRight];
+ [credits setTextColor:[UIColor colorWithRed:77.0f/255.0f green:87.0f/255.0f blue:107.0f/255.0f alpha:1.0f]];
+ [credits setShadowColor:[UIColor whiteColor]];
+ [credits setShadowOffset:CGSizeMake(0, 1)];
+ [credits setBackgroundColor:[UIColor clearColor]];
+ [credits setText:kIASKCredits];
+ [credits sizeToFit];
+
+ UIView* view = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, kIASKCreditsViewWidth, credits.frame.size.height + 6 + 11)] autorelease];
+ [view setBackgroundColor:[UIColor clearColor]];
+
+ CGRect frame = credits.frame;
+ frame.origin.y = 8;
+ frame.origin.x = 16;
+ frame.size.width = kIASKCreditsViewWidth;
+ credits.frame = frame;
+
+ [view addSubview:credits];
+ [view sizeToFit];
+
+ return view;
+}
+
+- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
+ if (!_showCreditsFooter || section != [self.settingsReader numberOfSections]-1) return 0.0f;
+
+ UIView* view = [self tableView:tableView viewForFooterInSection:section];
+ if (view != nil) {
+ return view.frame.size.height;
+ }
+ return -1;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+ IASKSpecifier *specifier = [self.settingsReader specifierForIndexPath:indexPath];
+ NSString *key = [specifier key];
+
+ if ([[specifier type] isEqualToString:kIASKPSToggleSwitchSpecifier]) {
+ IASKPSToggleSwitchSpecifierViewCell *cell = (IASKPSToggleSwitchSpecifierViewCell*)[tableView dequeueReusableCellWithIdentifier:[specifier type]];
+
+ if (!cell) {
+ cell = (IASKPSToggleSwitchSpecifierViewCell*) [[[NSBundle mainBundle] loadNibNamed:@"IASKPSToggleSwitchSpecifierViewCell"
+ owner:self
+ options:nil] objectAtIndex:0];
+ }
+ [[cell label] setText:[specifier title]];
+
+ id currentValue = [[NSUserDefaults standardUserDefaults] objectForKey:key];
+ BOOL toggleState;
+ if (currentValue) {
+ if ([currentValue isEqual:[specifier trueValue]]) {
+ toggleState = YES;
+ } else if ([currentValue isEqual:[specifier falseValue]]) {
+ toggleState = NO;
+ } else {
+ toggleState = [currentValue boolValue];
+ }
+ } else {
+ toggleState = [specifier defaultBoolValue];
+ }
+ [[cell toggle] setOn:toggleState];
+
+ [[cell toggle] addTarget:self action:@selector(toggledValue:) forControlEvents:UIControlEventValueChanged];
+ [[cell toggle] setKey:key];
+ return cell;
+ }
+ else if ([[specifier type] isEqualToString:kIASKPSMultiValueSpecifier]) {
+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[specifier type]];
+
+ if (!cell) {
+ cell = [[[IASKPSTitleValueSpecifierViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:[specifier type]] autorelease];
+ cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
+ }
+ [[cell textLabel] setText:[specifier title]];
+ [[cell detailTextLabel] setText:[[specifier titleForCurrentValue:[[NSUserDefaults standardUserDefaults] objectForKey:key] != nil ?
+ [[NSUserDefaults standardUserDefaults] objectForKey:key] : [specifier defaultValue]] description]];
+ return cell;
+ }
+ else if ([[specifier type] isEqualToString:kIASKPSTitleValueSpecifier]) {
+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[specifier type]];
+
+ if (!cell) {
+ cell = [[[IASKPSTitleValueSpecifierViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:[specifier type]] autorelease];
+ cell.accessoryType = UITableViewCellAccessoryNone;
+ }
+
+ cell.textLabel.text = [specifier title];
+ id value = [[NSUserDefaults standardUserDefaults] objectForKey:key] ? : [specifier defaultValue];
+
+ NSString *stringValue;
+ if ([specifier multipleValues] || [specifier multipleTitles]) {
+ stringValue = [specifier titleForCurrentValue:value];
+ } else {
+ stringValue = [value description];
+ }
+
+ cell.detailTextLabel.text = stringValue;
+ [cell setUserInteractionEnabled:NO];
+
+ return cell;
+ }
+ else if ([[specifier type] isEqualToString:kIASKPSTextFieldSpecifier]) {
+ IASKPSTextFieldSpecifierViewCell *cell = (IASKPSTextFieldSpecifierViewCell*)[tableView dequeueReusableCellWithIdentifier:[specifier type]];
+
+ if (!cell) {
+ cell = (IASKPSTextFieldSpecifierViewCell*) [[[NSBundle mainBundle] loadNibNamed:@"IASKPSTextFieldSpecifierViewCell"
+ owner:self
+ options:nil] objectAtIndex:0];
+ cell.textField.textAlignment = UITextAlignmentLeft;
+ cell.textField.returnKeyType = UIReturnKeyDone;
+ cell.accessoryType = UITableViewCellAccessoryNone;
+ }
+ [[cell label] setText:[specifier title]];
+ [[cell textField] setText:[[NSUserDefaults standardUserDefaults] objectForKey:key] != nil ?
+ [[NSUserDefaults standardUserDefaults] objectForKey:key] : [specifier defaultStringValue]];
+ [[cell textField] setKey:key];
+ [[cell textField] setDelegate:self];
+ [[cell textField] addTarget:self action:@selector(_textChanged:) forControlEvents:UIControlEventEditingChanged];
+ [[cell textField] setSecureTextEntry:[specifier isSecure]];
+ [[cell textField] setKeyboardType:[specifier keyboardType]];
+ [[cell textField] setAutocapitalizationType:[specifier autocapitalizationType]];
+ [[cell textField] setAutocorrectionType:[specifier autoCorrectionType]];
+ [cell setNeedsLayout];
+ return cell;
+ }
+ else if ([[specifier type] isEqualToString:kIASKPSSliderSpecifier]) {
+ IASKPSSliderSpecifierViewCell *cell = (IASKPSSliderSpecifierViewCell*)[tableView dequeueReusableCellWithIdentifier:[specifier type]];
+
+ if (!cell) {
+ cell = (IASKPSSliderSpecifierViewCell*) [[[NSBundle mainBundle] loadNibNamed:@"IASKPSSliderSpecifierViewCell"
+ owner:self
+ options:nil] objectAtIndex:0];
+ }
+
+ if ([[specifier minimumValueImage] length] > 0) {
+ [[cell minImage] setImage:[UIImage imageWithContentsOfFile:[_settingsReader pathForImageNamed:[specifier minimumValueImage]]]];
+ }
+
+ if ([[specifier maximumValueImage] length] > 0) {
+ [[cell maxImage] setImage:[UIImage imageWithContentsOfFile:[_settingsReader pathForImageNamed:[specifier maximumValueImage]]]];
+ }
+
+ [[cell slider] setMinimumValue:[specifier minimumValue]];
+ [[cell slider] setMaximumValue:[specifier maximumValue]];
+ [[cell slider] setValue:[[NSUserDefaults standardUserDefaults] objectForKey:key] != nil ?
+ [[[NSUserDefaults standardUserDefaults] objectForKey:key] floatValue] : [[specifier defaultValue] floatValue]];
+ [[cell slider] addTarget:self action:@selector(sliderChangedValue:) forControlEvents:UIControlEventValueChanged];
+ [[cell slider] setKey:key];
+ [cell setNeedsLayout];
+ return cell;
+ }
+ else if ([[specifier type] isEqualToString:kIASKPSChildPaneSpecifier]) {
+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[specifier type]];
+
+ if (!cell) {
+ cell = [[[IASKPSTitleValueSpecifierViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:[specifier type]] autorelease];
+ [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
+ }
+
+ [[cell textLabel] setText:[specifier title]];
+ return cell;
+ } else if ([[specifier type] isEqualToString:kIASKOpenURLSpecifier]) {
+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[specifier type]];
+
+ if (!cell) {
+ cell = [[[IASKPSTitleValueSpecifierViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:[specifier type]] autorelease];
+ [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
+ }
+
+ cell.textLabel.text = [specifier title];
+ cell.detailTextLabel.text = [[specifier defaultValue] description];
+ return cell;
+ } else {
+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[specifier type]];
+
+ if (!cell) {
+ cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[specifier type]] autorelease];
+ }
+ [[cell textLabel] setText:[specifier title]];
+ return cell;
+ }
+}
+
+- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+ IASKSpecifier *specifier = [self.settingsReader specifierForIndexPath:indexPath];
+
+ if ([[specifier type] isEqualToString:kIASKPSToggleSwitchSpecifier]) {
+ return nil;
+ } else {
+ return indexPath;
+ }
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+ IASKSpecifier *specifier = [self.settingsReader specifierForIndexPath:indexPath];
+
+ if ([[specifier type] isEqualToString:kIASKPSToggleSwitchSpecifier]) {
+ [tableView deselectRowAtIndexPath:indexPath animated:NO];
+ }
+ else if ([[specifier type] isEqualToString:kIASKPSMultiValueSpecifier]) {
+ IASKSpecifierValuesViewController *targetViewController = [[_viewList objectAtIndex:kIASKSpecifierValuesViewControllerIndex] objectForKey:@"viewController"];
+
+ if (targetViewController == nil) {
+ // the view controller has not been created yet, create it and set it to our viewList array
+ // create a new dictionary with the new view controller
+ NSMutableDictionary *newItemDict = [NSMutableDictionary dictionaryWithCapacity:3];
+ [newItemDict addEntriesFromDictionary: [_viewList objectAtIndex:kIASKSpecifierValuesViewControllerIndex]]; // copy the title and explain strings
+
+ targetViewController = [[IASKSpecifierValuesViewController alloc] initWithNibName:@"IASKSpecifierValuesView" bundle:nil];
+
+ // add the new view controller to the dictionary and then to the 'viewList' array
+ [newItemDict setObject:targetViewController forKey:@"viewController"];
+ [_viewList replaceObjectAtIndex:kIASKSpecifierValuesViewControllerIndex withObject:newItemDict];
+ [targetViewController release];
+
+ // load the view controll back in to push it
+ targetViewController = [[_viewList objectAtIndex:kIASKSpecifierValuesViewControllerIndex] objectForKey:@"viewController"];
+ }
+ _currentIndexPath = indexPath;
+ [targetViewController setCurrentSpecifier:specifier];
+ targetViewController.settingsReader = self.settingsReader;
+ [[self navigationController] pushViewController:targetViewController animated:YES];
+ }
+ else if ([[specifier type] isEqualToString:kIASKPSSliderSpecifier]) {
+ [tableView deselectRowAtIndexPath:indexPath animated:NO];
+ }
+ else if ([[specifier type] isEqualToString:kIASKPSTextFieldSpecifier]) {
+ IASKPSTextFieldSpecifierViewCell *textFieldCell = (id)[tableView cellForRowAtIndexPath:indexPath];
+ [textFieldCell.textField becomeFirstResponder];
+ }
+ else if ([[specifier type] isEqualToString:kIASKPSChildPaneSpecifier]) {
+ IASKAppSettingsViewController *targetViewController = [[_viewList objectAtIndex:kIASKSpecifierChildViewControllerIndex] objectForKey:@"viewController"];
+
+ if (targetViewController == nil) {
+ // the view controller has not been created yet, create it and set it to our viewList array
+ // create a new dictionary with the new view controller
+ NSMutableDictionary *newItemDict = [NSMutableDictionary dictionaryWithCapacity:3];
+ [newItemDict addEntriesFromDictionary: [_viewList objectAtIndex:kIASKSpecifierChildViewControllerIndex]]; // copy the title and explain strings
+
+ targetViewController = [[[self class] alloc] initWithNibName:@"IASKAppSettingsView" bundle:nil];
+
+ // add the new view controller to the dictionary and then to the 'viewList' array
+ [newItemDict setObject:targetViewController forKey:@"viewController"];
+ [_viewList replaceObjectAtIndex:kIASKSpecifierChildViewControllerIndex withObject:newItemDict];
+ [targetViewController release];
+
+ // load the view controll back in to push it
+ targetViewController = [[_viewList objectAtIndex:kIASKSpecifierChildViewControllerIndex] objectForKey:@"viewController"];
+ }
+ _currentIndexPath = indexPath;
+ targetViewController.file = specifier.file;
+ targetViewController.title = specifier.title;
+ targetViewController.showCreditsFooter = NO;
+ [[self navigationController] pushViewController:targetViewController animated:YES];
+ } else if ([[specifier type] isEqualToString:kIASKOpenURLSpecifier]) {
+ [tableView deselectRowAtIndexPath:indexPath animated:YES];
+ [[UIApplication sharedApplication] openURL:[NSURL URLWithString:specifier.file]];
+ } else {
+ [tableView deselectRowAtIndexPath:indexPath animated:NO];
+ }
+}
+
+
+#pragma mark -
+#pragma mark UITextFieldDelegate Functions
+
+- (void)_textChanged:(id)sender {
+ IASKTextField *text = (IASKTextField*)sender;
+ [[NSUserDefaults standardUserDefaults] setObject:[text text] forKey:[text key]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:kIASKAppSettingChanged object:[text key]];
+}
+
+- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
+ [textField setTextAlignment:UITextAlignmentLeft];
+ self.currentFirstResponder = textField;
+ return YES;
+}
+
+- (void)textFieldDidBeginEditing:(UITextField *)textField {
+ if ([_tableView indexPathsForVisibleRows].count) {
+ _topmostRowBeforeKeyboardWasShown = (NSIndexPath*)[[_tableView indexPathsForVisibleRows] objectAtIndex:0];
+ } else {
+ // this should never happen
+ _topmostRowBeforeKeyboardWasShown = [NSIndexPath indexPathForRow:0 inSection:0];
+ [textField resignFirstResponder];
+ }
+}
+
+- (void)textFieldDidEndEditing:(UITextField *)textField {
+ self.currentFirstResponder = nil;
+}
+
+- (BOOL)textFieldShouldReturn:(UITextField *)textField{
+ [textField resignFirstResponder];
+ return YES;
+}
+
+#pragma mark Keyboard Management
+- (void)_keyboardWillShow:(NSNotification*)notification {
+ if (self.navigationController.topViewController == self) {
+ NSDictionary* userInfo = [notification userInfo];
+
+ // we don't use SDK constants here to be universally compatible with all SDKs ≥ 3.0
+ NSValue* keyboardFrameValue = [userInfo objectForKey:@"UIKeyboardBoundsUserInfoKey"];
+ if (!keyboardFrameValue) {
+ keyboardFrameValue = [userInfo objectForKey:@"UIKeyboardFrameEndUserInfoKey"];
+ }
+
+ // Reduce the tableView height by the part of the keyboard that actually covers the tableView
+ CGRect windowRect = [[UIApplication sharedApplication] keyWindow].bounds;
+ CGRect viewRectAbsolute = [_tableView convertRect:_tableView.bounds toView:[[UIApplication sharedApplication] keyWindow]];
+ CGRect frame = _tableView.frame;
+ frame.size.height -= [keyboardFrameValue CGRectValue].size.height - CGRectGetMaxY(windowRect) + CGRectGetMaxY(viewRectAbsolute);
+
+ [UIView beginAnimations:nil context:NULL];
+ [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
+ [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
+ _tableView.frame = frame;
+ [UIView commitAnimations];
+
+ UITableViewCell *textFieldCell = (id)((UITextField *)self.currentFirstResponder).superview.superview;
+ NSIndexPath *textFieldIndexPath = [_tableView indexPathForCell:textFieldCell];
+
+ // iOS 3 sends hide and show notifications right after each other
+ // when switching between textFields, so cancel -scrollToOldPosition requests
+ [NSObject cancelPreviousPerformRequestsWithTarget:self];
+
+ [_tableView scrollToRowAtIndexPath:textFieldIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
+ }
+}
+
+- (void) scrollToOldPosition {
+ [_tableView scrollToRowAtIndexPath:_topmostRowBeforeKeyboardWasShown atScrollPosition:UITableViewScrollPositionTop animated:YES];
+}
+
+- (void)_keyboardWillHide:(NSNotification*)notification {
+ if (self.navigationController.topViewController == self) {
+ NSDictionary* userInfo = [notification userInfo];
+
+ [UIView beginAnimations:nil context:NULL];
+ [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
+ [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
+ _tableView.frame = self.view.bounds;
+ [UIView commitAnimations];
+
+ [self performSelector:@selector(scrollToOldPosition) withObject:nil afterDelay:0.1];
+ }
+}
+@end
--- /dev/null
+//
+// IASKSpecifierValuesViewController.h
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <UIKit/UIKit.h>
+
+@class IASKSpecifier;
+@class IASKSettingsReader;
+
+@interface IASKSpecifierValuesViewController : UIViewController {
+ IBOutlet UITableView *_tableView;
+
+ IASKSpecifier *_currentSpecifier;
+ NSIndexPath *_checkedItem;
+ IASKSettingsReader *_settingsReader;
+}
+
+@property (nonatomic, retain) NSIndexPath *checkedItem;
+@property (nonatomic, retain) IASKSpecifier *currentSpecifier;
+@property (nonatomic, retain) IASKSettingsReader *settingsReader;
+
+@end
--- /dev/null
+//
+// IASKSpecifierValuesViewController.m
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKSpecifierValuesViewController.h"
+#import "IASKSpecifier.h"
+#import "IASKSettingsReader.h"
+
+#define kCellValue @"kCellValue"
+
+@implementation IASKSpecifierValuesViewController
+
+@synthesize currentSpecifier=_currentSpecifier;
+@synthesize checkedItem=_checkedItem;
+@synthesize settingsReader = _settingsReader;
+
+/*
+ // The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
+ if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
+ // Custom initialization
+ }
+ return self;
+}
+*/
+
+
+/*- (void)viewDidLoad {
+ [super viewDidLoad];
+}*/
+
+- (void)viewWillAppear:(BOOL)animated {
+ if (_currentSpecifier) {
+ [self setTitle:[_currentSpecifier title]];
+ }
+
+ if (_tableView) {
+ [_tableView reloadData];
+ }
+ [super viewWillAppear:animated];
+}
+
+- (void)viewDidAppear:(BOOL)animated {
+ [_tableView flashScrollIndicators];
+ [super viewDidAppear:animated];
+}
+
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
+ return (interfaceOrientation == UIInterfaceOrientationPortrait) || (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
+}
+
+- (void)didReceiveMemoryWarning {
+ // Releases the view if it doesn't have a superview.
+ [super didReceiveMemoryWarning];
+
+ // Release any cached data, images, etc that aren't in use.
+}
+
+- (void)viewDidUnload {
+ // Release any retained subviews of the main view.
+ // e.g. self.myOutlet = nil;
+}
+
+
+- (void)dealloc {
+ [_currentSpecifier release];
+ [_settingsReader release];
+ _settingsReader = nil;
+
+ [super dealloc];
+}
+
+
+#pragma mark -
+#pragma mark UITableView delegates
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+ return 1;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+ return [_currentSpecifier multipleValuesCount];
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellValue];
+ NSArray *values = [_currentSpecifier multipleValues];
+ NSArray *titles = [_currentSpecifier multipleTitles];
+
+ if (!cell) {
+ cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellValue] autorelease];
+ }
+
+ if ([[NSUserDefaults standardUserDefaults] objectForKey:[_currentSpecifier key]] ?
+ [[[NSUserDefaults standardUserDefaults] objectForKey:[_currentSpecifier key]] isEqual:[values objectAtIndex:indexPath.row]] :
+ [[_currentSpecifier defaultValue] isEqual:[values objectAtIndex:indexPath.row]]) {
+ [self setCheckedItem:indexPath];
+ [cell setAccessoryType:UITableViewCellAccessoryCheckmark];
+ }
+ else {
+ [cell setAccessoryType:UITableViewCellAccessoryNone];
+ }
+
+ @try {
+ [[cell textLabel] setText:[self.settingsReader titleForStringId:[titles objectAtIndex:indexPath.row]]];
+ }
+ @catch (NSException * e) {}
+ return cell;
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+ if (indexPath == [self checkedItem]) {
+ [tableView deselectRowAtIndexPath:indexPath animated:YES];
+ return;
+ }
+
+ NSArray *values = [_currentSpecifier multipleValues];
+
+ [tableView deselectRowAtIndexPath:indexPath animated:YES];
+ [[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark];
+ [[tableView cellForRowAtIndexPath:[self checkedItem]] setAccessoryType:UITableViewCellAccessoryNone];
+ [self setCheckedItem:indexPath];
+
+ [[NSUserDefaults standardUserDefaults] setObject:[values objectAtIndex:indexPath.row] forKey:[_currentSpecifier key]];
+ [[NSNotificationCenter defaultCenter] postNotificationName:kIASKAppSettingChanged object:[_currentSpecifier key]];
+}
+
+
+@end
--- /dev/null
+//
+// IASKSettingsReader.h
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <Foundation/Foundation.h>
+
+#define kIASKPreferenceSpecifiers @"PreferenceSpecifiers"
+#define kIASKType @"Type"
+#define kIASKTitle @"Title"
+#define kIASKKey @"Key"
+#define kIASKFile @"File"
+#define kIASKDefaultValue @"DefaultValue"
+#define kIASKMinimumValue @"MinimumValue"
+#define kIASKMaximumValue @"MaximumValue"
+#define kIASKTrueValue @"TrueValue"
+#define kIASKFalseValue @"FalseValue"
+#define kIASKIsSecure @"IsSecure"
+#define KIASKKeyboardType @"KeyboardType"
+#define kIASKAutocapitalizationType @"AutocapitalizationType"
+#define kIASKAutoCorrectionType @"AutocorrectionType"
+#define kIASKValues @"Values"
+#define kIASKTitles @"Titles"
+#define kIASKKeyboardAlphabet @"Alphabet"
+#define kIASKKeyboardNumbersAndPunctuation @"NumbersAndPunctuation"
+#define kIASKKeyboardNumberPad @"NumberPad"
+#define KIASKKeyboardURL @"URL"
+#define kIASKKeyboardEmailAddress @"EmailAddress"
+#define kIASKAutoCapNone @"None"
+#define kIASKAutoCapSentences @"Sentences"
+#define kIASKAutoCapWords @"Words"
+#define kIASKAutoCapAllCharacters @"AllCharacters"
+#define kIASKAutoCorrDefault @"Default"
+#define kIASKAutoCorrNo @"No"
+#define kIASKAutoCorrYes @"Yes"
+#define kIASKMinimumValueImage @"MinimumValueImage"
+#define kIASKMaximumValueImage @"MaximumValueImage"
+
+#define kIASKPSGroupSpecifier @"PSGroupSpecifier"
+#define kIASKPSToggleSwitchSpecifier @"PSToggleSwitchSpecifier"
+#define kIASKPSMultiValueSpecifier @"PSMultiValueSpecifier"
+#define kIASKPSSliderSpecifier @"PSSliderSpecifier"
+#define kIASKPSTitleValueSpecifier @"PSTitleValueSpecifier"
+#define kIASKPSTextFieldSpecifier @"PSTextFieldSpecifier"
+#define kIASKPSChildPaneSpecifier @"PSChildPaneSpecifier"
+#define kIASKOpenURLSpecifier @"IASKOpenURLSpecifier"
+
+#define kIASKBundleFolder @"Settings.bundle"
+#define kIASKBundleFolderAlt @"InAppSettings.bundle"
+#define kIASKBundleFilename @"Root.plist"
+
+#define kIASKAppSettingChanged @"kAppSettingChanged"
+
+#define kIASKSectionHeaderIndex 0
+
+#define kIASKSliderNoImagesX 21
+#define kIASKSliderNoImagesWidth 278
+#define kIASKSliderBothImagesX 53
+#define kIASKSliderBothImagesWidth 214
+#define kIASKSliderOneImageWidth 246
+
+#define kIASKTableWidth 320
+#define kIASKSpacing 5
+#define kIASKMinLabelWidth 97
+#define kIASKMinValueWidth 35
+#define kIASKPaddingLeft 9
+#define kIASKPaddingRight 10
+
+#define kIASKLabelFontSize 17
+
+@class IASKSpecifier;
+
+@interface IASKSettingsReader : NSObject {
+ NSString *_path;
+ NSString *_bundleFolder;
+ NSDictionary *_settingsBundle;
+ NSArray *_dataSource;
+ NSBundle *_bundle;
+}
+
+- (id)initWithFile:(NSString*)file;
+- (NSInteger)numberOfSections;
+- (NSInteger)numberOfRowsForSection:(NSInteger)section;
+- (IASKSpecifier*)specifierForIndexPath:(NSIndexPath*)indexPath;
+- (IASKSpecifier*)specifierForKey:(NSString*)key;
+- (NSString*)titleForSection:(NSInteger)section;
+- (NSString*)titleForStringId:(NSString*)stringId;
+- (NSString*)bundlePath;
+- (NSString*)pathForImageNamed:(NSString*)image;
+
+@property (nonatomic, retain) NSString *path;
+@property (nonatomic, retain) NSString *bundleFolder;
+@property (nonatomic, retain) NSDictionary *settingsBundle;
+@property (nonatomic, retain) NSArray *dataSource;
+
+@end
--- /dev/null
+//
+// IASKSettingsReader.m
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKSettingsReader.h"
+#import "IASKSpecifier.h"
+
+@interface IASKSettingsReader (private)
+- (void)_reinterpretBundle:(NSDictionary*)settingsBundle;
+- (BOOL)_sectionHasHeading:(NSInteger)section;
+@end
+
+@implementation IASKSettingsReader
+
+@synthesize path=_path,
+bundleFolder=_bundleFolder,
+settingsBundle=_settingsBundle,
+dataSource=_dataSource;
+
+- (id)init {
+ return [self initWithFile:@"Root"];
+}
+
+- (id)initWithFile:(NSString*)file {
+ if ((self=[super init])) {
+ [self setBundleFolder:kIASKBundleFolderAlt];
+ // Generate the settings bundle path
+ NSString *path = [self bundlePath];
+
+ // Try both bundle folders
+ for (int i=0;i<2;i++) {
+ [self setPath:[path stringByAppendingPathComponent:[file stringByAppendingString:@".inApp.plist"]]];
+ [self setSettingsBundle:[NSDictionary dictionaryWithContentsOfFile:[self path]]];
+ if (!self.settingsBundle) {
+ [self setPath:[path stringByAppendingPathComponent:[file stringByAppendingString:@".plist"]]];
+ [self setSettingsBundle:[NSDictionary dictionaryWithContentsOfFile:[self path]]];
+ }
+ if (self.settingsBundle)
+ break;
+ [self setBundleFolder:kIASKBundleFolder];
+ path = [self bundlePath];
+ }
+ _bundle = [[NSBundle bundleWithPath:path] retain];
+
+ if (_settingsBundle) {
+ [self _reinterpretBundle:_settingsBundle];
+ }
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [_path release];
+ [_settingsBundle release];
+ [_dataSource release];
+ [_bundle release];
+ [super dealloc];
+}
+
+- (void)_reinterpretBundle:(NSDictionary*)settingsBundle {
+ NSArray *preferenceSpecifiers = [settingsBundle objectForKey:kIASKPreferenceSpecifiers];
+ NSInteger sectionCount = -1;
+ NSMutableArray *dataSource = [[[NSMutableArray alloc] init] autorelease];
+
+ for (NSDictionary *specifier in preferenceSpecifiers) {
+ if ([(NSString*)[specifier objectForKey:kIASKType] isEqualToString:kIASKPSGroupSpecifier]) {
+ NSMutableArray *newArray = [[NSMutableArray alloc] init];
+
+ [newArray addObject:specifier];
+ [dataSource addObject:newArray];
+ [newArray release];
+ sectionCount++;
+ }
+ else {
+ if (sectionCount == -1) {
+ NSMutableArray *newArray = [[NSMutableArray alloc] init];
+ [dataSource addObject:newArray];
+ [newArray release];
+ sectionCount++;
+ }
+
+ IASKSpecifier *newSpecifier = [[IASKSpecifier alloc] initWithSpecifier:specifier];
+ [(NSMutableArray*)[dataSource objectAtIndex:sectionCount] addObject:newSpecifier];
+ [newSpecifier release];
+ }
+ }
+ [self setDataSource:dataSource];
+}
+
+- (BOOL)_sectionHasHeading:(NSInteger)section {
+ return [[[[self dataSource] objectAtIndex:section] objectAtIndex:0] isKindOfClass:[NSDictionary class]];
+}
+
+- (NSInteger)numberOfSections {
+ return [[self dataSource] count];
+}
+
+- (NSInteger)numberOfRowsForSection:(NSInteger)section {
+ int headingCorrection = [self _sectionHasHeading:section] ? 1 : 0;
+ return [(NSArray*)[[self dataSource] objectAtIndex:section] count] - headingCorrection;
+}
+
+- (IASKSpecifier*)specifierForIndexPath:(NSIndexPath*)indexPath {
+ int headingCorrection = [self _sectionHasHeading:indexPath.section] ? 1 : 0;
+
+ IASKSpecifier *specifier = [[[self dataSource] objectAtIndex:indexPath.section] objectAtIndex:(indexPath.row+headingCorrection)];
+ specifier.settingsReader = self;
+ return specifier;
+}
+
+- (IASKSpecifier*)specifierForKey:(NSString*)key {
+ for (NSArray *specifiers in _dataSource) {
+ for (id sp in specifiers) {
+ if ([sp isKindOfClass:[IASKSpecifier class]]) {
+ if ([[sp key] isEqualToString:key]) {
+ return sp;
+ }
+ }
+ }
+ }
+ return nil;
+}
+
+- (NSString*)titleForSection:(NSInteger)section {
+ if ([self _sectionHasHeading:section]) {
+ NSDictionary *dict = [[[self dataSource] objectAtIndex:section] objectAtIndex:kIASKSectionHeaderIndex];
+ return [_bundle localizedStringForKey:[dict objectForKey:kIASKTitle] value:[dict objectForKey:kIASKTitle] table:@"Root"];
+ }
+ return nil;
+}
+
+- (NSString*)titleForStringId:(NSString*)stringId {
+ return [_bundle localizedStringForKey:stringId value:stringId table:@"Root"];
+}
+
+- (NSString*)bundlePath {
+ NSString *libDirectory = [[NSBundle mainBundle] bundlePath];
+ return [libDirectory stringByAppendingPathComponent:_bundleFolder];
+}
+
+- (NSString*)pathForImageNamed:(NSString*)image {
+ return [[self bundlePath] stringByAppendingPathComponent:image];
+}
+
+@end
--- /dev/null
+//
+// IASKSpecifier.h
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <Foundation/Foundation.h>
+
+@class IASKSettingsReader;
+
+@interface IASKSpecifier : NSObject {
+ NSDictionary *_specifierDict;
+ NSDictionary *_multipleValuesDict;
+ IASKSettingsReader *_settingsReader;
+}
+@property (nonatomic, retain) NSDictionary *specifierDict;
+@property (nonatomic, assign) IASKSettingsReader *settingsReader;
+
+- (id)initWithSpecifier:(NSDictionary*)specifier;
+- (NSString*)title;
+- (NSString*)key;
+- (NSString*)type;
+- (NSString*)titleForCurrentValue:(id)currentValue;
+- (NSInteger)multipleValuesCount;
+- (NSArray*)multipleValues;
+- (NSArray*)multipleTitles;
+- (NSString*)file;
+- (id)defaultValue;
+- (id)defaultStringValue;
+- (BOOL)defaultBoolValue;
+- (id)trueValue;
+- (id)falseValue;
+- (float)minimumValue;
+- (float)maximumValue;
+- (NSString*)minimumValueImage;
+- (NSString*)maximumValueImage;
+- (BOOL)isSecure;
+- (UIKeyboardType)keyboardType;
+- (UITextAutocapitalizationType)autocapitalizationType;
+- (UITextAutocorrectionType)autoCorrectionType;
+
+@end
--- /dev/null
+//
+// IASKSpecifier.m
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKSpecifier.h"
+#import "IASKSettingsReader.h"
+
+@interface IASKSpecifier ()
+@property (nonatomic, retain) NSDictionary *multipleValuesDict;
+- (void)_reinterpretValues:(NSDictionary*)specifierDict;
+@end
+
+@implementation IASKSpecifier
+
+@synthesize specifierDict=_specifierDict;
+@synthesize multipleValuesDict=_multipleValuesDict;
+@synthesize settingsReader = _settingsReader;
+
+- (id)initWithSpecifier:(NSDictionary*)specifier {
+ if ([super init]) {
+ [self setSpecifierDict:specifier];
+
+ if ([[self type] isEqualToString:kIASKPSMultiValueSpecifier] ||
+ [[self type] isEqualToString:kIASKPSTitleValueSpecifier]) {
+ [self _reinterpretValues:[self specifierDict]];
+ }
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [_specifierDict release];
+ [_multipleValuesDict release];
+ _settingsReader = nil;
+
+ [super dealloc];
+}
+
+- (void)_reinterpretValues:(NSDictionary*)specifierDict {
+ NSArray *values = [_specifierDict objectForKey:kIASKValues];
+ NSArray *titles = [_specifierDict objectForKey:kIASKTitles];
+
+ NSMutableDictionary *multipleValuesDict = [[[NSMutableDictionary alloc] init] autorelease];
+
+ if (values) {
+ [multipleValuesDict setObject:values forKey:kIASKValues];
+ }
+
+ if (titles) {
+ [multipleValuesDict setObject:titles forKey:kIASKTitles];
+ }
+
+ [self setMultipleValuesDict:multipleValuesDict];
+}
+
+- (NSString*)title {
+ return [self.settingsReader titleForStringId:[_specifierDict objectForKey:kIASKTitle]];
+}
+
+- (NSString*)key {
+ return [_specifierDict objectForKey:kIASKKey];
+}
+
+- (NSString*)type {
+ return [_specifierDict objectForKey:kIASKType];
+}
+
+- (NSString*)titleForCurrentValue:(id)currentValue {
+ NSArray *values = [self multipleValues];
+ NSArray *titles = [self multipleTitles];
+ if (values.count != titles.count) {
+ return nil;
+ }
+ NSInteger keyIndex = [values indexOfObject:currentValue];
+ if (keyIndex == NSNotFound) {
+ return nil;
+ }
+ @try {
+ return [self.settingsReader titleForStringId:[titles objectAtIndex:keyIndex]];
+ }
+ @catch (NSException * e) {}
+ return nil;
+}
+
+- (NSInteger)multipleValuesCount {
+ return [[_multipleValuesDict objectForKey:kIASKValues] count];
+}
+
+- (NSArray*)multipleValues {
+ return [_multipleValuesDict objectForKey:kIASKValues];
+}
+
+- (NSArray*)multipleTitles {
+ return [_multipleValuesDict objectForKey:kIASKTitles];
+}
+
+- (NSString*)file {
+ return [_specifierDict objectForKey:kIASKFile];
+}
+
+- (id)defaultValue {
+ return [_specifierDict objectForKey:kIASKDefaultValue];
+}
+
+- (id)defaultStringValue {
+ return [[_specifierDict objectForKey:kIASKDefaultValue] description];
+}
+
+- (BOOL)defaultBoolValue {
+ id defaultValue = [self defaultValue];
+ if ([defaultValue isEqual:[self trueValue]]) {
+ return YES;
+ }
+ if ([defaultValue isEqual:[self falseValue]]) {
+ return NO;
+ }
+ return [defaultValue boolValue];
+}
+
+- (id)trueValue {
+ return [_specifierDict objectForKey:kIASKTrueValue];
+}
+
+- (id)falseValue {
+ return [_specifierDict objectForKey:kIASKFalseValue];
+}
+
+- (float)minimumValue {
+ return [[_specifierDict objectForKey:kIASKMinimumValue] floatValue];
+}
+
+- (float)maximumValue {
+ return [[_specifierDict objectForKey:kIASKMaximumValue] floatValue];
+}
+
+- (NSString*)minimumValueImage {
+ return [_specifierDict objectForKey:kIASKMinimumValueImage];
+}
+
+- (NSString*)maximumValueImage {
+ return [_specifierDict objectForKey:kIASKMaximumValueImage];
+}
+
+- (BOOL)isSecure {
+ return [[_specifierDict objectForKey:kIASKIsSecure] boolValue];
+}
+
+- (UIKeyboardType)keyboardType {
+ if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardAlphabet]) {
+ return UIKeyboardTypeASCIICapable;
+ }
+ else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardNumbersAndPunctuation]) {
+ return UIKeyboardTypeNumbersAndPunctuation;
+ }
+ else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardNumberPad]) {
+ return UIKeyboardTypeNumberPad;
+ }
+ else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:KIASKKeyboardURL]) {
+ return UIKeyboardTypeURL;
+ }
+ else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardEmailAddress]) {
+ return UIKeyboardTypeEmailAddress;
+ }
+ return UIKeyboardTypeDefault;
+}
+
+- (UITextAutocapitalizationType)autocapitalizationType {
+ if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapNone]) {
+ return UITextAutocapitalizationTypeNone;
+ }
+ else if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapSentences]) {
+ return UITextAutocapitalizationTypeSentences;
+ }
+ else if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapWords]) {
+ return UITextAutocapitalizationTypeWords;
+ }
+ else if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapAllCharacters]) {
+ return UITextAutocapitalizationTypeAllCharacters;
+ }
+ return UITextAutocapitalizationTypeNone;
+}
+
+- (UITextAutocorrectionType)autoCorrectionType {
+ if ([[_specifierDict objectForKey:kIASKAutoCorrectionType] isEqualToString:kIASKAutoCorrDefault]) {
+ return UITextAutocorrectionTypeDefault;
+ }
+ else if ([[_specifierDict objectForKey:kIASKAutoCorrectionType] isEqualToString:kIASKAutoCorrNo]) {
+ return UITextAutocorrectionTypeNo;
+ }
+ else if ([[_specifierDict objectForKey:kIASKAutoCorrectionType] isEqualToString:kIASKAutoCorrYes]) {
+ return UITextAutocorrectionTypeYes;
+ }
+ return UITextAutocorrectionTypeDefault;
+}
+
+@end
--- /dev/null
+//
+// IASKPSSliderSpecifierViewCell.h
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <UIKit/UIKit.h>
+
+@class IASKSlider;
+
+@interface IASKPSSliderSpecifierViewCell : UITableViewCell {
+ IBOutlet IASKSlider *_slider;
+ IBOutlet UIImageView *_minImage;
+ IBOutlet UIImageView *_maxImage;
+}
+
+@property (nonatomic, readonly) IASKSlider *slider;
+@property (nonatomic, readonly) UIImageView *minImage;
+@property (nonatomic, readonly) UIImageView *maxImage;
+
+@end
--- /dev/null
+//
+// IASKPSSliderSpecifierViewCell.m
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009-2010:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKPSSliderSpecifierViewCell.h"
+#import "IASKSlider.h"
+#import "IASKSettingsReader.h"
+
+@implementation IASKPSSliderSpecifierViewCell
+
+@synthesize slider=_slider,
+ minImage=_minImage,
+ maxImage=_maxImage;
+
+- (void)layoutSubviews {
+ CGRect sliderFrame = _slider.frame;
+ sliderFrame.origin.x = kIASKSliderNoImagesX;
+ sliderFrame.size.width = kIASKSliderNoImagesWidth;
+ _minImage.hidden = YES;
+ _maxImage.hidden = YES;
+
+ // Check if there are min and max images. If so, change the layout accordingly.
+ if (_minImage.image && _maxImage.image) {
+ // Both images
+ _minImage.hidden = NO;
+ _maxImage.hidden = NO;
+ sliderFrame.origin.x = kIASKSliderBothImagesX;
+ sliderFrame.size.width = kIASKSliderBothImagesWidth;
+ }
+ else if (_minImage.image) {
+ // Min image
+ _minImage.hidden = NO;
+ sliderFrame.origin.x = kIASKSliderBothImagesX;
+ sliderFrame.size.width = kIASKSliderOneImageWidth;
+ }
+ else if (_maxImage.image) {
+ // Max image
+ _maxImage.hidden = NO;
+ sliderFrame.origin.x = kIASKSliderNoImagesX;
+ sliderFrame.size.width = kIASKSliderOneImageWidth;
+ }
+
+ _slider.frame = sliderFrame;
+}
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+- (void)prepareForReuse {
+ _minImage.image = nil;
+ _maxImage.image = nil;
+}
+@end
--- /dev/null
+//
+// IASKPSTextFieldSpecifierViewCell.h
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <UIKit/UIKit.h>
+
+@class IASKTextField;
+
+@interface IASKPSTextFieldSpecifierViewCell : UITableViewCell {
+ IBOutlet UILabel *_label;
+ IBOutlet IASKTextField *_textField;
+}
+
+@property (nonatomic, readonly) UILabel *label;
+@property (nonatomic, readonly) IASKTextField *textField;
+
+@end
--- /dev/null
+//
+// IASKPSTextFieldSpecifierViewCell.m
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009-2010:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKPSTextFieldSpecifierViewCell.h"
+#import "IASKTextField.h"
+#import "IASKSettingsReader.h"
+
+@implementation IASKPSTextFieldSpecifierViewCell
+
+@synthesize label=_label,
+ textField=_textField;
+
+- (void)layoutSubviews {
+ CGSize labelSize = [_label sizeThatFits:CGSizeZero];
+ labelSize.width = MIN(labelSize.width, _label.bounds.size.width);
+
+ CGRect textFieldFrame = _textField.frame;
+ textFieldFrame.origin.x = _label.frame.origin.x + MAX(kIASKMinLabelWidth, labelSize.width) + kIASKSpacing;
+ if (!_label.text.length)
+ textFieldFrame.origin.x = _label.frame.origin.x;
+ textFieldFrame.size.width = kIASKTableWidth - textFieldFrame.origin.x - _label.frame.origin.x;
+ _textField.frame = textFieldFrame;
+}
+
+- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
+
+ [super setSelected:selected animated:animated];
+
+ // Configure the view for the selected state
+}
+
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+
+@end
--- /dev/null
+//
+// IASKPSTitleValueSpecifierViewCell.h
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2010:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <UIKit/UIKit.h>
+
+
+@interface IASKPSTitleValueSpecifierViewCell : UITableViewCell
+
+@end
--- /dev/null
+//
+// IASKPSTitleValueSpecifierViewCell.m
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2010:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKPSTitleValueSpecifierViewCell.h"
+#import "IASKSettingsReader.h"
+
+
+@implementation IASKPSTitleValueSpecifierViewCell
+
+- (void)layoutSubviews {
+ // left align the value if the title is empty
+ if (!self.textLabel.text.length) {
+ self.textLabel.text = self.detailTextLabel.text;
+ self.detailTextLabel.text = nil;
+ if ([self.reuseIdentifier isEqualToString:kIASKPSMultiValueSpecifier]) {
+ self.textLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize]];
+ self.textLabel.textColor = self.detailTextLabel.textColor;
+ }
+ }
+ [super layoutSubviews];
+
+ CGSize viewSize = [self.textLabel superview].frame.size;
+
+ // set the left title label frame
+ CGFloat labelWidth = [self.textLabel sizeThatFits:CGSizeZero].width;
+ CGFloat minValueWidth = (self.detailTextLabel.text.length) ? kIASKMinValueWidth + kIASKSpacing : 0;
+ labelWidth = MIN(labelWidth, viewSize.width - minValueWidth - kIASKPaddingLeft -kIASKPaddingRight);
+ CGRect labelFrame = CGRectMake(kIASKPaddingLeft, 0, labelWidth, viewSize.height -2);
+ self.textLabel.frame = labelFrame;
+
+ // set the right value label frame
+ if (self.detailTextLabel.text.length) {
+ CGRect valueFrame = CGRectMake(kIASKPaddingLeft + labelWidth + kIASKSpacing,
+ 0,
+ viewSize.width - (kIASKPaddingLeft + labelWidth + kIASKSpacing) - kIASKPaddingRight,
+ viewSize.height -2);
+ self.detailTextLabel.frame = valueFrame;
+ }
+}
+
+@end
--- /dev/null
+//
+// IASKPSToggleSwitchSpecifierViewCell.h
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <UIKit/UIKit.h>
+
+@class IASKSwitch;
+
+@interface IASKPSToggleSwitchSpecifierViewCell : UITableViewCell {
+ IBOutlet UILabel *_label;
+ IBOutlet IASKSwitch *_toggle;
+}
+
+@property (nonatomic, readonly) UILabel *label;
+@property (nonatomic, readonly) IASKSwitch *toggle;
+
+@end
--- /dev/null
+//
+// IASKPSToggleSwitchSpecifierViewCell.m
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKPSToggleSwitchSpecifierViewCell.h"
+#import "IASKSwitch.h"
+
+@implementation IASKPSToggleSwitchSpecifierViewCell
+
+@synthesize label=_label,
+ toggle=_toggle;
+
+- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
+ if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) {
+ // Initialization code
+ }
+ return self;
+}
+
+
+- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
+
+ [super setSelected:selected animated:animated];
+
+ // Configure the view for the selected state
+}
+
+
+- (void)dealloc {
+ [super dealloc];
+}
+
+
+@end
--- /dev/null
+//
+// IASKSlider.h
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <UIKit/UIKit.h>
+
+
+@interface IASKSlider : UISlider {
+ NSString *_key;
+}
+
+@property (nonatomic, retain) NSString *key;
+
+@end
--- /dev/null
+//
+// IASKSlider.m
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKSlider.h"
+
+
+@implementation IASKSlider
+
+@synthesize key=_key;
+
+- (void)dealloc {
+ [_key release];
+ [super dealloc];
+}
+
+@end
--- /dev/null
+//
+// IASKSwitch.h
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <UIKit/UIKit.h>
+
+
+@interface IASKSwitch : UISwitch {
+ NSString *_key;
+}
+
+@property (nonatomic, retain) NSString *key;
+
+@end
--- /dev/null
+//
+// IASKSwitch.m
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKSwitch.h"
+
+
+@implementation IASKSwitch
+
+@synthesize key=_key;
+
+- (void)dealloc {
+ [_key release];
+ [super dealloc];
+}
+
+
+@end
--- /dev/null
+//
+// IASKTextField.h
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import <UIKit/UIKit.h>
+
+
+@interface IASKTextField : UITextField {
+ NSString *_key;
+}
+
+@property (nonatomic, retain) NSString *key;
+
+@end
--- /dev/null
+//
+// IASKTextField.m
+// http://www.inappsettingskit.com
+//
+// Copyright (c) 2009:
+// Luc Vandal, Edovia Inc., http://www.edovia.com
+// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
+// All rights reserved.
+//
+// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
+// as the original authors of this code. You can give credit in a blog post, a tweet or on
+// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
+//
+// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
+//
+
+#import "IASKTextField.h"
+
+
+@implementation IASKTextField
+
+@synthesize key=_key;
+
+- (void)dealloc {
+ [_key release];
+ [super dealloc];
+}
+
+@end
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">768</int>
+ <string key="IBDocument.SystemVersion">10F569</string>
+ <string key="IBDocument.InterfaceBuilderVersion">788</string>
+ <string key="IBDocument.AppKitVersion">1038.29</string>
+ <string key="IBDocument.HIToolboxVersion">461.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string key="NS.object.0">117</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="1"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="372490531">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ </object>
+ <object class="IBProxyObject" id="975951072">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ </object>
+ <object class="IBUIView" id="191373211">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">276</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUITableView" id="1838945">
+ <reference key="NSNextResponder" ref="191373211"/>
+ <int key="NSvFlags">274</int>
+ <string key="NSFrameSize">{320, 460}</string>
+ <reference key="NSSuperview" ref="191373211"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">10</int>
+ <object class="NSImage" key="NSImage">
+ <int key="NSImageFlags">549453824</int>
+ <string key="NSSize">{84, 1}</string>
+ <object class="NSMutableArray" key="NSReps">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="0"/>
+ <object class="NSBitmapImageRep">
+ <object class="NSData" key="NSTIFFRepresentation">
+ <bytes key="NS.bytes">TU0AKgAAAVjFzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/
+y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/
+xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/
+xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/
+xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/
+xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P8ADQEAAAMAAAABAFQAAAEB
+AAMAAAABAAEAAAECAAMAAAAEAAAB+gEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES
+AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABAAEAAAEXAAQAAAABAAABUAEcAAMAAAABAAEAAAFS
+AAMAAAABAAEAAAFTAAMAAAAEAAACAgAAAAAACAAIAAgACAABAAEAAQABA</bytes>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MCAwAA</bytes>
+ </object>
+ </object>
+ <string key="IBUIColorCocoaTouchKeyPath">groupTableViewBackgroundColor</string>
+ </object>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ <bool key="IBUIBouncesZoom">NO</bool>
+ <int key="IBUIStyle">1</int>
+ <int key="IBUISeparatorStyle">1</int>
+ <int key="IBUISectionIndexMinimumDisplayRowCount">0</int>
+ <bool key="IBUIShowsSelectionImmediatelyOnTouchBegin">YES</bool>
+ <float key="IBUIRowHeight">44</float>
+ <float key="IBUISectionHeaderHeight">10</float>
+ <float key="IBUISectionFooterHeight">10</float>
+ </object>
+ </object>
+ <string key="NSFrameSize">{320, 460}</string>
+ <reference key="NSSuperview"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ </object>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">view</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="191373211"/>
+ </object>
+ <int key="connectionID">3</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">_tableView</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="1838945"/>
+ </object>
+ <int key="connectionID">5</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">dataSource</string>
+ <reference key="source" ref="1838945"/>
+ <reference key="destination" ref="372490531"/>
+ </object>
+ <int key="connectionID">6</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="1838945"/>
+ <reference key="destination" ref="372490531"/>
+ </object>
+ <int key="connectionID">7</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">1</int>
+ <reference key="object" ref="191373211"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1838945"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="372490531"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="975951072"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">4</int>
+ <reference key="object" ref="1838945"/>
+ <reference key="parent" ref="191373211"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.CustomClassName</string>
+ <string>-2.CustomClassName</string>
+ <string>1.IBEditorWindowLastContentRect</string>
+ <string>1.IBPluginDependency</string>
+ <string>4.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>IASKAppSettingsViewController</string>
+ <string>UIResponder</string>
+ <string>{{549, 492}, {320, 460}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">7</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">IASKAppSettingsViewController</string>
+ <string key="superclassName">UIViewController</string>
+ <object class="NSMutableDictionary" key="actions">
+ <string key="NS.key.0">dismiss:</string>
+ <string key="NS.object.0">id</string>
+ </object>
+ <object class="NSMutableDictionary" key="actionInfosByName">
+ <string key="NS.key.0">dismiss:</string>
+ <object class="IBActionInfo" key="NS.object.0">
+ <string key="name">dismiss:</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="outlets">
+ <string key="NS.key.0">_tableView</string>
+ <string key="NS.object.0">UITableView</string>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <string key="NS.key.0">_tableView</string>
+ <object class="IBToOneOutletInfo" key="NS.object.0">
+ <string key="name">_tableView</string>
+ <string key="candidateClassName">UITableView</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">../InAppSettingsKit/Controllers/IASKAppSettingsViewController.h</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSError.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSNetServices.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSPort.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSStream.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSXMLParser.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="189941974">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIResponder</string>
+ <string key="superclassName">NSObject</string>
+ <reference key="sourceIdentifier" ref="189941974"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIScrollView</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIScrollView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchBar</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchBar.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchDisplayController</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchDisplayController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITableView</string>
+ <string key="superclassName">UIScrollView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITableView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINavigationController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITabBarController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIViewController.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
+ <integer value="768" key="NS.object.0"/>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
+ <integer value="3000" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <string key="IBDocument.LastKnownRelativeProjectPath">../InAppSettingsKitSampleApp.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <string key="IBCocoaTouchPluginVersion">117</string>
+ </data>
+</archive>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">768</int>
+ <string key="IBDocument.SystemVersion">10C540</string>
+ <string key="IBDocument.InterfaceBuilderVersion">740</string>
+ <string key="IBDocument.AppKitVersion">1038.25</string>
+ <string key="IBDocument.HIToolboxVersion">458.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string key="NS.object.0">62</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="2"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="841351856">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ </object>
+ <object class="IBProxyObject" id="371349661">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ </object>
+ <object class="IBUITableViewCell" id="699910302">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">290</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUIView" id="833157797">
+ <reference key="NSNextResponder" ref="699910302"/>
+ <int key="NSvFlags">256</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUISlider" id="213296969">
+ <reference key="NSNextResponder" ref="833157797"/>
+ <int key="NSvFlags">290</int>
+ <string key="NSFrame">{{52, 12}, {216, 23}}</string>
+ <reference key="NSSuperview" ref="833157797"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIMultipleTouchEnabled">YES</bool>
+ <int key="IBUIContentHorizontalAlignment">0</int>
+ <int key="IBUIContentVerticalAlignment">0</int>
+ <float key="IBUIValue">0.5</float>
+ </object>
+ <object class="IBUIImageView" id="343121076">
+ <reference key="NSNextResponder" ref="833157797"/>
+ <int key="NSvFlags">289</int>
+ <string key="NSFrame">{{278, 13}, {21, 21}}</string>
+ <reference key="NSSuperview" ref="833157797"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <int key="IBUIContentMode">4</int>
+ <bool key="IBUIUserInteractionEnabled">NO</bool>
+ </object>
+ <object class="IBUIImageView" id="408162837">
+ <reference key="NSNextResponder" ref="833157797"/>
+ <int key="NSvFlags">292</int>
+ <string key="NSFrame">{{21, 13}, {21, 21}}</string>
+ <reference key="NSSuperview" ref="833157797"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <int key="IBUIContentMode">4</int>
+ <bool key="IBUIUserInteractionEnabled">NO</bool>
+ </object>
+ </object>
+ <string key="NSFrameSize">{320, 43}</string>
+ <reference key="NSSuperview" ref="699910302"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MCAwAA</bytes>
+ </object>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <int key="IBUIContentMode">4</int>
+ <bool key="IBUIMultipleTouchEnabled">YES</bool>
+ </object>
+ </object>
+ <string key="NSFrameSize">{320, 44}</string>
+ <reference key="NSSuperview"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MSAxIDEAA</bytes>
+ </object>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <int key="IBUISeparatorStyle">1</int>
+ <reference key="IBUIContentView" ref="833157797"/>
+ <string key="IBUIReuseIdentifier">PSSliderSpecifier</string>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">_slider</string>
+ <reference key="source" ref="699910302"/>
+ <reference key="destination" ref="213296969"/>
+ </object>
+ <int key="connectionID">4</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">_maxImage</string>
+ <reference key="source" ref="699910302"/>
+ <reference key="destination" ref="343121076"/>
+ </object>
+ <int key="connectionID">8</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">_minImage</string>
+ <reference key="source" ref="699910302"/>
+ <reference key="destination" ref="408162837"/>
+ </object>
+ <int key="connectionID">10</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="841351856"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="371349661"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">2</int>
+ <reference key="object" ref="699910302"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="408162837"/>
+ <reference ref="343121076"/>
+ <reference ref="213296969"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">3</int>
+ <reference key="object" ref="213296969"/>
+ <reference key="parent" ref="699910302"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">6</int>
+ <reference key="object" ref="343121076"/>
+ <reference key="parent" ref="699910302"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">9</int>
+ <reference key="object" ref="408162837"/>
+ <reference key="parent" ref="699910302"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-2.CustomClassName</string>
+ <string>2.CustomClassName</string>
+ <string>2.IBEditorWindowLastContentRect</string>
+ <string>2.IBPluginDependency</string>
+ <string>3.CustomClassName</string>
+ <string>3.IBPluginDependency</string>
+ <string>6.IBPluginDependency</string>
+ <string>9.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UIResponder</string>
+ <string>IASKPSSliderSpecifierViewCell</string>
+ <string>{{171, 925}, {320, 44}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>IASKSlider</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">10</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">IASKPSSliderSpecifierViewCell</string>
+ <string key="superclassName">UITableViewCell</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>_maxImage</string>
+ <string>_minImage</string>
+ <string>_slider</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UIImageView</string>
+ <string>UIImageView</string>
+ <string>IASKSlider</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">../InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">IASKSlider</string>
+ <string key="superclassName">UISlider</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">../InAppSettingsKit/Views/IASKSlider.h</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSError.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSNetServices.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSPort.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSStream.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSXMLParser.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="74477970">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIControl</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIControl.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIImageView</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIImageView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIResponder</string>
+ <string key="superclassName">NSObject</string>
+ <reference key="sourceIdentifier" ref="74477970"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISlider</string>
+ <string key="superclassName">UIControl</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISlider.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITableViewCell</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITableViewCell.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIView.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
+ <integer value="768" key="NS.object.0"/>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
+ <integer value="3100" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <string key="IBDocument.LastKnownRelativeProjectPath">../InAppSettingsKitSampleApp.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <string key="IBCocoaTouchPluginVersion">3.1</string>
+ </data>
+</archive>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">1024</int>
+ <string key="IBDocument.SystemVersion">10F569</string>
+ <string key="IBDocument.InterfaceBuilderVersion">788</string>
+ <string key="IBDocument.AppKitVersion">1038.29</string>
+ <string key="IBDocument.HIToolboxVersion">461.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string key="NS.object.0">117</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="2"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="841351856">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ </object>
+ <object class="IBProxyObject" id="371349661">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ </object>
+ <object class="IBUITableViewCell" id="639928991">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">290</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUIView" id="642554623">
+ <reference key="NSNextResponder" ref="639928991"/>
+ <int key="NSvFlags">256</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUILabel" id="68117349">
+ <reference key="NSNextResponder" ref="642554623"/>
+ <int key="NSvFlags">294</int>
+ <string key="NSFrame">{{19, 11}, {240, 21}}</string>
+ <reference key="NSSuperview" ref="642554623"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIUserInteractionEnabled">NO</bool>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ <string key="IBUIText">Label</string>
+ <object class="NSFont" key="IBUIFont">
+ <string key="NSName">Helvetica-Bold</string>
+ <double key="NSSize">17</double>
+ <int key="NSfFlags">16</int>
+ </object>
+ <object class="NSColor" key="IBUITextColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MCAwIDAAA</bytes>
+ </object>
+ <nil key="IBUIHighlightedColor"/>
+ <int key="IBUIBaselineAdjustment">1</int>
+ <float key="IBUIMinimumFontSize">10</float>
+ </object>
+ <object class="IBUITextField" id="239084550">
+ <reference key="NSNextResponder" ref="642554623"/>
+ <int key="NSvFlags">291</int>
+ <string key="NSFrame">{{100, 11}, {201, 21}}</string>
+ <reference key="NSSuperview" ref="642554623"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ <string key="IBUIText">hello</string>
+ <object class="NSColor" key="IBUITextColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MC4yNzQ1MDk4MiAwLjM3NjQ3MDYgMC41MjE1Njg2NgA</bytes>
+ </object>
+ <object class="NSFont" key="IBUIFont">
+ <string key="NSName">Helvetica</string>
+ <double key="NSSize">17</double>
+ <int key="NSfFlags">16</int>
+ </object>
+ <int key="IBUITextAlignment">2</int>
+ <bool key="IBUIAdjustsFontSizeToFit">YES</bool>
+ <float key="IBUIMinimumFontSize">10</float>
+ <object class="IBUITextInputTraits" key="IBUITextInputTraits">
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ </object>
+ </object>
+ </object>
+ <string key="NSFrameSize">{320, 44}</string>
+ <reference key="NSSuperview" ref="639928991"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MCAwAA</bytes>
+ </object>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <int key="IBUIContentMode">4</int>
+ <bool key="IBUIMultipleTouchEnabled">YES</bool>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ </object>
+ </object>
+ <string key="NSFrameSize">{320, 44}</string>
+ <reference key="NSSuperview"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MSAxIDEAA</bytes>
+ </object>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ <int key="IBUISeparatorStyle">1</int>
+ <int key="IBUISelectionStyle">0</int>
+ <reference key="IBUIContentView" ref="642554623"/>
+ <string key="IBUIReuseIdentifier">PSTextFieldSpecifier</string>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">_label</string>
+ <reference key="source" ref="639928991"/>
+ <reference key="destination" ref="68117349"/>
+ </object>
+ <int key="connectionID">5</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">_textField</string>
+ <reference key="source" ref="639928991"/>
+ <reference key="destination" ref="239084550"/>
+ </object>
+ <int key="connectionID">6</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="841351856"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="371349661"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">2</int>
+ <reference key="object" ref="639928991"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="68117349"/>
+ <reference ref="239084550"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">3</int>
+ <reference key="object" ref="68117349"/>
+ <reference key="parent" ref="639928991"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">4</int>
+ <reference key="object" ref="239084550"/>
+ <reference key="parent" ref="639928991"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-2.CustomClassName</string>
+ <string>2.CustomClassName</string>
+ <string>2.IBEditorWindowLastContentRect</string>
+ <string>2.IBPluginDependency</string>
+ <string>3.IBPluginDependency</string>
+ <string>4.CustomClassName</string>
+ <string>4.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UIResponder</string>
+ <string>IASKPSTextFieldSpecifierViewCell</string>
+ <string>{{105, 513}, {320, 44}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>IASKTextField</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">7</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">IASKPSTextFieldSpecifierViewCell</string>
+ <string key="superclassName">UITableViewCell</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>_label</string>
+ <string>_textField</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UILabel</string>
+ <string>IASKTextField</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>_label</string>
+ <string>_textField</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBToOneOutletInfo">
+ <string key="name">_label</string>
+ <string key="candidateClassName">UILabel</string>
+ </object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">_textField</string>
+ <string key="candidateClassName">IASKTextField</string>
+ </object>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">../InAppSettingsKit/Views/IASKPSTextFieldSpecifierViewCell.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">IASKTextField</string>
+ <string key="superclassName">UITextField</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">../InAppSettingsKit/Views/IASKTextField.h</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSError.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSNetServices.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSPort.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSStream.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSXMLParser.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="283125325">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIControl</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIControl.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UILabel</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UILabel.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIResponder</string>
+ <string key="superclassName">NSObject</string>
+ <reference key="sourceIdentifier" ref="283125325"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITableViewCell</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITableViewCell.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITextField</string>
+ <string key="superclassName">UIControl</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="757893786">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <reference key="sourceIdentifier" ref="757893786"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIView.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
+ <integer value="1024" key="NS.object.0"/>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
+ <integer value="3100" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <string key="IBDocument.LastKnownRelativeProjectPath">../InAppSettingsKitSampleApp.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <string key="IBCocoaTouchPluginVersion">117</string>
+ </data>
+</archive>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">768</int>
+ <string key="IBDocument.SystemVersion">10C540</string>
+ <string key="IBDocument.InterfaceBuilderVersion">740</string>
+ <string key="IBDocument.AppKitVersion">1038.25</string>
+ <string key="IBDocument.HIToolboxVersion">458.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string key="NS.object.0">62</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="2"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="841351856">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ </object>
+ <object class="IBProxyObject" id="371349661">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ </object>
+ <object class="IBUITableViewCell" id="507262743">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">290</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUIView" id="659685403">
+ <reference key="NSNextResponder" ref="507262743"/>
+ <int key="NSvFlags">256</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUILabel" id="697203718">
+ <reference key="NSNextResponder" ref="659685403"/>
+ <int key="NSvFlags">294</int>
+ <string key="NSFrame">{{9, 10}, {200, 21}}</string>
+ <reference key="NSSuperview" ref="659685403"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIUserInteractionEnabled">NO</bool>
+ <string key="IBUIText">Label</string>
+ <object class="NSFont" key="IBUIFont">
+ <string key="NSName">Helvetica-Bold</string>
+ <double key="NSSize">17</double>
+ <int key="NSfFlags">16</int>
+ </object>
+ <object class="NSColor" key="IBUITextColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MCAwIDAAA</bytes>
+ </object>
+ <nil key="IBUIHighlightedColor"/>
+ <int key="IBUIBaselineAdjustment">1</int>
+ <float key="IBUIMinimumFontSize">10</float>
+ </object>
+ <object class="IBUISwitch" id="297989004">
+ <reference key="NSNextResponder" ref="659685403"/>
+ <int key="NSvFlags">289</int>
+ <string key="NSFrame">{{218, 8}, {94, 27}}</string>
+ <reference key="NSSuperview" ref="659685403"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIMultipleTouchEnabled">YES</bool>
+ <int key="IBUIContentHorizontalAlignment">0</int>
+ <int key="IBUIContentVerticalAlignment">0</int>
+ <bool key="IBUIOn">YES</bool>
+ </object>
+ </object>
+ <string key="NSFrameSize">{320, 43}</string>
+ <reference key="NSSuperview" ref="507262743"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MCAwAA</bytes>
+ </object>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <int key="IBUIContentMode">4</int>
+ <bool key="IBUIMultipleTouchEnabled">YES</bool>
+ </object>
+ </object>
+ <string key="NSFrameSize">{320, 44}</string>
+ <reference key="NSSuperview"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">1</int>
+ <bytes key="NSRGB">MSAxIDEAA</bytes>
+ </object>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <int key="IBUISeparatorStyle">1</int>
+ <int key="IBUISelectionStyle">0</int>
+ <reference key="IBUIContentView" ref="659685403"/>
+ <string key="IBUIReuseIdentifier">PSToggleSwitchSpecifier</string>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">_label</string>
+ <reference key="source" ref="507262743"/>
+ <reference key="destination" ref="697203718"/>
+ </object>
+ <int key="connectionID">5</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">_toggle</string>
+ <reference key="source" ref="507262743"/>
+ <reference key="destination" ref="297989004"/>
+ </object>
+ <int key="connectionID">7</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="841351856"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="371349661"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">2</int>
+ <reference key="object" ref="507262743"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="697203718"/>
+ <reference ref="297989004"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">3</int>
+ <reference key="object" ref="697203718"/>
+ <reference key="parent" ref="507262743"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">4</int>
+ <reference key="object" ref="297989004"/>
+ <reference key="parent" ref="507262743"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-2.CustomClassName</string>
+ <string>2.CustomClassName</string>
+ <string>2.IBEditorWindowLastContentRect</string>
+ <string>2.IBPluginDependency</string>
+ <string>3.IBPluginDependency</string>
+ <string>4.CustomClassName</string>
+ <string>4.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UIResponder</string>
+ <string>IASKPSToggleSwitchSpecifierViewCell</string>
+ <string>{{1676, 1200}, {320, 44}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>IASKSwitch</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">7</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">IASKPSToggleSwitchSpecifierViewCell</string>
+ <string key="superclassName">UITableViewCell</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>_label</string>
+ <string>_toggle</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>UILabel</string>
+ <string>IASKSwitch</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">../InAppSettingsKit/Views/IASKPSToggleSwitchSpecifierViewCell.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">IASKSwitch</string>
+ <string key="superclassName">UISwitch</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">../InAppSettingsKit/Views/IASKSwitch.h</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSError.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSNetServices.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSPort.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSStream.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSXMLParser.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="1054107769">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIControl</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIControl.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UILabel</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UILabel.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIResponder</string>
+ <string key="superclassName">NSObject</string>
+ <reference key="sourceIdentifier" ref="1054107769"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISwitch</string>
+ <string key="superclassName">UIControl</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISwitch.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITableViewCell</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITableViewCell.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIView.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
+ <integer value="768" key="NS.object.0"/>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
+ <integer value="3100" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <string key="IBDocument.LastKnownRelativeProjectPath">../InAppSettingsKitSampleApp.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <string key="IBCocoaTouchPluginVersion">3.1</string>
+ </data>
+</archive>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">768</int>
+ <string key="IBDocument.SystemVersion">10B504</string>
+ <string key="IBDocument.InterfaceBuilderVersion">732</string>
+ <string key="IBDocument.AppKitVersion">1038.2</string>
+ <string key="IBDocument.HIToolboxVersion">437.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string key="NS.object.0">62</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="1"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="372490531">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ </object>
+ <object class="IBProxyObject" id="975951072">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ </object>
+ <object class="IBUIView" id="191373211">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">292</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBUITableView" id="575792171">
+ <reference key="NSNextResponder" ref="191373211"/>
+ <int key="NSvFlags">274</int>
+ <string key="NSFrameSize">{320, 460}</string>
+ <reference key="NSSuperview" ref="191373211"/>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <bool key="IBUIBouncesZoom">NO</bool>
+ <int key="IBUIStyle">1</int>
+ <int key="IBUISeparatorStyle">1</int>
+ <int key="IBUISectionIndexMinimumDisplayRowCount">0</int>
+ <bool key="IBUIShowsSelectionImmediatelyOnTouchBegin">YES</bool>
+ <float key="IBUIRowHeight">44</float>
+ <float key="IBUISectionHeaderHeight">10</float>
+ <float key="IBUISectionFooterHeight">10</float>
+ </object>
+ </object>
+ <string key="NSFrameSize">{320, 460}</string>
+ <reference key="NSSuperview"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ <object class="NSColorSpace" key="NSCustomColorSpace">
+ <int key="NSID">2</int>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">view</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="191373211"/>
+ </object>
+ <int key="connectionID">3</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">dataSource</string>
+ <reference key="source" ref="575792171"/>
+ <reference key="destination" ref="372490531"/>
+ </object>
+ <int key="connectionID">5</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="575792171"/>
+ <reference key="destination" ref="372490531"/>
+ </object>
+ <int key="connectionID">6</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">_tableView</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="575792171"/>
+ </object>
+ <int key="connectionID">7</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">1</int>
+ <reference key="object" ref="191373211"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="575792171"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="372490531"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="975951072"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">4</int>
+ <reference key="object" ref="575792171"/>
+ <reference key="parent" ref="191373211"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.CustomClassName</string>
+ <string>-2.CustomClassName</string>
+ <string>1.IBEditorWindowLastContentRect</string>
+ <string>1.IBPluginDependency</string>
+ <string>4.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>IASKSpecifierValuesViewController</string>
+ <string>UIResponder</string>
+ <string>{{556, 432}, {320, 460}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">7</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">IASKSpecifierValuesViewController</string>
+ <string key="superclassName">UIViewController</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <string key="NS.key.0">_tableView</string>
+ <string key="NS.object.0">UITableView</string>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">IASKSpecifierValuesViewController.h</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSError.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSNetServices.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSPort.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSStream.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSXMLParser.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="612400033">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIResponder</string>
+ <string key="superclassName">NSObject</string>
+ <reference key="sourceIdentifier" ref="612400033"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIScrollView</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIScrollView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchBar</string>
+ <string key="superclassName">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchBar.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UISearchDisplayController</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UISearchDisplayController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UITableView</string>
+ <string key="superclassName">UIScrollView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITableView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIView</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UINavigationController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UITabBarController.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">UIViewController</string>
+ <string key="superclassName">UIResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">UIKit.framework/Headers/UIViewController.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
+ <integer value="768" key="NS.object.0"/>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
+ <integer value="3000" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <string key="IBDocument.LastKnownRelativeProjectPath">TouchPad.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <string key="IBCocoaTouchPluginVersion">3.1</string>
+ </data>
+</archive>
--- /dev/null
+//
+// SFHFKeychainUtils.h
+//
+// Created by Buzz Andersen on 10/20/08.
+// Based partly on code by Jonathan Wight, Jon Crosby, and Mike Malone.
+// Copyright 2008 Sci-Fi Hi-Fi. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#import <UIKit/UIKit.h>
+
+
+@interface SFHFKeychainUtils : NSObject {
+
+}
+
++ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error;
++ (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error;
++ (BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error;
+
+@end
\ No newline at end of file
--- /dev/null
+//
+// SFHFKeychainUtils.m
+//
+// Created by Buzz Andersen on 10/20/08.
+// Based partly on code by Jonathan Wight, Jon Crosby, and Mike Malone.
+// Copyright 2008 Sci-Fi Hi-Fi. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#import "SFHFKeychainUtils.h"
+#import <Security/Security.h>
+
+static NSString *SFHFKeychainUtilsErrorDomain = @"SFHFKeychainUtilsErrorDomain";
+
+#if __IPHONE_OS_VERSION_MIN_REQUIRED < 30000 && TARGET_IPHONE_SIMULATOR
+@interface SFHFKeychainUtils (PrivateMethods)
++ (SecKeychainItemRef) getKeychainItemReferenceForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error;
+@end
+#endif
+
+@implementation SFHFKeychainUtils
+
+#if __IPHONE_OS_VERSION_MIN_REQUIRED < 30000 && TARGET_IPHONE_SIMULATOR
+
++ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error {
+ if (!username || !serviceName) {
+ *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
+ return nil;
+ }
+
+ SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServiceName: serviceName error: error];
+
+ if (*error || !item) {
+ return nil;
+ }
+
+ // from Advanced Mac OS X Programming, ch. 16
+ UInt32 length;
+ char *password;
+ SecKeychainAttribute attributes[8];
+ SecKeychainAttributeList list;
+
+ attributes[0].tag = kSecAccountItemAttr;
+ attributes[1].tag = kSecDescriptionItemAttr;
+ attributes[2].tag = kSecLabelItemAttr;
+ attributes[3].tag = kSecModDateItemAttr;
+
+ list.count = 4;
+ list.attr = attributes;
+
+ OSStatus status = SecKeychainItemCopyContent(item, NULL, &list, &length, (void **)&password);
+
+ if (status != noErr) {
+ *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
+ return nil;
+ }
+
+ NSString *passwordString = nil;
+
+ if (password != NULL) {
+ char passwordBuffer[1024];
+
+ if (length > 1023) {
+ length = 1023;
+ }
+ strncpy(passwordBuffer, password, length);
+
+ passwordBuffer[length] = '\0';
+ passwordString = [NSString stringWithCString:passwordBuffer];
+ }
+
+ SecKeychainItemFreeContent(&list, password);
+
+ CFRelease(item);
+
+ return passwordString;
+}
+
++ (void) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error {
+ if (!username || !password || !serviceName) {
+ *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
+ return;
+ }
+
+ OSStatus status = noErr;
+
+ SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServiceName: serviceName error: error];
+
+ if (*error && [*error code] != noErr) {
+ return;
+ }
+
+ *error = nil;
+
+ if (item) {
+ status = SecKeychainItemModifyAttributesAndData(item,
+ NULL,
+ strlen([password UTF8String]),
+ [password UTF8String]);
+
+ CFRelease(item);
+ }
+ else {
+ status = SecKeychainAddGenericPassword(NULL,
+ strlen([serviceName UTF8String]),
+ [serviceName UTF8String],
+ strlen([username UTF8String]),
+ [username UTF8String],
+ strlen([password UTF8String]),
+ [password UTF8String],
+ NULL);
+ }
+
+ if (status != noErr) {
+ *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
+ }
+}
+
++ (void) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error {
+ if (!username || !serviceName) {
+ *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: 2000 userInfo: nil];
+ return;
+ }
+
+ *error = nil;
+
+ SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServiceName: serviceName error: error];
+
+ if (*error && [*error code] != noErr) {
+ return;
+ }
+
+ OSStatus status;
+
+ if (item) {
+ status = SecKeychainItemDelete(item);
+
+ CFRelease(item);
+ }
+
+ if (status != noErr) {
+ *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
+ }
+}
+
++ (SecKeychainItemRef) getKeychainItemReferenceForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error {
+ if (!username || !serviceName) {
+ *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
+ return nil;
+ }
+
+ *error = nil;
+
+ SecKeychainItemRef item;
+
+ OSStatus status = SecKeychainFindGenericPassword(NULL,
+ strlen([serviceName UTF8String]),
+ [serviceName UTF8String],
+ strlen([username UTF8String]),
+ [username UTF8String],
+ NULL,
+ NULL,
+ &item);
+
+ if (status != noErr) {
+ if (status != errSecItemNotFound) {
+ *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
+ }
+
+ return nil;
+ }
+
+ return item;
+}
+
+#else
+
++ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error {
+ if (!username || !serviceName) {
+ if (error) *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
+ return nil;
+ }
+
+ if (error) *error = nil;
+
+ // Set up a query dictionary with the base query attributes: item type (generic), username, and service
+
+ NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, kSecAttrAccount, kSecAttrService, nil] autorelease];
+ NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, username, serviceName, nil] autorelease];
+
+ NSMutableDictionary *query = [[[NSMutableDictionary alloc] initWithObjects: objects forKeys: keys] autorelease];
+
+ // First do a query for attributes, in case we already have a Keychain item with no password data set.
+ // One likely way such an incorrect item could have come about is due to the previous (incorrect)
+ // version of this code (which set the password as a generic attribute instead of password data).
+
+ NSDictionary *attributeResult = NULL;
+ NSMutableDictionary *attributeQuery = [query mutableCopy];
+ [attributeQuery setObject: (id) kCFBooleanTrue forKey:(id) kSecReturnAttributes];
+ OSStatus status = SecItemCopyMatching((CFDictionaryRef) attributeQuery, (CFTypeRef *) &attributeResult);
+
+ [attributeResult release];
+ [attributeQuery release];
+
+ if (status != noErr) {
+ // No existing item found--simply return nil for the password
+ if (status != errSecItemNotFound) {
+ //Only return an error if a real exception happened--not simply for "not found."
+ if (error) *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
+ }
+
+ return nil;
+ }
+
+ // We have an existing item, now query for the password data associated with it.
+
+ NSData *resultData = nil;
+ NSMutableDictionary *passwordQuery = [query mutableCopy];
+ [passwordQuery setObject: (id) kCFBooleanTrue forKey: (id) kSecReturnData];
+
+ status = SecItemCopyMatching((CFDictionaryRef) passwordQuery, (CFTypeRef *) &resultData);
+
+ [resultData autorelease];
+ [passwordQuery release];
+
+ if (status != noErr) {
+ if (status == errSecItemNotFound) {
+ // We found attributes for the item previously, but no password now, so return a special error.
+ // Users of this API will probably want to detect this error and prompt the user to
+ // re-enter their credentials. When you attempt to store the re-entered credentials
+ // using storeUsername:andPassword:forServiceName:updateExisting:error
+ // the old, incorrect entry will be deleted and a new one with a properly encrypted
+ // password will be added.
+ if (error) *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -1999 userInfo: nil];
+ }
+ else {
+ // Something else went wrong. Simply return the normal Keychain API error code.
+ if (error) *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
+ }
+
+ return nil;
+ }
+
+ NSString *password = nil;
+
+ if (resultData) {
+ password = [[NSString alloc] initWithData: resultData encoding: NSUTF8StringEncoding];
+ }
+ else {
+ // There is an existing item, but we weren't able to get password data for it for some reason,
+ // Possibly as a result of an item being incorrectly entered by the previous code.
+ // Set the -1999 error so the code above us can prompt the user again.
+ if (error) *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -1999 userInfo: nil];
+ }
+
+ return [password autorelease];
+}
+
++ (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error {
+ if (!username || !password || !serviceName) {
+ if (error) *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
+ return NO;
+ }
+
+ // See if we already have a password entered for these credentials.
+ NSError *checkPasswordError = nil;
+ NSString *existingPassword = [SFHFKeychainUtils getPasswordForUsername: username andServiceName: serviceName error: &checkPasswordError];
+
+ if ([checkPasswordError code] == -1999) {
+ // There is an existing entry without a password properly stored (possibly as a result of the previous incorrect version of this code.
+ // Delete the existing item before moving on entering a correct one.
+
+ NSError *deleteError = nil;
+
+ [self deleteItemForUsername: username andServiceName: serviceName error: &deleteError];
+
+ if ([deleteError code] != noErr) {
+ if (error) *error = deleteError;
+ return NO;
+ }
+ }
+ else if ([checkPasswordError code] != noErr) {
+ if (error) *error = checkPasswordError;
+ return NO;
+ }
+
+ if (error) *error = nil;
+
+ OSStatus status = noErr;
+
+ if (existingPassword) {
+ // We have an existing, properly entered item with a password.
+ // Update the existing item.
+
+ if (![existingPassword isEqualToString:password] && updateExisting) {
+ //Only update if we're allowed to update existing. If not, simply do nothing.
+
+ NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass,
+ kSecAttrService,
+ kSecAttrLabel,
+ kSecAttrAccount,
+ nil] autorelease];
+
+ NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword,
+ serviceName,
+ serviceName,
+ username,
+ nil] autorelease];
+
+ NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease];
+
+ status = SecItemUpdate((CFDictionaryRef) query, (CFDictionaryRef) [NSDictionary dictionaryWithObject: [password dataUsingEncoding: NSUTF8StringEncoding] forKey: (NSString *) kSecValueData]);
+ }
+ }
+ else {
+ // No existing entry (or an existing, improperly entered, and therefore now
+ // deleted, entry). Create a new entry.
+
+ NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass,
+ kSecAttrService,
+ kSecAttrLabel,
+ kSecAttrAccount,
+ kSecValueData,
+ nil] autorelease];
+
+ NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword,
+ serviceName,
+ serviceName,
+ username,
+ [password dataUsingEncoding: NSUTF8StringEncoding],
+ nil] autorelease];
+
+ NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease];
+
+ status = SecItemAdd((CFDictionaryRef) query, NULL);
+ }
+
+ if (status != noErr) {
+ // Something went wrong with adding the new item. Return the Keychain error code.
+ if (error) *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
+ return NO;
+ }
+ return YES;
+}
+
++ (BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error {
+ if (!username || !serviceName) {
+ if (error) *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
+ return NO;
+ }
+
+ if (error) *error = nil;
+
+ NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, kSecAttrAccount, kSecAttrService, kSecReturnAttributes, nil] autorelease];
+ NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, username, serviceName, kCFBooleanTrue, nil] autorelease];
+
+ NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease];
+
+ OSStatus status = SecItemDelete((CFDictionaryRef) query);
+
+ if (status != noErr) {
+ if (error) *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
+ return NO;
+ }
+ return YES;
+}
+
+#endif
+
+@end
\ No newline at end of file
--- /dev/null
+/*
+ * Base64Transcoder.c
+ * Base64Test
+ *
+ * Created by Jonathan Wight on Tue Mar 18 2003.
+ * Copyright (c) 2003 Toxic Software. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "Base64Transcoder.h"
+
+#include <math.h>
+#include <string.h>
+
+const u_int8_t kBase64EncodeTable[64] = {
+ /* 0 */ 'A', /* 1 */ 'B', /* 2 */ 'C', /* 3 */ 'D',
+ /* 4 */ 'E', /* 5 */ 'F', /* 6 */ 'G', /* 7 */ 'H',
+ /* 8 */ 'I', /* 9 */ 'J', /* 10 */ 'K', /* 11 */ 'L',
+ /* 12 */ 'M', /* 13 */ 'N', /* 14 */ 'O', /* 15 */ 'P',
+ /* 16 */ 'Q', /* 17 */ 'R', /* 18 */ 'S', /* 19 */ 'T',
+ /* 20 */ 'U', /* 21 */ 'V', /* 22 */ 'W', /* 23 */ 'X',
+ /* 24 */ 'Y', /* 25 */ 'Z', /* 26 */ 'a', /* 27 */ 'b',
+ /* 28 */ 'c', /* 29 */ 'd', /* 30 */ 'e', /* 31 */ 'f',
+ /* 32 */ 'g', /* 33 */ 'h', /* 34 */ 'i', /* 35 */ 'j',
+ /* 36 */ 'k', /* 37 */ 'l', /* 38 */ 'm', /* 39 */ 'n',
+ /* 40 */ 'o', /* 41 */ 'p', /* 42 */ 'q', /* 43 */ 'r',
+ /* 44 */ 's', /* 45 */ 't', /* 46 */ 'u', /* 47 */ 'v',
+ /* 48 */ 'w', /* 49 */ 'x', /* 50 */ 'y', /* 51 */ 'z',
+ /* 52 */ '0', /* 53 */ '1', /* 54 */ '2', /* 55 */ '3',
+ /* 56 */ '4', /* 57 */ '5', /* 58 */ '6', /* 59 */ '7',
+ /* 60 */ '8', /* 61 */ '9', /* 62 */ '+', /* 63 */ '/'
+};
+
+/*
+-1 = Base64 end of data marker.
+-2 = White space (tabs, cr, lf, space)
+-3 = Noise (all non whitespace, non-base64 characters)
+-4 = Dangerous noise
+-5 = Illegal noise (null byte)
+*/
+
+const int8_t kBase64DecodeTable[128] = {
+ /* 0x00 */ -5, /* 0x01 */ -3, /* 0x02 */ -3, /* 0x03 */ -3,
+ /* 0x04 */ -3, /* 0x05 */ -3, /* 0x06 */ -3, /* 0x07 */ -3,
+ /* 0x08 */ -3, /* 0x09 */ -2, /* 0x0a */ -2, /* 0x0b */ -2,
+ /* 0x0c */ -2, /* 0x0d */ -2, /* 0x0e */ -3, /* 0x0f */ -3,
+ /* 0x10 */ -3, /* 0x11 */ -3, /* 0x12 */ -3, /* 0x13 */ -3,
+ /* 0x14 */ -3, /* 0x15 */ -3, /* 0x16 */ -3, /* 0x17 */ -3,
+ /* 0x18 */ -3, /* 0x19 */ -3, /* 0x1a */ -3, /* 0x1b */ -3,
+ /* 0x1c */ -3, /* 0x1d */ -3, /* 0x1e */ -3, /* 0x1f */ -3,
+ /* ' ' */ -2, /* '!' */ -3, /* '"' */ -3, /* '#' */ -3,
+ /* '$' */ -3, /* '%' */ -3, /* '&' */ -3, /* ''' */ -3,
+ /* '(' */ -3, /* ')' */ -3, /* '*' */ -3, /* '+' */ 62,
+ /* ',' */ -3, /* '-' */ -3, /* '.' */ -3, /* '/' */ 63,
+ /* '0' */ 52, /* '1' */ 53, /* '2' */ 54, /* '3' */ 55,
+ /* '4' */ 56, /* '5' */ 57, /* '6' */ 58, /* '7' */ 59,
+ /* '8' */ 60, /* '9' */ 61, /* ':' */ -3, /* ';' */ -3,
+ /* '<' */ -3, /* '=' */ -1, /* '>' */ -3, /* '?' */ -3,
+ /* '@' */ -3, /* 'A' */ 0, /* 'B' */ 1, /* 'C' */ 2,
+ /* 'D' */ 3, /* 'E' */ 4, /* 'F' */ 5, /* 'G' */ 6,
+ /* 'H' */ 7, /* 'I' */ 8, /* 'J' */ 9, /* 'K' */ 10,
+ /* 'L' */ 11, /* 'M' */ 12, /* 'N' */ 13, /* 'O' */ 14,
+ /* 'P' */ 15, /* 'Q' */ 16, /* 'R' */ 17, /* 'S' */ 18,
+ /* 'T' */ 19, /* 'U' */ 20, /* 'V' */ 21, /* 'W' */ 22,
+ /* 'X' */ 23, /* 'Y' */ 24, /* 'Z' */ 25, /* '[' */ -3,
+ /* '\' */ -3, /* ']' */ -3, /* '^' */ -3, /* '_' */ -3,
+ /* '`' */ -3, /* 'a' */ 26, /* 'b' */ 27, /* 'c' */ 28,
+ /* 'd' */ 29, /* 'e' */ 30, /* 'f' */ 31, /* 'g' */ 32,
+ /* 'h' */ 33, /* 'i' */ 34, /* 'j' */ 35, /* 'k' */ 36,
+ /* 'l' */ 37, /* 'm' */ 38, /* 'n' */ 39, /* 'o' */ 40,
+ /* 'p' */ 41, /* 'q' */ 42, /* 'r' */ 43, /* 's' */ 44,
+ /* 't' */ 45, /* 'u' */ 46, /* 'v' */ 47, /* 'w' */ 48,
+ /* 'x' */ 49, /* 'y' */ 50, /* 'z' */ 51, /* '{' */ -3,
+ /* '|' */ -3, /* '}' */ -3, /* '~' */ -3, /* 0x7f */ -3
+};
+
+const u_int8_t kBits_00000011 = 0x03;
+const u_int8_t kBits_00001111 = 0x0F;
+const u_int8_t kBits_00110000 = 0x30;
+const u_int8_t kBits_00111100 = 0x3C;
+const u_int8_t kBits_00111111 = 0x3F;
+const u_int8_t kBits_11000000 = 0xC0;
+const u_int8_t kBits_11110000 = 0xF0;
+const u_int8_t kBits_11111100 = 0xFC;
+
+size_t EstimateBas64EncodedDataSize(size_t inDataSize)
+{
+size_t theEncodedDataSize = (int)ceil(inDataSize / 3.0) * 4;
+theEncodedDataSize = theEncodedDataSize / 72 * 74 + theEncodedDataSize % 72;
+return(theEncodedDataSize);
+}
+
+size_t EstimateBas64DecodedDataSize(size_t inDataSize)
+{
+size_t theDecodedDataSize = (int)ceil(inDataSize / 4.0) * 3;
+//theDecodedDataSize = theDecodedDataSize / 72 * 74 + theDecodedDataSize % 72;
+return(theDecodedDataSize);
+}
+
+bool Base64EncodeData(const void *inInputData, size_t inInputDataSize, char *outOutputData, size_t *ioOutputDataSize)
+{
+size_t theEncodedDataSize = EstimateBas64EncodedDataSize(inInputDataSize);
+if (*ioOutputDataSize < theEncodedDataSize)
+ return(false);
+*ioOutputDataSize = theEncodedDataSize;
+const u_int8_t *theInPtr = (const u_int8_t *)inInputData;
+u_int32_t theInIndex = 0, theOutIndex = 0;
+for (; theInIndex < (inInputDataSize / 3) * 3; theInIndex += 3)
+ {
+ outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2];
+ outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (theInPtr[theInIndex + 1] & kBits_11110000) >> 4];
+ outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 1] & kBits_00001111) << 2 | (theInPtr[theInIndex + 2] & kBits_11000000) >> 6];
+ outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 2] & kBits_00111111) >> 0];
+ if (theOutIndex % 74 == 72)
+ {
+ outOutputData[theOutIndex++] = '\r';
+ outOutputData[theOutIndex++] = '\n';
+ }
+ }
+const size_t theRemainingBytes = inInputDataSize - theInIndex;
+if (theRemainingBytes == 1)
+ {
+ outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2];
+ outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (0 & kBits_11110000) >> 4];
+ outOutputData[theOutIndex++] = '=';
+ outOutputData[theOutIndex++] = '=';
+ if (theOutIndex % 74 == 72)
+ {
+ outOutputData[theOutIndex++] = '\r';
+ outOutputData[theOutIndex++] = '\n';
+ }
+ }
+else if (theRemainingBytes == 2)
+ {
+ outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2];
+ outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (theInPtr[theInIndex + 1] & kBits_11110000) >> 4];
+ outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 1] & kBits_00001111) << 2 | (0 & kBits_11000000) >> 6];
+ outOutputData[theOutIndex++] = '=';
+ if (theOutIndex % 74 == 72)
+ {
+ outOutputData[theOutIndex++] = '\r';
+ outOutputData[theOutIndex++] = '\n';
+ }
+ }
+return(true);
+}
+
+bool Base64DecodeData(const void *inInputData, size_t inInputDataSize, void *ioOutputData, size_t *ioOutputDataSize)
+{
+memset(ioOutputData, '.', *ioOutputDataSize);
+
+size_t theDecodedDataSize = EstimateBas64DecodedDataSize(inInputDataSize);
+if (*ioOutputDataSize < theDecodedDataSize)
+ return(false);
+*ioOutputDataSize = 0;
+const u_int8_t *theInPtr = (const u_int8_t *)inInputData;
+u_int8_t *theOutPtr = (u_int8_t *)ioOutputData;
+size_t theInIndex = 0, theOutIndex = 0;
+u_int8_t theOutputOctet;
+size_t theSequence = 0;
+for (; theInIndex < inInputDataSize; )
+ {
+ int8_t theSextet = 0;
+
+ int8_t theCurrentInputOctet = theInPtr[theInIndex];
+ theSextet = kBase64DecodeTable[theCurrentInputOctet];
+ if (theSextet == -1)
+ break;
+ while (theSextet == -2)
+ {
+ theCurrentInputOctet = theInPtr[++theInIndex];
+ theSextet = kBase64DecodeTable[theCurrentInputOctet];
+ }
+ while (theSextet == -3)
+ {
+ theCurrentInputOctet = theInPtr[++theInIndex];
+ theSextet = kBase64DecodeTable[theCurrentInputOctet];
+ }
+ if (theSequence == 0)
+ {
+ theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 2 & kBits_11111100;
+ }
+ else if (theSequence == 1)
+ {
+ theOutputOctet |= (theSextet >- 0 ? theSextet : 0) >> 4 & kBits_00000011;
+ theOutPtr[theOutIndex++] = theOutputOctet;
+ }
+ else if (theSequence == 2)
+ {
+ theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 4 & kBits_11110000;
+ }
+ else if (theSequence == 3)
+ {
+ theOutputOctet |= (theSextet >= 0 ? theSextet : 0) >> 2 & kBits_00001111;
+ theOutPtr[theOutIndex++] = theOutputOctet;
+ }
+ else if (theSequence == 4)
+ {
+ theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 6 & kBits_11000000;
+ }
+ else if (theSequence == 5)
+ {
+ theOutputOctet |= (theSextet >= 0 ? theSextet : 0) >> 0 & kBits_00111111;
+ theOutPtr[theOutIndex++] = theOutputOctet;
+ }
+ theSequence = (theSequence + 1) % 6;
+ if (theSequence != 2 && theSequence != 4)
+ theInIndex++;
+ }
+*ioOutputDataSize = theOutIndex;
+return(true);
+}
--- /dev/null
+/*
+ * Base64Transcoder.h
+ * Base64Test
+ *
+ * Created by Jonathan Wight on Tue Mar 18 2003.
+ * Copyright (c) 2003 Toxic Software. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdbool.h>
+
+extern size_t EstimateBas64EncodedDataSize(size_t inDataSize);
+extern size_t EstimateBas64DecodedDataSize(size_t inDataSize);
+
+extern bool Base64EncodeData(const void *inInputData, size_t inInputDataSize, char *outOutputData, size_t *ioOutputDataSize);
+extern bool Base64DecodeData(const void *inInputData, size_t inInputDataSize, void *ioOutputData, size_t *ioOutputDataSize);
+
--- /dev/null
+//
+// hmac.c
+// OAuthConsumer
+//
+// Created by Jonathan Wight on 4/8/8.
+// Copyright 2008 Jonathan Wight. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+/*
+ * Implementation of HMAC-SHA1. Adapted from example at http://tools.ietf.org/html/rfc2104
+
+ */
+
+#include "sha1.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+void hmac_sha1(const unsigned char *inText, size_t inTextLength, unsigned char* inKey, size_t inKeyLength, unsigned char *outDigest)
+{
+const size_t B = 64;
+const size_t L = 20;
+
+SHA1_CTX theSHA1Context;
+unsigned char k_ipad[B + 1]; /* inner padding - key XORd with ipad */
+unsigned char k_opad[B + 1]; /* outer padding - key XORd with opad */
+
+/* if key is longer than 64 bytes reset it to key=SHA1 (key) */
+if (inKeyLength > B)
+ {
+ SHA1Init(&theSHA1Context);
+ SHA1Update(&theSHA1Context, inKey, inKeyLength);
+ SHA1Final(inKey, &theSHA1Context);
+ inKeyLength = L;
+ }
+
+/* start out by storing key in pads */
+memset(k_ipad, 0, sizeof k_ipad);
+memset(k_opad, 0, sizeof k_opad);
+memcpy(k_ipad, inKey, inKeyLength);
+memcpy(k_opad, inKey, inKeyLength);
+
+/* XOR key with ipad and opad values */
+int i;
+for (i = 0; i < B; i++)
+ {
+ k_ipad[i] ^= 0x36;
+ k_opad[i] ^= 0x5c;
+ }
+
+/*
+* perform inner SHA1
+*/
+SHA1Init(&theSHA1Context); /* init context for 1st pass */
+SHA1Update(&theSHA1Context, k_ipad, B); /* start with inner pad */
+SHA1Update(&theSHA1Context, (unsigned char *)inText, inTextLength); /* then text of datagram */
+SHA1Final((unsigned char *)outDigest, &theSHA1Context); /* finish up 1st pass */
+
+/*
+* perform outer SHA1
+*/
+SHA1Init(&theSHA1Context); /* init context for 2nd
+* pass */
+SHA1Update(&theSHA1Context, k_opad, B); /* start with outer pad */
+SHA1Update(&theSHA1Context, outDigest, L); /* then results of 1st
+* hash */
+SHA1Final(outDigest, &theSHA1Context); /* finish up 2nd pass */
+
+}
\ No newline at end of file
--- /dev/null
+//
+// hmac.h
+// OAuthConsumer
+//
+// Created by Jonathan Wight on 4/8/8.
+// Copyright 2008 Jonathan Wight. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef HMAC_H
+#define HMAC_H 1
+
+extern void hmac_sha1(const unsigned char *inText, int inTextLength, unsigned char* inKey, const unsigned int inKeyLength, unsigned char *outDigest);
+
+#endif /* HMAC_H */
\ No newline at end of file
--- /dev/null
+/*
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+ A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+ 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+/* #define LITTLE_ENDIAN * This should be #define'd if true. */
+#if __LITTLE_ENDIAN__
+#define LITTLE_ENDIAN
+#endif
+/* #define SHA1HANDSOFF * Copies data before messing with it. */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "sha1.h"
+
+void SHA1Transform(unsigned long state[5], unsigned char buffer[64]);
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#ifdef LITTLE_ENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+ |(rol(block->l[i],8)&0x00FF00FF))
+#else
+#define blk0(i) block->l[i]
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+ ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void SHA1Transform(unsigned long state[5], unsigned char buffer[64])
+{
+unsigned long a, b, c, d, e;
+typedef union {
+ unsigned char c[64];
+ unsigned long l[16];
+} CHAR64LONG16;
+CHAR64LONG16* block;
+#ifdef SHA1HANDSOFF
+static unsigned char workspace[64];
+ block = (CHAR64LONG16*)workspace;
+ memcpy(block, buffer, 64);
+#else
+ block = (CHAR64LONG16*)buffer;
+#endif
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void SHA1Init(SHA1_CTX* context)
+{
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len)
+{
+unsigned int i, j;
+
+ j = (context->count[0] >> 3) & 63;
+ if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
+ context->count[1] += (len >> 29);
+ if ((j + len) > 63) {
+ memcpy(&context->buffer[j], data, (i = 64-j));
+ SHA1Transform(context->state, context->buffer);
+ for ( ; i + 63 < len; i += 64) {
+ SHA1Transform(context->state, &data[i]);
+ }
+ j = 0;
+ }
+ else i = 0;
+ memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
+{
+unsigned long i, j;
+unsigned char finalcount[8];
+
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+ SHA1Update(context, (unsigned char *)"\200", 1);
+ while ((context->count[0] & 504) != 448) {
+ SHA1Update(context, (unsigned char *)"\0", 1);
+ }
+ SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
+ for (i = 0; i < 20; i++) {
+ digest[i] = (unsigned char)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+ /* Wipe variables */
+ i = j = 0;
+ memset(context->buffer, 0, 64);
+ memset(context->state, 0, 20);
+ memset(context->count, 0, 8);
+ memset(&finalcount, 0, 8);
+#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
+ SHA1Transform(context->state, context->buffer);
+#endif
+}
--- /dev/null
+
+// From http://www.mirrors.wiretapped.net/security/cryptography/hashes/sha1/sha1.c
+
+typedef struct {
+ unsigned long state[5];
+ unsigned long count[2];
+ unsigned char buffer[64];
+} SHA1_CTX;
+
+extern void SHA1Init(SHA1_CTX* context);
+extern void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len);
+extern void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
--- /dev/null
+//
+// NSString+URLEncoding.h
+//
+// Created by Jon Crosby on 10/19/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+// Modified by Cassie Doll on 02/02/09
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import <Foundation/Foundation.h>
+
+
+@interface NSString (OAURLEncodingAdditions)
+
+- (NSString *)URLEncodedString;
+- (NSString *)MinimalURLEncodedString;
+- (NSString *)URLDecodedString;
+
+@end
--- /dev/null
+//
+// NSString+URLEncoding.m
+//
+// Created by Jon Crosby on 10/19/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+// Modified by Cassie Doll on 02/02/09
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import "NSString+URLEncoding.h"
+
+
+@implementation NSString (OAURLEncodingAdditions)
+
+- (NSString *)URLEncodedString
+{
+ NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
+ (CFStringRef)self,
+ NULL,
+ CFSTR("!*'();:@&=+$,/?#[]"),
+ kCFStringEncodingUTF8);
+ [result autorelease];
+ return result;
+}
+
+- (NSString *)MinimalURLEncodedString {
+ NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
+ (CFStringRef)self,
+ CFSTR("%"), // characters to leave unescaped (NULL = all escaped sequences are replaced)
+ CFSTR("?=&+"), // legal URL characters to be escaped (NULL = all legal characters are replaced)
+ kCFStringEncodingUTF8); // encoding
+ [result autorelease];
+ return result;
+}
+
+- (NSString*)URLDecodedString
+{
+ NSString *result = (NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault,
+ (CFStringRef)self,
+ CFSTR(""),
+ kCFStringEncodingUTF8);
+ [result autorelease];
+ return result;
+}
+
+@end
--- /dev/null
+//
+// OAAsynchronousDataFetcher.h
+// OAuthConsumer
+//
+// Created by Zsombor Szabó on 12/3/08.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import <Foundation/Foundation.h>
+
+@class OAMutableURLRequest;
+
+@interface OAAsynchronousDataFetcher : NSObject {
+ OAMutableURLRequest *request;
+ NSURLResponse *response;
+ NSURLConnection *connection;
+ NSMutableData *responseData;
+ id delegate;
+ SEL didFinishSelector;
+ SEL didFailSelector;
+}
+
++ (id)asynchronousFetcherWithRequest:(OAMutableURLRequest *)aRequest delegate:(id)aDelegate didFinishSelector:(SEL)finishSelector didFailSelector:(SEL)failSelector;
+- (id)initWithRequest:(OAMutableURLRequest *)aRequest delegate:(id)aDelegate didFinishSelector:(SEL)finishSelector didFailSelector:(SEL)failSelector;
+
+- (void)start;
+
+@end
--- /dev/null
+//
+// OAAsynchronousDataFetcher.m
+// OAuthConsumer
+//
+// Created by Zsombor Szabó on 12/3/08.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "OAAsynchronousDataFetcher.h"
+
+#import "OAServiceTicket.h"
+
+@implementation OAAsynchronousDataFetcher
+
++ (id)asynchronousFetcherWithRequest:(OAMutableURLRequest *)aRequest delegate:(id)aDelegate didFinishSelector:(SEL)finishSelector didFailSelector:(SEL)failSelector
+{
+ return [[[OAAsynchronousDataFetcher alloc] initWithRequest:aRequest delegate:aDelegate didFinishSelector:finishSelector didFailSelector:failSelector] autorelease];
+}
+
+- (id)initWithRequest:(OAMutableURLRequest *)aRequest delegate:(id)aDelegate didFinishSelector:(SEL)finishSelector didFailSelector:(SEL)failSelector
+{
+ if (self = [super init])
+ {
+ request = [aRequest retain];
+ delegate = aDelegate;
+ didFinishSelector = finishSelector;
+ didFailSelector = failSelector;
+ }
+ return self;
+}
+
+- (void)start
+{
+ [request prepare];
+
+ if (connection)
+ [connection release];
+
+ connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
+
+ if (connection)
+ {
+ if (responseData)
+ [responseData release];
+ responseData = [[NSMutableData data] retain];
+ }
+ else
+ {
+ OAServiceTicket *ticket= [[OAServiceTicket alloc] initWithRequest:request
+ response:nil
+ didSucceed:NO];
+ [delegate performSelector:didFailSelector
+ withObject:ticket
+ withObject:nil];
+ [ticket release];
+ }
+}
+
+- (void)cancel
+{
+ if (connection)
+ [connection cancel];
+}
+
+- (void)dealloc
+{
+ if (request) [request release];
+ if (connection) [connection release];
+ if (response) [response release];
+ if (responseData) [responseData release];
+ [super dealloc];
+}
+
+#pragma mark -
+#pragma mark NSURLConnection's delegate methods
+
+- (void)connection:(NSURLConnection *)aConnection didReceiveResponse:(NSURLResponse *)aResponse
+{
+ if (response)
+ [response release];
+ response = [aResponse retain];
+ [responseData setLength:0];
+}
+
+- (void)connection:(NSURLConnection *)aConnection didReceiveData:(NSData *)data
+{
+ [responseData appendData:data];
+}
+
+- (void)connection:(NSURLConnection *)aConnection didFailWithError:(NSError *)error
+{
+ OAServiceTicket *ticket= [[OAServiceTicket alloc] initWithRequest:request
+ response:response
+ didSucceed:NO];
+ [delegate performSelector:didFailSelector
+ withObject:ticket
+ withObject:error];
+
+ [ticket release];
+}
+
+- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection
+{
+ OAServiceTicket *ticket = [[OAServiceTicket alloc] initWithRequest:request
+ response:response
+ didSucceed:[(NSHTTPURLResponse *)response statusCode] < 400];
+ [delegate performSelector:didFinishSelector
+ withObject:ticket
+ withObject:responseData];
+
+ [ticket release];
+}
+
+@end
+
--- /dev/null
+//
+// OAConsumer.h
+// OAuthConsumer
+//
+// Created by Jon Crosby on 10/19/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+// Modified by Cassie Doll on 02/02/09
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import <Foundation/Foundation.h>
+
+
+@interface OAConsumer : NSObject {
+@protected
+ NSString *key;
+ NSString *secret;
+}
+@property(retain) NSString *key;
+@property(retain) NSString *secret;
+
+- (id)initWithKey:(NSString *)aKey secret:(NSString *)aSecret;
+
+@end
--- /dev/null
+//
+// OAConsumer.m
+// OAuthConsumer
+//
+// Created by Jon Crosby on 10/19/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+// Modified by Cassie Doll on 02/02/09
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "OAConsumer.h"
+
+
+@implementation OAConsumer
+@synthesize key, secret;
+
+#pragma mark init
+
+- (id)initWithKey:(NSString *)aKey secret:(NSString *)aSecret
+{
+ if (self = [super init])
+ {
+ self.key = aKey;
+ self.secret = aSecret;
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ [key release];
+ [secret release];
+ [super dealloc];
+}
+
+@end
--- /dev/null
+//
+// OADataFetcher.h
+// OAuthConsumer
+//
+// Created by Jon Crosby on 11/5/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+// Modified by Cassie Doll on 02/02/09
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import <Foundation/Foundation.h>
+#import "OAMutableURLRequest.h"
+#import "OAServiceTicket.h"
+
+
+@interface OADataFetcher : NSObject
+
++ (void)fetchDataWithRequest:(OAMutableURLRequest *)aRequest
+ delegate:(id)aDelegate
+ didFinishSelector:(SEL)finishSelector;
+
+@end
--- /dev/null
+//
+// OADataFetcher.m
+// OAuthConsumer
+//
+// Created by Jon Crosby on 11/5/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+// Modified by Cassie Doll on 02/02/09
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import "OADataFetcher.h"
+
+
+@implementation OADataFetcher
+
++ (void)fetchDataWithRequest:(OAMutableURLRequest *)request
+ delegate:(id)delegate
+ didFinishSelector:(SEL)didFinishSelector {
+ NSURLResponse *response;
+ NSError *error = nil;
+
+ [request prepare];
+ // TODO: use the asynch fetcher from Google's open source library.
+ // Never do sync fetches in a client app on the main thread.
+ NSData *responseData = [NSURLConnection sendSynchronousRequest:request
+ returningResponse:&response
+ error:&error];
+
+ NSString *responseBody = [[[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding] autorelease];
+ NSLog(@"Request url: %@", [[request URL] absoluteString]);
+ NSLog(@"Response Body: %@", responseBody);
+
+ if (response == nil || responseData == nil || error != nil) {
+ OAServiceTicket *ticket = [[[OAServiceTicket alloc] initWithRequest:request response:response didSucceed:NO] autorelease];
+ [delegate performSelector:didFinishSelector withObject:ticket withObject:error];
+
+ } else {
+ NSLog(@"response had status code %i", [(NSHTTPURLResponse *)response statusCode]);
+ OAServiceTicket *ticket = [[[OAServiceTicket alloc] initWithRequest:request
+ response:response
+ didSucceed:[(NSHTTPURLResponse *)response statusCode] < 400] autorelease];
+
+ [delegate performSelector:didFinishSelector withObject:ticket withObject:responseBody];
+ }
+}
+
+@end
--- /dev/null
+//
+// OAMutableURLRequest.h
+// OAuthConsumer
+//
+// Created by Jon Crosby on 10/19/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+// Modified by Cassie Doll on 02/02/09
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import <Foundation/Foundation.h>
+#import "OASignatureProviding.h"
+@class OAConsumer;
+@class OAToken;
+@class OAHMAC_SHA1SignatureProvider;
+@class OARequestParameter;
+
+
+@interface OAMutableURLRequest : NSMutableURLRequest {
+@protected
+ OAConsumer *consumer;
+ OAToken *token;
+ NSString *realm;
+ NSString *signature;
+ id<OASignatureProviding> signatureProvider;
+ NSString *nonce;
+ NSString *timestamp;
+ NSMutableArray *parameters;
+}
+@property(readonly) NSString *signature;
+@property(readonly) NSString *nonce;
+@property(retain) NSMutableArray *parameters;
+
+- (id)initWithURL:(NSURL *)aUrl
+ consumer:(OAConsumer *)aConsumer
+ token:(OAToken *)aToken;
+
+- (id)initWithURL:(NSURL *)aUrl
+ parameters:(NSArray *)extraParameters
+ consumer:(OAConsumer *)aConsumer
+ token:(OAToken *)aToken;
+
+- (id)initWithURL:(NSURL *)aUrl
+ consumer:(OAConsumer *)aConsumer
+ token:(OAToken *)aToken
+ realm:(NSString *)aRealm
+signatureProvider:(id<OASignatureProviding, NSObject>)aProvider;
+
+- (id)initWithURL:(NSURL *)aUrl
+ parameters:(NSArray *)extraParameters
+ consumer:(OAConsumer *)aConsumer
+ token:(OAToken *)aToken
+ realm:(NSString *)aRealm
+signatureProvider:(id<OASignatureProviding, NSObject>)aProvider
+ nonce:(NSString *)aNonce
+ timestamp:(NSString *)aTimestamp;
+
+- (void)prepare;
+
+@end
--- /dev/null
+//
+// OAMutableURLRequest.m
+// OAuthConsumer
+//
+// Created by Jon Crosby on 10/19/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+// Modified by Cassie Doll on 02/02/09
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import "OAMutableURLRequest.h"
+#import "OAConsumer.h"
+#import "OAToken.h"
+#import "OAHMAC_SHA1SignatureProvider.h"
+#import "OARequestParameter.h"
+
+@interface OAMutableURLRequest ()
+@property (nonatomic, retain) id<OASignatureProviding> signatureProvider;
+- (NSString *)_generateTimestamp;
+- (NSString *)_generateNonce;
+- (NSString *)_signatureBaseString;
+- (void)_putParametersInRequest;
+- (NSString *)_getNormalizedRequestParameters;
+@end
+
+@implementation OAMutableURLRequest
+@synthesize signatureProvider;
+@synthesize signature, nonce, parameters;
+
+#pragma mark init
+
+- (id)initWithURL:(NSURL *)aUrl consumer:(OAConsumer *)aConsumer token:(OAToken *)aToken {
+ return [self initWithURL:aUrl parameters:nil consumer:aConsumer token:aToken];
+}
+
+- (id)initWithURL:(NSURL *)aUrl parameters:(NSArray *)extraParameters
+ consumer:(OAConsumer *)aConsumer token:(OAToken *)aToken {
+ return [self initWithURL:aUrl parameters:extraParameters consumer:aConsumer token:aToken realm:nil
+ signatureProvider:nil nonce:[self _generateNonce] timestamp:[self _generateTimestamp]];
+}
+
+- (id)initWithURL:(NSURL *)aUrl consumer:(OAConsumer *)aConsumer token:(OAToken *)aToken
+ realm:(NSString *)aRealm signatureProvider:(id<OASignatureProviding, NSObject>)aProvider {
+ return [self initWithURL:aUrl parameters:nil consumer:aConsumer token:aToken realm:aRealm
+ signatureProvider:aProvider nonce:[self _generateNonce] timestamp:[self _generateTimestamp]];
+}
+
+// Setting a timestamp and nonce to known
+// values can be helpful for testing
+- (id)initWithURL:(NSURL *)aUrl
+ parameters:(NSArray *)extraParameters
+ consumer:(OAConsumer *)aConsumer
+ token:(OAToken *)aToken
+ realm:(NSString *)aRealm
+signatureProvider:(id<OASignatureProviding, NSObject>)aProvider
+ nonce:(NSString *)aNonce
+ timestamp:(NSString *)aTimestamp {
+ if (self = [super initWithURL:aUrl
+ cachePolicy:NSURLRequestReloadIgnoringCacheData
+ timeoutInterval:20.0]) {
+ consumer = [aConsumer retain];
+
+ // empty token for Unauthorized Request Token transaction
+ if (aToken == nil) {
+ token = nil;
+ } else {
+ token = [aToken retain];
+ }
+
+ if (aRealm == nil) {
+ realm = @"";
+ } else {
+ realm = [aRealm retain];
+ }
+
+ // default to HMAC-SHA1
+ if (aProvider == nil) {
+ self.signatureProvider = [[[OAHMAC_SHA1SignatureProvider alloc] init] autorelease];
+ } else {
+ self.signatureProvider = aProvider;
+ }
+
+ timestamp = [aTimestamp retain];
+ nonce = [aNonce retain];
+
+ if (extraParameters) {
+ self.parameters = [NSMutableArray arrayWithArray:extraParameters];
+ } else {
+ self.parameters = [NSMutableArray arrayWithCapacity:7];
+ }
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [consumer release];
+ [token release];
+ [realm release];
+ [signatureProvider release];
+ [timestamp release];
+ [nonce release];
+ [parameters release];
+ [super dealloc];
+}
+
+#pragma mark -
+#pragma mark Public
+
+- (void)prepare {
+ // Add in all of the oauth parameters
+ [parameters addObject:[OARequestParameter requestParameterWithName:@"oauth_consumer_key" value:consumer.key]];
+ [parameters addObject:[OARequestParameter requestParameterWithName:@"oauth_signature_method" value:[signatureProvider name]]];
+ [parameters addObject:[OARequestParameter requestParameterWithName:@"oauth_timestamp" value:timestamp]];
+ [parameters addObject:[OARequestParameter requestParameterWithName:@"oauth_nonce" value:nonce]];
+ [parameters addObject:[OARequestParameter requestParameterWithName:@"oauth_version" value:@"1.0"]];
+
+ if (token) {
+ [parameters addObject:[OARequestParameter requestParameterWithName:@"oauth_token" value:token.key]];
+ }
+
+ // TODO: if later RSA-SHA1 support is added then a little code redesign is needed
+ NSString *baseString = [self _signatureBaseString];
+ NSString *secret = [NSString stringWithFormat:@"%@&%@",
+ [consumer.secret URLEncodedString],
+ token ? [token.secret URLEncodedString] : @""];
+
+ NSLog(@"Base string: %@ and secret: %@", baseString, secret);
+ signature = [signatureProvider signClearText:baseString
+ withSecret:secret];
+
+ [parameters addObject:[OARequestParameter requestParameterWithName:@"oauth_signature" value:signature]];
+ [self _putParametersInRequest];
+}
+
+#pragma mark -
+#pragma mark Private
+
+- (NSString *)_generateTimestamp {
+ return [NSString stringWithFormat:@"%d", time(NULL)];
+}
+
+- (NSString *)_generateNonce {
+ CFUUIDRef theUUID = CFUUIDCreate(NULL);
+ CFStringRef string = CFUUIDCreateString(NULL, theUUID);
+ NSMakeCollectable(theUUID);
+ return [(NSString *)string autorelease];
+}
+
+- (NSString *)_signatureBaseString {
+ return [NSString stringWithFormat:@"%@&%@&%@",
+ [self HTTPMethod],
+ [[[self URL] absoluteString] URLEncodedString],
+ [[self _getNormalizedRequestParameters] URLEncodedString]];
+}
+
+- (void)_putParametersInRequest {
+ NSString *normalizedRequestParameters = [self _getNormalizedRequestParameters];
+
+ if ([[self HTTPMethod] isEqualToString:@"GET"] || [[self HTTPMethod] isEqualToString:@"DELETE"]) {
+ [self setURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@?%@", [[self URL] absoluteString], normalizedRequestParameters]]];
+
+ } else {
+ // POST, PUT
+ NSData *postData = [normalizedRequestParameters dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
+ [self setHTTPBody:postData];
+ [self setValue:[NSString stringWithFormat:@"%d", [postData length]] forHTTPHeaderField:@"Content-Length"];
+ [self setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
+
+ NSString *oauthToken = @"";
+ if (token) {
+ oauthToken = [NSString stringWithFormat:@"oauth_token=\"%@\", ", [token.key URLEncodedString]];
+ }
+
+ NSString *oauthHeader = [NSString stringWithFormat:@"OAuth realm=\"%@\" oauth_consumer_key=\"%@\", %@oauth_signature_method=\"%@\", oauth_signature=\"%@\", oauth_timestamp=\"%@\", oauth_nonce=\"%@\", oauth_version=\"1.0\"",
+ [realm URLEncodedString],
+ [consumer.key URLEncodedString],
+ oauthToken,
+ [[signatureProvider name] URLEncodedString],
+ [signature URLEncodedString],
+ timestamp,
+ nonce];
+
+ [self setValue:oauthHeader forHTTPHeaderField:@"Authorization"];
+ [oauthToken release];
+ [oauthHeader release];
+ }
+}
+
+- (NSString *)_getNormalizedRequestParameters {
+ NSMutableArray *parameterPairs = [NSMutableArray arrayWithCapacity:([parameters count])];
+
+ for (OARequestParameter *param in parameters) {
+ [parameterPairs addObject:[param URLEncodedNameValuePair]];
+ }
+
+ NSArray* sortedPairs = [parameterPairs sortedArrayUsingSelector:@selector(compare:)];
+ return [sortedPairs componentsJoinedByString:@"&"];
+}
+
+
+@end
--- /dev/null
+//
+// OARequestParameter.h
+// OAuthConsumer
+//
+// Created by Jon Crosby on 10/19/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import <Foundation/Foundation.h>
+#import "NSString+URLEncoding.h"
+
+
+@interface OARequestParameter : NSObject {
+@protected
+ NSString *name;
+ NSString *value;
+}
+@property(retain) NSString *name;
+@property(retain) NSString *value;
+
++ (id)requestParameterWithName:(NSString *)aName value:(NSString *)aValue;
+- (id)initWithName:(NSString *)aName value:(NSString *)aValue;
+- (NSString *)URLEncodedName;
+- (NSString *)URLEncodedValue;
+- (NSString *)URLEncodedNameValuePair;
+
+@end
--- /dev/null
+//
+// OARequestParameter.m
+// OAuthConsumer
+//
+// Created by Jon Crosby on 10/19/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import "OARequestParameter.h"
+
+
+@implementation OARequestParameter
+@synthesize name, value;
+
++ (id)requestParameterWithName:(NSString *)aName value:(NSString *)aValue
+{
+ return [[[OARequestParameter alloc] initWithName:aName value:aValue] autorelease];
+}
+
+- (id)initWithName:(NSString *)aName value:(NSString *)aValue
+{
+ if (self = [super init])
+ {
+ self.name = aName;
+ self.value = aValue;
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ [name release];
+ [value release];
+ [super dealloc];
+}
+
+- (NSString *)URLEncodedName
+{
+ return [self.name URLEncodedString];
+}
+
+- (NSString *)URLEncodedValue
+{
+ return [self.value URLEncodedString];
+}
+
+- (NSString *)URLEncodedNameValuePair
+{
+ return [NSString stringWithFormat:@"%@=%@", [self URLEncodedName], [self URLEncodedValue]];
+}
+
+@end
--- /dev/null
+//
+// OAServiceTicket.h
+// OAuthConsumer
+//
+// Created by Jon Crosby on 11/5/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import <Foundation/Foundation.h>
+#import "OAMutableURLRequest.h"
+
+
+@interface OAServiceTicket : NSObject {
+@private
+ OAMutableURLRequest *request;
+ NSURLResponse *response;
+ BOOL didSucceed;
+}
+@property(retain) OAMutableURLRequest *request;
+@property(retain) NSURLResponse *response;
+@property(assign) BOOL didSucceed;
+
+- (id)initWithRequest:(OAMutableURLRequest *)aRequest response:(NSURLResponse *)aResponse didSucceed:(BOOL)success;
+
+@end
--- /dev/null
+//
+// OAServiceTicket.m
+// OAuthConsumer
+//
+// Created by Jon Crosby on 11/5/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import "OAServiceTicket.h"
+
+
+@implementation OAServiceTicket
+@synthesize request, response, didSucceed;
+
+- (id)initWithRequest:(OAMutableURLRequest *)aRequest response:(NSURLResponse *)aResponse didSucceed:(BOOL)success
+{
+ if (self = [super init])
+ {
+ self.request = aRequest;
+ self.response = aResponse;
+ self.didSucceed = success;
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ [request release];
+ [response release];
+ [super dealloc];
+}
+
+@end
--- /dev/null
+//
+// OAToken.h
+// OAuthConsumer
+//
+// Created by Jon Crosby on 10/19/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+// Modified by Cassie Doll on 02/02/09
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import <Foundation/Foundation.h>
+
+@interface OAToken : NSObject {
+@public
+ NSString *key;
+ NSString *secret;
+}
+@property(copy) NSString *key;
+@property(copy) NSString *secret;
+
+- (id)initWithKey:(NSString *)aKey secret:(NSString *)aSecret;
+- (id)initWithHTTPResponseBody:(NSString *)body;
+@end
--- /dev/null
+//
+// OAToken.m
+// OAuthConsumer
+//
+// Created by Jon Crosby on 10/19/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+// Modified by Cassie Doll on 02/02/09
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import "OAToken.h"
+#import "NSString+URLEncoding.h"
+
+@implementation OAToken
+
+@synthesize key, secret;
+
+#pragma mark init
+
+- (id)init
+{
+ if (self = [super init])
+ {
+ self.key = @"";
+ self.secret = @"";
+ }
+ return self;
+}
+
+- (id)initWithKey:(NSString *)aKey secret:(NSString *)aSecret
+{
+ if (self = [super init])
+ {
+ self.key = aKey;
+ self.secret = aSecret;
+ }
+ return self;
+}
+
+- (id)initWithHTTPResponseBody:(NSString *)body
+{
+ if (self = [super init])
+ {
+ NSArray *pairs = [body componentsSeparatedByString:@"&"];
+
+ for (NSString *pair in pairs) {
+ NSArray *elements = [pair componentsSeparatedByString:@"="];
+ if ([[elements objectAtIndex:0] isEqualToString:@"oauth_token"]) {
+ self.key = [[elements objectAtIndex:1] URLDecodedString];
+ } else if ([[elements objectAtIndex:0] isEqualToString:@"oauth_token_secret"]) {
+ self.secret = [[elements objectAtIndex:1] URLDecodedString];
+ }
+ }
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ [key release];
+ [secret release];
+ [super dealloc];
+}
+
+@end
--- /dev/null
+//
+// OAToken_KeychainExtensions.h
+// TouchTheFireEagle
+//
+// Created by Jonathan Wight on 04/04/08.
+// Modified by Cassie Doll on 02/02/09
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "OAToken.h"
+
+#import <Security/Security.h>
+
+@interface OAToken (OAToken_KeychainExtensions)
+
+- (NSError *)storeInDefaultKeychainWithAppName:(NSString *)name tokenType:(NSString *)type;
+- (id)initWithKeychainUsingAppName:(NSString *)name tokenType:(NSString *)type;
+
+@end
--- /dev/null
+//
+// OAToken_KeychainExtensions.m
+// TouchTheFireEagle
+//
+// Created by Jonathan Wight on 04/04/08.
+// Modified by Cassie Doll on 02/02/09
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "OAToken_KeychainExtensions.h"
+#import "SFHFKeychainUtils.h"
+
+@implementation OAToken (OAToken_KeychainExtensions)
+
+
+- (NSError *)storeInDefaultKeychainWithAppName:(NSString *)name tokenType:(NSString *)type {
+ NSString *password = [NSString stringWithFormat:@"%@:::%@", self.key, self.secret];
+
+ NSError *error = nil;
+ [SFHFKeychainUtils storeUsername:type andPassword:password
+ forServiceName:name updateExisting:TRUE error:&error];
+ return error;
+}
+
+- (id)initWithKeychainUsingAppName:(NSString *)name tokenType:(NSString *)type {
+ self = [super init];
+ if (self) {
+ NSString *password = [SFHFKeychainUtils getPasswordForUsername:type andServiceName:name error:nil];
+
+ if (!password || [password length] == 0) {
+ [self release];
+ return nil;
+ }
+
+ NSArray *components =[password componentsSeparatedByString:@":::"];
+ if (2 <= [components count]) {
+ self.key = [components objectAtIndex:0];
+ self.secret = [components objectAtIndex:1];
+ }
+ // TODO: this will fail if the key or the secret contain ':::'
+ }
+ return self;
+}
+
+
+
+@end
--- /dev/null
+//
+// OAHMAC_SHA1SignatureProvider.h
+// OAuthConsumer
+//
+// Created by Jon Crosby on 10/19/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import <Foundation/Foundation.h>
+#import "OASignatureProviding.h"
+
+
+@interface OAHMAC_SHA1SignatureProvider : NSObject <OASignatureProviding>
+@end
--- /dev/null
+//
+// OAHMAC_SHA1SignatureProvider.m
+// OAuthConsumer
+//
+// Created by Jon Crosby on 10/19/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import "OAHMAC_SHA1SignatureProvider.h"
+
+#include "hmac.h"
+#include "Base64Transcoder.h"
+
+@implementation OAHMAC_SHA1SignatureProvider
+
+- (NSString *)name
+{
+ return @"HMAC-SHA1";
+}
+
+- (NSString *)signClearText:(NSString *)text withSecret:(NSString *)secret
+{
+ NSData *secretData = [secret dataUsingEncoding:NSUTF8StringEncoding];
+ NSData *clearTextData = [text dataUsingEncoding:NSUTF8StringEncoding];
+ unsigned char result[20];
+ hmac_sha1((unsigned char *)[clearTextData bytes], [clearTextData length], (unsigned char *)[secretData bytes], [secretData length], result);
+
+ //Base64 Encoding
+
+ char base64Result[32];
+ size_t theResultLength = 32;
+ Base64EncodeData(result, 20, base64Result, &theResultLength);
+ NSData *theData = [NSData dataWithBytes:base64Result length:theResultLength];
+
+ NSString *base64EncodedResult = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];
+ return [base64EncodedResult autorelease];
+}
+
+@end
--- /dev/null
+//
+// OAPlaintextSignatureProvider.h
+// OAuthConsumer
+//
+// Created by Jon Crosby on 10/19/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import <Foundation/Foundation.h>
+#import "OASignatureProviding.h"
+
+@interface OAPlaintextSignatureProvider : NSObject <OASignatureProviding>
+@end
--- /dev/null
+//
+// OAPlaintextSignatureProvider.m
+// OAuthConsumer
+//
+// Created by Jon Crosby on 10/19/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import "OAPlaintextSignatureProvider.h"
+#import "NSString+URLEncoding.h"
+
+
+@implementation OAPlaintextSignatureProvider
+
+- (NSString *)name
+{
+ return @"PLAINTEXT";
+}
+
+- (NSString *)signClearText:(NSString *)text withSecret:(NSString *)secret
+{
+ return secret;
+}
+
+@end
--- /dev/null
+//
+// OASignatureProviding.h
+//
+// Created by Jon Crosby on 10/19/07.
+// Copyright 2007 Kaboomerang LLC. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#import <Foundation/Foundation.h>
+
+
+@protocol OASignatureProviding <NSObject>
+
+- (NSString *)name;
+- (NSString *)signClearText:(NSString *)text withSecret:(NSString *)secret;
+
+@end
--- /dev/null
+Getting Started
+===============
+1. git clone git://github.com/quanganhdo/atutor-social-iphone.git ATutor
+2. cd ATutor
+3. git submodule update --init
+4. open ATutor.xcodeproj
+5. Build and Go!
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>StringsTable</key>
+ <string>Root</string>
+ <key>Title</key>
+ <string>ATutor</string>
+ <key>PreferenceSpecifiers</key>
+ <array>
+ <dict>
+ <key>Type</key>
+ <string>PSGroupSpecifier</string>
+ <key>Title</key>
+ <string>ATutor URL</string>
+ </dict>
+ <dict>
+ <key>Type</key>
+ <string>PSTextFieldSpecifier</string>
+ <key>Title</key>
+ <string>URL</string>
+ <key>Key</key>
+ <string>atutorURL</string>
+ <key>DefaultValue</key>
+ <string>http://www.example.com/atutor/docs</string>
+ <key>IsSecure</key>
+ <false/>
+ <key>KeyboardType</key>
+ <string>URL</string>
+ <key>AutocapitalizationType</key>
+ <string>None</string>
+ <key>AutocorrectionType</key>
+ <string>No</string>
+ </dict>
+ <dict>
+ <key>Type</key>
+ <string>PSGroupSpecifier</string>
+ <key>Title</key>
+ <string>Shindig URL</string>
+ </dict>
+ <dict>
+ <key>Type</key>
+ <string>PSTextFieldSpecifier</string>
+ <key>Title</key>
+ <string>URL</string>
+ <key>Key</key>
+ <string>shindigURL</string>
+ <key>DefaultValue</key>
+ <string>http://www.example.com/shindig/php</string>
+ <key>IsSecure</key>
+ <false/>
+ <key>KeyboardType</key>
+ <string>URL</string>
+ <key>AutocapitalizationType</key>
+ <string>None</string>
+ <key>AutocorrectionType</key>
+ <string>No</string>
+ </dict>
+ </array>
+</dict>
+</plist>
--- /dev/null
+//
+// CDataScanner.h
+// TouchJSON
+//
+// Created by Jonathan Wight on 04/16/08.
+// Copyright 2008 toxicsoftware.com. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+// NSScanner
+
+@interface CDataScanner : NSObject {
+ NSData *data;
+
+ u_int8_t *start;
+ u_int8_t *end;
+ u_int8_t *current;
+ NSUInteger length;
+
+ NSCharacterSet *doubleCharacters;
+}
+
+@property (readwrite, retain) NSData *data;
+@property (readwrite, assign) NSInteger scanLocation;
+@property (readonly, assign) BOOL isAtEnd;
+
++ (id)scannerWithData:(NSData *)inData;
+
+- (unichar)currentCharacter;
+- (unichar)scanCharacter;
+- (BOOL)scanCharacter:(unichar)inCharacter;
+
+- (BOOL)scanUTF8String:(const char *)inString intoString:(NSString **)outValue;
+- (BOOL)scanString:(NSString *)inString intoString:(NSString **)outValue;
+- (BOOL)scanCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue; // inSet must only contain 7-bit ASCII characters
+
+- (BOOL)scanUpToString:(NSString *)string intoString:(NSString **)outValue;
+- (BOOL)scanUpToCharactersFromSet:(NSCharacterSet *)set intoString:(NSString **)outValue; // inSet must only contain 7-bit ASCII characters
+
+- (BOOL)scanNumber:(NSNumber **)outValue;
+
+@end
--- /dev/null
+//
+// CDataScanner.m
+// TouchJSON
+//
+// Created by Jonathan Wight on 04/16/08.
+// Copyright 2008 toxicsoftware.com. All rights reserved.
+//
+
+#import "CDataScanner.h"
+
+#import "CDataScanner_Extensions.h"
+
+@interface CDataScanner ()
+@property (readwrite, retain) NSCharacterSet *doubleCharacters;
+@end
+
+#pragma mark -
+
+inline static unichar CharacterAtPointer(void *start, void *end)
+{
+
+ const u_int8_t theByte = *(u_int8_t *)start;
+if (theByte & 0x80)
+ {
+ // TODO -- UNICODE!!!!
+ }
+const unichar theCharacter = theByte;
+return(theCharacter);
+}
+
+@implementation CDataScanner
+
+@dynamic data;
+@dynamic scanLocation;
+@dynamic isAtEnd;
+@synthesize doubleCharacters;
+
++ (id)scannerWithData:(NSData *)inData
+{
+CDataScanner *theScanner = [[[self alloc] init] autorelease];
+theScanner.data = inData;
+return(theScanner);
+}
+
+- (id)init
+{
+if ((self = [super init]) != nil)
+ {
+ self.doubleCharacters = [NSCharacterSet characterSetWithCharactersInString:@"0123456789eE-."];
+ }
+return(self);
+}
+
+- (void)dealloc
+{
+self.data = NULL;
+self.doubleCharacters = NULL;
+//
+[super dealloc];
+}
+
+- (NSInteger)scanLocation
+{
+return current - start;
+}
+
+- (NSData *)data
+{
+return(data);
+}
+
+- (void)setData:(NSData *)inData
+{
+if (data != inData)
+ {
+ if (data)
+ {
+ [data autorelease];
+ data = NULL;
+ }
+
+ if (inData)
+ {
+ data = [inData retain];
+ //
+ start = (u_int8_t *)data.bytes;
+ end = start + data.length;
+ current = start;
+ length = data.length;
+ }
+ }
+}
+
+- (void)setScanLocation:(NSInteger)inScanLocation
+{
+current = start + inScanLocation;
+}
+
+- (BOOL)isAtEnd
+{
+return(self.scanLocation >= length);
+}
+
+- (unichar)currentCharacter
+{
+return(CharacterAtPointer(current, end));
+}
+
+- (unichar)scanCharacter
+{
+const unichar theCharacter = CharacterAtPointer(current++, end);
+return(theCharacter);
+}
+
+- (BOOL)scanCharacter:(unichar)inCharacter
+{
+unichar theCharacter = CharacterAtPointer(current, end);
+if (theCharacter == inCharacter)
+ {
+ ++current;
+ return(YES);
+ }
+else
+ return(NO);
+}
+
+- (BOOL)scanUTF8String:(const char *)inString intoString:(NSString **)outValue;
+{
+const size_t theLength = strlen(inString);
+if (end - current < theLength)
+ return(NO);
+if (strncmp((char *)current, inString, theLength) == 0)
+ {
+ current += theLength;
+ if (outValue)
+ *outValue = [NSString stringWithUTF8String:inString];
+ return(YES);
+ }
+return(NO);
+}
+
+- (BOOL)scanString:(NSString *)inString intoString:(NSString **)outValue
+{
+if (end - current < inString.length)
+ return(NO);
+if (strncmp((char *)current, [inString UTF8String], inString.length) == 0)
+ {
+ current += inString.length;
+ if (outValue)
+ *outValue = inString;
+ return(YES);
+ }
+return(NO);
+}
+
+- (BOOL)scanCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue
+{
+u_int8_t *P;
+for (P = current; P < end && [inSet characterIsMember:*P] == YES; ++P)
+ ;
+
+if (P == current)
+ {
+ return(NO);
+ }
+
+if (outValue)
+ {
+ *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease];
+ }
+
+current = P;
+
+return(YES);
+}
+
+- (BOOL)scanUpToString:(NSString *)inString intoString:(NSString **)outValue
+{
+const char *theToken = [inString UTF8String];
+const char *theResult = strnstr((char *)current, theToken, end - current);
+if (theResult == NULL)
+ {
+ return(NO);
+ }
+
+if (outValue)
+ {
+ *outValue = [[[NSString alloc] initWithBytes:current length:theResult - (char *)current encoding:NSUTF8StringEncoding] autorelease];
+ }
+
+current = (u_int8_t *)theResult;
+
+return(YES);
+}
+
+- (BOOL)scanUpToCharactersFromSet:(NSCharacterSet *)inSet intoString:(NSString **)outValue
+{
+u_int8_t *P;
+for (P = current; P < end && [inSet characterIsMember:*P] == NO; ++P)
+ ;
+
+if (P == current)
+ {
+ return(NO);
+ }
+
+if (outValue)
+ {
+ *outValue = [[[NSString alloc] initWithBytes:current length:P - current encoding:NSUTF8StringEncoding] autorelease];
+ }
+
+current = P;
+
+return(YES);
+}
+
+- (BOOL)scanNumber:(NSNumber **)outValue
+{
+// Replace all of this with a strtod call
+NSString *theString = NULL;
+if ([self scanCharactersFromSet:doubleCharacters intoString:&theString])
+ {
+ if (outValue)
+ *outValue = [NSNumber numberWithDouble:[theString doubleValue]]; // TODO dont use doubleValue
+ return(YES);
+ }
+return(NO);
+}
+
+@end
--- /dev/null
+//
+// CDataScanner_Extensions.h
+// TouchJSON
+//
+// Created by Jonathan Wight on 12/08/2005.
+// Copyright 2005 Toxic Software. All rights reserved.
+//
+
+#import "CDataScanner.h"
+
+@interface CDataScanner (CDataScanner_Extensions)
+
+- (BOOL)scanCStyleComment:(NSString **)outComment;
+- (BOOL)scanCPlusPlusStyleComment:(NSString **)outComment;
+
+@end
--- /dev/null
+//
+// NSScanner_Extensions.m
+// TouchJSON
+//
+// Created by Jonathan Wight on 12/08/2005.
+// Copyright 2005 Toxic Software. All rights reserved.
+//
+
+#import "CDataScanner_Extensions.h"
+
+#import "NSCharacterSet_Extensions.h"
+
+@implementation CDataScanner (CDataScanner_Extensions)
+
+- (BOOL)scanCStyleComment:(NSString **)outComment
+{
+if ([self scanString:@"/*" intoString:NULL] == YES)
+ {
+ NSString *theComment = NULL;
+ if ([self scanUpToString:@"*/" intoString:&theComment] == NO)
+ [NSException raise:NSGenericException format:@"Started to scan a C style comment but it wasn't terminated."];
+
+ if ([theComment rangeOfString:@"/*"].location != NSNotFound)
+ [NSException raise:NSGenericException format:@"C style comments should not be nested."];
+
+ if ([self scanString:@"*/" intoString:NULL] == NO)
+ [NSException raise:NSGenericException format:@"C style comment did not end correctly."];
+
+ if (outComment != NULL)
+ *outComment = theComment;
+
+ return(YES);
+ }
+else
+ {
+ return(NO);
+ }
+}
+
+- (BOOL)scanCPlusPlusStyleComment:(NSString **)outComment
+{
+if ([self scanString:@"//" intoString:NULL] == YES)
+ {
+ NSString *theComment = NULL;
+ [self scanUpToCharactersFromSet:[NSCharacterSet linebreaksCharacterSet] intoString:&theComment];
+ [self scanCharactersFromSet:[NSCharacterSet linebreaksCharacterSet] intoString:NULL];
+
+ if (outComment != NULL)
+ *outComment = theComment;
+
+ return(YES);
+ }
+else
+ {
+ return(NO);
+ }
+}
+
+@end
--- /dev/null
+//
+// NSCharacterSet_Extensions.h
+// TouchJSON
+//
+// Created by Jonathan Wight on 12/08/2005.
+// Copyright (c) 2005 Toxic Software. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface NSCharacterSet (NSCharacterSet_Extensions)
+
++ (NSCharacterSet *)linebreaksCharacterSet;
+
+@end
--- /dev/null
+//
+// NSCharacterSet_Extensions.m
+// TouchJSON
+//
+// Created by Jonathan Wight on 12/08/2005.
+// Copyright (c) 2005 Toxic Software. All rights reserved.
+//
+
+#import "NSCharacterSet_Extensions.h"
+
+@implementation NSCharacterSet (NSCharacterSet_Extensions)
+
+#define LF 0x000a // Line Feed
+#define FF 0x000c // Form Feed
+#define CR 0x000d // Carriage Return
+#define NEL 0x0085 // Next Line
+#define LS 0x2028 // Line Separator
+#define PS 0x2029 // Paragraph Separator
+
++ (NSCharacterSet *)linebreaksCharacterSet
+{
+unichar theCharacters[] = { LF, FF, CR, NEL, LS, PS, };
+
+return([NSCharacterSet characterSetWithCharactersInString:[NSString stringWithCharacters:theCharacters length:sizeof(theCharacters) / sizeof(*theCharacters)]]);
+}
+
+@end
--- /dev/null
+//
+// NSDictionary_JSONExtensions.h
+// TouchJSON
+//
+// Created by Jonathan Wight on 04/17/08.
+// Copyright 2008 toxicsoftware.com. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface NSDictionary (NSDictionary_JSONExtensions)
+
++ (id)dictionaryWithJSONData:(NSData *)inData error:(NSError **)outError;
+
+@end
--- /dev/null
+//
+// NSDictionary_JSONExtensions.m
+// TouchJSON
+//
+// Created by Jonathan Wight on 04/17/08.
+// Copyright 2008 toxicsoftware.com. All rights reserved.
+//
+
+#import "NSDictionary_JSONExtensions.h"
+
+#import "CJSONDeserializer.h"
+
+@implementation NSDictionary (NSDictionary_JSONExtensions)
+
++ (id)dictionaryWithJSONData:(NSData *)inData error:(NSError **)outError
+{
+return([[CJSONDeserializer deserializer] deserialize:inData error:outError]);
+}
+
+@end
--- /dev/null
+//
+// CJSONDeserializer.h
+// TouchJSON
+//
+// Created by Jonathan Wight on 12/15/2005.
+// Copyright 2005 Toxic Software. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface CJSONDeserializer : NSObject {
+
+}
+
++ (id)deserializer;
+
+- (id)deserialize:(NSData *)inData error:(NSError **)outError;
+
+@end
--- /dev/null
+//
+// CJSONDeserializer.m
+// TouchJSON
+//
+// Created by Jonathan Wight on 12/15/2005.
+// Copyright 2005 Toxic Software. All rights reserved.
+//
+
+#import "CJSONDeserializer.h"
+
+#import "CJSONScanner.h"
+#import "CDataScanner.h"
+
+@implementation CJSONDeserializer
+
++ (id)deserializer
+{
+return([[[self alloc] init] autorelease]);
+}
+
+- (id)deserialize:(NSData *)inData error:(NSError **)outError
+{
+CJSONScanner *theScanner = [CJSONScanner scannerWithData:inData];
+id theObject = NULL;
+if ([theScanner scanJSONObject:&theObject error:outError] == YES)
+ return(theObject);
+else
+ return(NULL);
+}
+
+@end
--- /dev/null
+//
+// CJSONScanner.h
+// TouchJSON
+//
+// Created by Jonathan Wight on 12/07/2005.
+// Copyright 2005 Toxic Software. All rights reserved.
+//
+
+#import "CDataScanner.h"
+
+@interface CJSONScanner : CDataScanner {
+ BOOL scanComments;
+ NSCharacterSet *notQuoteCharacters;
+ NSCharacterSet *whitespaceCharacterSet;
+}
+
+@property (readwrite, assign) BOOL scanComments;
+
+- (BOOL)scanJSONObject:(id *)outObject error:(NSError **)outError;
+- (BOOL)scanJSONDictionary:(NSDictionary **)outDictionary error:(NSError **)outError;
+- (BOOL)scanJSONArray:(NSArray **)outArray error:(NSError **)outError;
+- (BOOL)scanJSONStringConstant:(NSString **)outStringConstant error:(NSError **)outError;
+- (BOOL)scanJSONNumberConstant:(NSNumber **)outNumberConstant error:(NSError **)outError;
+- (void)skipJSONWhitespace;
+
+@end
--- /dev/null
+//
+// CJSONScanner.m
+// TouchJSON
+//
+// Created by Jonathan Wight on 12/07/2005.
+// Copyright 2005 Toxic Software. All rights reserved.
+//
+
+#import "CJSONScanner.h"
+
+#import "NSCharacterSet_Extensions.h"
+#import "CDataScanner_Extensions.h"
+
+inline static int HexToInt(char inCharacter)
+{
+int theValues[] = { 0x0 /* 48 '0' */, 0x1 /* 49 '1' */, 0x2 /* 50 '2' */, 0x3 /* 51 '3' */, 0x4 /* 52 '4' */, 0x5 /* 53 '5' */, 0x6 /* 54 '6' */, 0x7 /* 55 '7' */, 0x8 /* 56 '8' */, 0x9 /* 57 '9' */, -1 /* 58 ':' */, -1 /* 59 ';' */, -1 /* 60 '<' */, -1 /* 61 '=' */, -1 /* 62 '>' */, -1 /* 63 '?' */, -1 /* 64 '@' */, 0xa /* 65 'A' */, 0xb /* 66 'B' */, 0xc /* 67 'C' */, 0xd /* 68 'D' */, 0xe /* 69 'E' */, 0xf /* 70 'F' */, -1 /* 71 'G' */, -1 /* 72 'H' */, -1 /* 73 'I' */, -1 /* 74 'J' */, -1 /* 75 'K' */, -1 /* 76 'L' */, -1 /* 77 'M' */, -1 /* 78 'N' */, -1 /* 79 'O' */, -1 /* 80 'P' */, -1 /* 81 'Q' */, -1 /* 82 'R' */, -1 /* 83 'S' */, -1 /* 84 'T' */, -1 /* 85 'U' */, -1 /* 86 'V' */, -1 /* 87 'W' */, -1 /* 88 'X' */, -1 /* 89 'Y' */, -1 /* 90 'Z' */, -1 /* 91 '[' */, -1 /* 92 '\' */, -1 /* 93 ']' */, -1 /* 94 '^' */, -1 /* 95 '_' */, -1 /* 96 '`' */, 0xa /* 97 'a' */, 0xb /* 98 'b' */, 0xc /* 99 'c' */, 0xd /* 100 'd' */, 0xe /* 101 'e' */, 0xf /* 102 'f' */, };
+if (inCharacter >= '0' && inCharacter <= 'f')
+ return(theValues[inCharacter - '0']);
+else
+ return(-1);
+}
+
+@interface CJSONScanner ()
+@property (readwrite, retain) NSCharacterSet *notQuoteCharacters;
+@property (readwrite, retain) NSCharacterSet *whitespaceCharacterSet;
+@end
+
+#pragma mark -
+
+@implementation CJSONScanner
+
+@synthesize scanComments;
+@synthesize notQuoteCharacters;
+@synthesize whitespaceCharacterSet;
+
+- (id)init
+{
+if ((self = [super init]) != nil)
+ {
+ self.notQuoteCharacters = [[NSCharacterSet characterSetWithCharactersInString:@"\\\""] invertedSet];
+ self.whitespaceCharacterSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
+ }
+return(self);
+}
+
+- (void)dealloc
+{
+self.notQuoteCharacters = NULL;
+self.whitespaceCharacterSet = NULL;
+//
+[super dealloc];
+}
+
+#pragma mark -
+
+- (void)setData:(NSData *)inData
+{
+NSData *theData = inData;
+if (theData && theData.length >= 4)
+ {
+ // This code is lame, but it works. Because the first character of any JSON string will always be a control character we can work out the Unicode encoding by the bit pattern. See section 3 of http://www.ietf.org/rfc/rfc4627.txt
+ const char *theChars = theData.bytes;
+ NSStringEncoding theEncoding = NSUTF8StringEncoding;
+ if (theChars[0] != 0 && theChars[1] == 0)
+ {
+ if (theChars[2] != 0 && theChars[3] == 0)
+ theEncoding = NSUTF16LittleEndianStringEncoding;
+ else if (theChars[2] == 0 && theChars[3] == 0)
+ theEncoding = NSUTF32LittleEndianStringEncoding;
+ }
+ else if (theChars[0] == 0 && theChars[2] == 0 && theChars[3] != 0)
+ {
+ if (theChars[1] == 0)
+ theEncoding = NSUTF32BigEndianStringEncoding;
+ else if (theChars[1] != 0)
+ theEncoding = NSUTF16BigEndianStringEncoding;
+ }
+
+ if (theEncoding != NSUTF8StringEncoding)
+ {
+ NSString *theString = [[[NSString alloc] initWithData:theData encoding:theEncoding] autorelease];
+ theData = [theString dataUsingEncoding:NSUTF8StringEncoding];
+ }
+ }
+[super setData:theData];
+}
+
+#pragma mark -
+
+- (BOOL)scanJSONObject:(id *)outObject error:(NSError **)outError
+{
+[self skipJSONWhitespace];
+
+id theObject = NULL;
+
+const unichar C = [self currentCharacter];
+switch (C)
+ {
+ case 't':
+ if ([self scanUTF8String:"true" intoString:NULL])
+ {
+ theObject = [NSNumber numberWithBool:YES];
+ }
+ break;
+ case 'f':
+ if ([self scanUTF8String:"false" intoString:NULL])
+ {
+ theObject = [NSNumber numberWithBool:NO];
+ }
+ break;
+ case 'n':
+ if ([self scanUTF8String:"null" intoString:NULL])
+ {
+ theObject = [NSNull null];
+ }
+ break;
+ case '\"':
+ case '\'':
+ [self scanJSONStringConstant:&theObject error:outError];
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '-':
+ [self scanJSONNumberConstant:&theObject error:outError];
+ break;
+ case '{':
+ [self scanJSONDictionary:&theObject error:outError];
+ break;
+ case '[':
+ [self scanJSONArray:&theObject error:outError];
+ break;
+ default:
+
+ break;
+ }
+
+if (outObject != NULL)
+ *outObject = theObject;
+return(YES);
+}
+
+- (BOOL)scanJSONDictionary:(NSDictionary **)outDictionary error:(NSError **)outError
+{
+unsigned theScanLocation = [self scanLocation];
+
+//[self skipJSONWhitespace];
+
+if ([self scanCharacter:'{'] == NO)
+ {
+ if (outError)
+ {
+ *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-1 userInfo:NULL];
+ }
+ return(NO);
+ }
+
+NSMutableDictionary *theDictionary = [NSMutableDictionary dictionary];
+
+while ([self scanCharacter:'}'] == NO)
+ {
+ NSString *theKey = NULL;
+ if ([self scanJSONStringConstant:&theKey error:outError] == NO)
+ {
+ [self setScanLocation:theScanLocation];
+ if (outError)
+ {
+ *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-2 userInfo:NULL];
+ }
+ return(NO);
+ }
+
+ [self skipJSONWhitespace];
+
+ if ([self scanCharacter:':'] == NO)
+ {
+ [self setScanLocation:theScanLocation];
+ if (outError)
+ {
+ *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-3 userInfo:NULL];
+ }
+ return(NO);
+ }
+
+ id theValue = NULL;
+ if ([self scanJSONObject:&theValue error:outError] == NO)
+ {
+ [self setScanLocation:theScanLocation];
+ if (outError)
+ {
+ *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-4 userInfo:NULL];
+ }
+ return(NO);
+ }
+
+ [theDictionary setValue:theValue forKey:theKey];
+
+ [self skipJSONWhitespace];
+ if ([self scanCharacter:','] == NO)
+ {
+ if ([self currentCharacter] != '}')
+ {
+ [self setScanLocation:theScanLocation];
+ if (outError)
+ {
+ *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-5 userInfo:NULL];
+ }
+ return(NO);
+ }
+ break;
+ }
+ else
+ {
+ [self skipJSONWhitespace];
+ if ([self currentCharacter] == '}')
+ break;
+ }
+ }
+
+if ([self scanCharacter:'}'] == NO)
+ {
+ [self setScanLocation:theScanLocation];
+ if (outError)
+ {
+ *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-6 userInfo:NULL];
+ }
+ return(NO);
+ }
+
+if (outDictionary != NULL)
+ *outDictionary = theDictionary;
+return(YES);
+}
+
+- (BOOL)scanJSONArray:(NSArray **)outArray error:(NSError **)outError
+{
+unsigned theScanLocation = [self scanLocation];
+
+//[self skipJSONWhitespace];
+if ([self scanCharacter:'['] == NO)
+ {
+ if (outError)
+ {
+ *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-7 userInfo:NULL];
+ }
+ return(NO);
+ }
+
+NSMutableArray *theArray = [NSMutableArray array];
+
+[self skipJSONWhitespace];
+while ([self currentCharacter] != ']')
+ {
+ NSString *theValue = NULL;
+ if ([self scanJSONObject:&theValue error:outError] == NO)
+ {
+ [self setScanLocation:theScanLocation];
+ if (outError)
+ {
+ *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-8 userInfo:NULL];
+ }
+ return(NO);
+ }
+
+ [theArray addObject:theValue];
+
+ [self skipJSONWhitespace];
+ if ([self scanCharacter:','] == NO)
+ {
+ [self skipJSONWhitespace];
+ if ([self currentCharacter] != ']')
+ {
+ [self setScanLocation:theScanLocation];
+ if (outError)
+ {
+ *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-9 userInfo:NULL];
+ }
+ return(NO);
+ }
+
+ break;
+ }
+ [self skipJSONWhitespace];
+ }
+
+[self skipJSONWhitespace];
+
+if ([self scanCharacter:']'] == NO)
+ {
+ [self setScanLocation:theScanLocation];
+ if (outError)
+ {
+ *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-10 userInfo:NULL];
+ }
+ return(NO);
+ }
+
+if (outArray != NULL)
+ *outArray = theArray;
+return(YES);
+}
+
+- (BOOL)scanJSONStringConstant:(NSString **)outStringConstant error:(NSError **)outError
+{
+unsigned theScanLocation = [self scanLocation];
+
+[self skipJSONWhitespace]; // TODO - i want to remove this method. But breaks unit tests.
+
+NSMutableString *theString = [NSMutableString string];
+
+if ([self scanCharacter:'"'] == NO)
+ {
+ [self setScanLocation:theScanLocation];
+ if (outError)
+ {
+ *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-11 userInfo:NULL];
+ }
+ return(NO);
+ }
+
+while ([self scanCharacter:'"'] == NO)
+ {
+ NSString *theStringChunk = NULL;
+ if ([self scanCharactersFromSet:notQuoteCharacters intoString:&theStringChunk])
+ {
+ [theString appendString:theStringChunk];
+ }
+
+ if ([self scanCharacter:'\\'] == YES)
+ {
+ unichar theCharacter = [self scanCharacter];
+ switch (theCharacter)
+ {
+ case '"':
+ case '\\':
+ case '/':
+ break;
+ case 'b':
+ theCharacter = '\b';
+ break;
+ case 'f':
+ theCharacter = '\f';
+ break;
+ case 'n':
+ theCharacter = '\n';
+ break;
+ case 'r':
+ theCharacter = '\r';
+ break;
+ case 't':
+ theCharacter = '\t';
+ break;
+ case 'u':
+ {
+ theCharacter = 0;
+
+ int theShift;
+ for (theShift = 12; theShift >= 0; theShift -= 4)
+ {
+ const int theDigit = HexToInt([self scanCharacter]);
+ if (theDigit == -1)
+ {
+ [self setScanLocation:theScanLocation];
+ if (outError)
+ {
+ *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-12 userInfo:NULL];
+ }
+ return(NO);
+ }
+ theCharacter |= (theDigit << theShift);
+ }
+ }
+ break;
+ default:
+ {
+ [self setScanLocation:theScanLocation];
+ if (outError)
+ {
+ *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-13 userInfo:NULL];
+ }
+ return(NO);
+ }
+ break;
+ }
+ CFStringAppendCharacters((CFMutableStringRef)theString, &theCharacter, 1);
+// [theString appendFormat:@"%C", theCharacter];
+ }
+ }
+
+if (outStringConstant != NULL)
+ *outStringConstant = theString;
+
+return(YES);
+}
+
+- (BOOL)scanJSONNumberConstant:(NSNumber **)outNumberConstant error:(NSError **)outError
+{
+//[self skipJSONWhitespace];
+
+NSNumber *theNumber = NULL;
+if ([self scanNumber:&theNumber] == YES)
+ {
+ if (outNumberConstant != NULL)
+ *outNumberConstant = theNumber;
+ return(YES);
+ }
+else
+ {
+ if (outError)
+ {
+ *outError = [NSError errorWithDomain:@"CJSONScannerErrorDomain" code:-14 userInfo:NULL];
+ }
+ return(NO);
+ }
+}
+
+- (void)skipJSONWhitespace
+{
+[self scanCharactersFromSet:whitespaceCharacterSet intoString:NULL];
+if (scanComments)
+ {
+ [self scanCStyleComment:NULL];
+ [self scanCPlusPlusStyleComment:NULL];
+ [self scanCharactersFromSet:whitespaceCharacterSet intoString:NULL];
+ }
+}
+
+@end
--- /dev/null
+//
+// CJSONSerializer.h
+// TouchJSON
+//
+// Created by Jonathan Wight on 12/07/2005.
+// Copyright 2005 Toxic Software. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface CJSONSerializer : NSObject {
+}
+
++ (id)serializer;
+
+- (NSString *)serializeObject:(id)inObject;
+
+- (NSString *)serializeNull:(NSNull *)inNull;
+- (NSString *)serializeNumber:(NSNumber *)inNumber;
+- (NSString *)serializeString:(NSString *)inString;
+- (NSString *)serializeArray:(NSArray *)inArray;
+- (NSString *)serializeDictionary:(NSDictionary *)inDictionary;
+
+@end
--- /dev/null
+//
+// CJSONSerializer.m
+// TouchJSON
+//
+// Created by Jonathan Wight on 12/07/2005.
+// Copyright 2005 Toxic Software. All rights reserved.
+//
+
+#import "CJSONSerializer.h"
+
+@implementation CJSONSerializer
+
++ (id)serializer
+{
+return([[[self alloc] init] autorelease]);
+}
+
+- (NSString *)serializeObject:(id)inObject;
+{
+NSString *theResult = @"";
+
+if ([inObject isKindOfClass:[NSNull class]])
+ {
+ theResult = [self serializeNull:inObject];
+ }
+else if ([inObject isKindOfClass:[NSNumber class]])
+ {
+ theResult = [self serializeNumber:inObject];
+ }
+else if ([inObject isKindOfClass:[NSString class]])
+ {
+ theResult = [self serializeString:inObject];
+ }
+else if ([inObject isKindOfClass:[NSArray class]])
+ {
+ theResult = [self serializeArray:inObject];
+ }
+else if ([inObject isKindOfClass:[NSDictionary class]])
+ {
+ theResult = [self serializeDictionary:inObject];
+ }
+else if ([inObject isKindOfClass:[NSData class]])
+ {
+ NSString *theString = [[[NSString alloc] initWithData:inObject encoding:NSUTF8StringEncoding] autorelease];
+ theResult = [self serializeString:theString];
+ }
+else
+ {
+ [NSException raise:NSGenericException format:@"Cannot serialize data of type '%@'", NSStringFromClass([inObject class])];
+ }
+if (theResult == NULL)
+ [NSException raise:NSGenericException format:@"Could not serialize object '%@'", inObject];
+return(theResult);
+}
+
+- (NSString *)serializeNull:(NSNull *)inNull
+{
+#pragma unused (inNull)
+return(@"null");
+}
+
+- (NSString *)serializeNumber:(NSNumber *)inNumber
+{
+NSString *theResult = NULL;
+switch (CFNumberGetType((CFNumberRef)inNumber))
+ {
+ case kCFNumberCharType:
+ {
+ int theValue = [inNumber intValue];
+ if (theValue == 0)
+ theResult = @"false";
+ else if (theValue == 1)
+ theResult = @"true";
+ else
+ theResult = [inNumber stringValue];
+ }
+ break;
+ case kCFNumberSInt8Type:
+ case kCFNumberSInt16Type:
+ case kCFNumberSInt32Type:
+ case kCFNumberSInt64Type:
+ case kCFNumberFloat32Type:
+ case kCFNumberFloat64Type:
+ case kCFNumberShortType:
+ case kCFNumberIntType:
+ case kCFNumberLongType:
+ case kCFNumberLongLongType:
+ case kCFNumberFloatType:
+ case kCFNumberDoubleType:
+ case kCFNumberCFIndexType:
+ default:
+ theResult = [inNumber stringValue];
+ break;
+ }
+return(theResult);
+}
+
+- (NSString *)serializeString:(NSString *)inString
+{
+NSMutableString *theMutableCopy = [[inString mutableCopy] autorelease];
+[theMutableCopy replaceOccurrencesOfString:@"\\" withString:@"\\\\" options:0 range:NSMakeRange(0, [theMutableCopy length])];
+[theMutableCopy replaceOccurrencesOfString:@"\"" withString:@"\\\"" options:0 range:NSMakeRange(0, [theMutableCopy length])];
+[theMutableCopy replaceOccurrencesOfString:@"/" withString:@"\\/" options:0 range:NSMakeRange(0, [theMutableCopy length])];
+[theMutableCopy replaceOccurrencesOfString:@"\b" withString:@"\\b" options:0 range:NSMakeRange(0, [theMutableCopy length])];
+[theMutableCopy replaceOccurrencesOfString:@"\f" withString:@"\\f" options:0 range:NSMakeRange(0, [theMutableCopy length])];
+[theMutableCopy replaceOccurrencesOfString:@"\n" withString:@"\\n" options:0 range:NSMakeRange(0, [theMutableCopy length])];
+[theMutableCopy replaceOccurrencesOfString:@"\n" withString:@"\\n" options:0 range:NSMakeRange(0, [theMutableCopy length])];
+[theMutableCopy replaceOccurrencesOfString:@"\t" withString:@"\\t" options:0 range:NSMakeRange(0, [theMutableCopy length])];
+/*
+ case 'u':
+ {
+ theCharacter = 0;
+
+ int theShift;
+ for (theShift = 12; theShift >= 0; theShift -= 4)
+ {
+ int theDigit = HexToInt([self scanCharacter]);
+ if (theDigit == -1)
+ {
+ [self setScanLocation:theScanLocation];
+ return(NO);
+ }
+ theCharacter |= (theDigit << theShift);
+ }
+ }
+*/
+return([NSString stringWithFormat:@"\"%@\"", theMutableCopy]);
+}
+
+- (NSString *)serializeArray:(NSArray *)inArray
+{
+NSMutableString *theString = [NSMutableString string];
+
+NSEnumerator *theEnumerator = [inArray objectEnumerator];
+id theValue = NULL;
+while ((theValue = [theEnumerator nextObject]) != NULL)
+ {
+ [theString appendString:[self serializeObject:theValue]];
+ if (theValue != [inArray lastObject])
+ [theString appendString:@","];
+ }
+return([NSString stringWithFormat:@"[%@]", theString]);
+}
+
+- (NSString *)serializeDictionary:(NSDictionary *)inDictionary
+{
+NSMutableString *theString = [NSMutableString string];
+
+NSArray *theKeys = [inDictionary allKeys];
+NSEnumerator *theEnumerator = [theKeys objectEnumerator];
+NSString *theKey = NULL;
+while ((theKey = [theEnumerator nextObject]) != NULL)
+ {
+ id theValue = [inDictionary valueForKey:theKey];
+
+ [theString appendFormat:@"%@:%@", [self serializeString:theKey], [self serializeObject:theValue]];
+ if (theKey != [theKeys lastObject])
+ [theString appendString:@","];
+ }
+return([NSString stringWithFormat:@"{%@}", theString]);
+}
+
+@end
--- /dev/null
+//
+// main.m
+// ATutor
+//
+// Created by Quang Anh Do on 25/05/2010.
+// Copyright Quang Anh Do 2010. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+int main(int argc, char *argv[]) {
+
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+ int retVal = UIApplicationMain(argc, argv, nil, @"ATutorAppDelegate");
+ [pool release];
+ return retVal;
+}