From e69989cb08ddc7c1bbcde068676384fddd52bcca Mon Sep 17 00:00:00 2001 From: Rodrigo Sieiro Date: Wed, 8 Feb 2012 00:40:18 -0200 Subject: [PATCH] New Instapaper Demo This demo shows how to use RSOAuthEngine with xAuth to add a bookmark to Instapaper. --- InstapaperDemo.xcodeproj/project.pbxproj | 430 +++++++++++ .../contents.xcworkspacedata | 7 + InstapaperDemo/AppDelegate.h | 35 + InstapaperDemo/AppDelegate.m | 82 +++ InstapaperDemo/AuthViewController.h | 46 ++ InstapaperDemo/AuthViewController.m | 87 +++ .../Instapaper/RSInstapaperEngine.h | 59 ++ .../Instapaper/RSInstapaperEngine.m | 278 +++++++ InstapaperDemo/InstapaperDemo-Info.plist | 54 ++ InstapaperDemo/InstapaperDemo-Prefix.pch | 15 + InstapaperDemo/ViewController.h | 50 ++ InstapaperDemo/ViewController.m | 261 +++++++ .../en.lproj/AuthViewController.xib | 400 ++++++++++ InstapaperDemo/en.lproj/InfoPlist.strings | 2 + InstapaperDemo/en.lproj/ViewController.xib | 692 ++++++++++++++++++ InstapaperDemo/main.m | 35 + 16 files changed, 2533 insertions(+) create mode 100644 InstapaperDemo.xcodeproj/project.pbxproj create mode 100644 InstapaperDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 InstapaperDemo/AppDelegate.h create mode 100644 InstapaperDemo/AppDelegate.m create mode 100644 InstapaperDemo/AuthViewController.h create mode 100644 InstapaperDemo/AuthViewController.m create mode 100644 InstapaperDemo/Instapaper/RSInstapaperEngine.h create mode 100644 InstapaperDemo/Instapaper/RSInstapaperEngine.m create mode 100644 InstapaperDemo/InstapaperDemo-Info.plist create mode 100644 InstapaperDemo/InstapaperDemo-Prefix.pch create mode 100644 InstapaperDemo/ViewController.h create mode 100644 InstapaperDemo/ViewController.m create mode 100644 InstapaperDemo/en.lproj/AuthViewController.xib create mode 100644 InstapaperDemo/en.lproj/InfoPlist.strings create mode 100644 InstapaperDemo/en.lproj/ViewController.xib create mode 100644 InstapaperDemo/main.m diff --git a/InstapaperDemo.xcodeproj/project.pbxproj b/InstapaperDemo.xcodeproj/project.pbxproj new file mode 100644 index 0000000..557944e --- /dev/null +++ b/InstapaperDemo.xcodeproj/project.pbxproj @@ -0,0 +1,430 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 5B667C4D14E20B59000881C6 /* AuthViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B667C4B14E20B59000881C6 /* AuthViewController.m */; }; + 5B667C5614E212F6000881C6 /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B667C5514E212F6000881C6 /* NSData+Base64.m */; }; + 5B667C6B14E2179D000881C6 /* AuthViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B667C6D14E2179D000881C6 /* AuthViewController.xib */; }; + 5B9770C8149789C200791728 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B9770C7149789C200791728 /* UIKit.framework */; }; + 5B9770CA149789C200791728 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B9770C9149789C200791728 /* Foundation.framework */; }; + 5B9770CC149789C200791728 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B9770CB149789C200791728 /* CoreGraphics.framework */; }; + 5B9770D2149789C200791728 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5B9770D0149789C200791728 /* InfoPlist.strings */; }; + 5B9770D4149789C200791728 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B9770D3149789C200791728 /* main.m */; }; + 5B9770D8149789C200791728 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B9770D7149789C200791728 /* AppDelegate.m */; }; + 5B9770DB149789C200791728 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B9770DA149789C200791728 /* ViewController.m */; }; + 5B9770DE149789C200791728 /* ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B9770DC149789C200791728 /* ViewController.xib */; }; + 5B97710614978D5400791728 /* NSDate+RFC1123.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B9770F614978D5400791728 /* NSDate+RFC1123.m */; }; + 5B97710714978D5400791728 /* NSDictionary+RequestEncoding.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B9770F814978D5400791728 /* NSDictionary+RequestEncoding.m */; }; + 5B97710814978D5400791728 /* NSString+MKNetworkKitAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B9770FA14978D5400791728 /* NSString+MKNetworkKitAdditions.m */; }; + 5B97710914978D5400791728 /* UIAlertView+MKNetworkKitAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B9770FC14978D5400791728 /* UIAlertView+MKNetworkKitAdditions.m */; }; + 5B97710A14978D5400791728 /* MKNetworkEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B9770FE14978D5400791728 /* MKNetworkEngine.m */; }; + 5B97710B14978D5400791728 /* MKNetworkOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B97710114978D5400791728 /* MKNetworkOperation.m */; }; + 5B97710C14978D5400791728 /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B97710414978D5400791728 /* Reachability.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 5B97710E14978DB400791728 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B97710D14978DB400791728 /* CFNetwork.framework */; }; + 5B97711014978DBC00791728 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B97710F14978DBC00791728 /* SystemConfiguration.framework */; }; + 5B97711214978F6100791728 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B97711114978F6100791728 /* Security.framework */; }; + 5B97711A14978FFD00791728 /* RSOAuthEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B97711814978FFD00791728 /* RSOAuthEngine.m */; }; + 5B9771241497927C00791728 /* RSInstapaperEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B9771231497927C00791728 /* RSInstapaperEngine.m */; }; + 5BAA64D61497D8CB00ED569D /* logo_cube_57.png in Resources */ = {isa = PBXBuildFile; fileRef = 5BAA64D51497D8CB00ED569D /* logo_cube_57.png */; }; + 5BAA64D81497D8D300ED569D /* logo_cube_114.png in Resources */ = {isa = PBXBuildFile; fileRef = 5BAA64D71497D8D300ED569D /* logo_cube_114.png */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 5B667C4A14E20B59000881C6 /* AuthViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AuthViewController.h; sourceTree = ""; }; + 5B667C4B14E20B59000881C6 /* AuthViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AuthViewController.m; sourceTree = ""; }; + 5B667C5414E212F6000881C6 /* NSData+Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+Base64.h"; sourceTree = ""; }; + 5B667C5514E212F6000881C6 /* NSData+Base64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+Base64.m"; sourceTree = ""; }; + 5B667C6C14E2179D000881C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/AuthViewController.xib; sourceTree = ""; }; + 5B9770C3149789C200791728 /* InstapaperDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = InstapaperDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 5B9770C7149789C200791728 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 5B9770C9149789C200791728 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 5B9770CB149789C200791728 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 5B9770CF149789C200791728 /* InstapaperDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "InstapaperDemo-Info.plist"; sourceTree = ""; }; + 5B9770D1149789C200791728 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 5B9770D3149789C200791728 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = main.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 5B9770D5149789C200791728 /* InstapaperDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "InstapaperDemo-Prefix.pch"; sourceTree = ""; }; + 5B9770D6149789C200791728 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = AppDelegate.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 5B9770D7149789C200791728 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AppDelegate.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 5B9770D9149789C200791728 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ViewController.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 5B9770DA149789C200791728 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 5B9770DD149789C200791728 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ViewController.xib; sourceTree = ""; }; + 5B9770F514978D5400791728 /* NSDate+RFC1123.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+RFC1123.h"; sourceTree = ""; }; + 5B9770F614978D5400791728 /* NSDate+RFC1123.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDate+RFC1123.m"; sourceTree = ""; }; + 5B9770F714978D5400791728 /* NSDictionary+RequestEncoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+RequestEncoding.h"; sourceTree = ""; }; + 5B9770F814978D5400791728 /* NSDictionary+RequestEncoding.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+RequestEncoding.m"; sourceTree = ""; }; + 5B9770F914978D5400791728 /* NSString+MKNetworkKitAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+MKNetworkKitAdditions.h"; sourceTree = ""; }; + 5B9770FA14978D5400791728 /* NSString+MKNetworkKitAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+MKNetworkKitAdditions.m"; sourceTree = ""; }; + 5B9770FB14978D5400791728 /* UIAlertView+MKNetworkKitAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIAlertView+MKNetworkKitAdditions.h"; sourceTree = ""; }; + 5B9770FC14978D5400791728 /* UIAlertView+MKNetworkKitAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIAlertView+MKNetworkKitAdditions.m"; sourceTree = ""; }; + 5B9770FD14978D5400791728 /* MKNetworkEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKNetworkEngine.h; sourceTree = ""; }; + 5B9770FE14978D5400791728 /* MKNetworkEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKNetworkEngine.m; sourceTree = ""; }; + 5B9770FF14978D5400791728 /* MKNetworkKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKNetworkKit.h; sourceTree = ""; }; + 5B97710014978D5400791728 /* MKNetworkOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MKNetworkOperation.h; sourceTree = ""; }; + 5B97710114978D5400791728 /* MKNetworkOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MKNetworkOperation.m; sourceTree = ""; }; + 5B97710314978D5400791728 /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = ""; }; + 5B97710414978D5400791728 /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Reachability.m; sourceTree = ""; }; + 5B97710D14978DB400791728 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 5B97710F14978DBC00791728 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + 5B97711114978F6100791728 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 5B97711714978FFD00791728 /* RSOAuthEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = RSOAuthEngine.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 5B97711814978FFD00791728 /* RSOAuthEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = RSOAuthEngine.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 5B9771221497927C00791728 /* RSInstapaperEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = RSInstapaperEngine.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 5B9771231497927C00791728 /* RSInstapaperEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = RSInstapaperEngine.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 5BAA64D51497D8CB00ED569D /* logo_cube_57.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = logo_cube_57.png; path = ../logo_cube_57.png; sourceTree = ""; }; + 5BAA64D71497D8D300ED569D /* logo_cube_114.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = logo_cube_114.png; path = ../logo_cube_114.png; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 5B9770C0149789C200791728 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5B97711214978F6100791728 /* Security.framework in Frameworks */, + 5B97711014978DBC00791728 /* SystemConfiguration.framework in Frameworks */, + 5B97710E14978DB400791728 /* CFNetwork.framework in Frameworks */, + 5B9770C8149789C200791728 /* UIKit.framework in Frameworks */, + 5B9770CA149789C200791728 /* Foundation.framework in Frameworks */, + 5B9770CC149789C200791728 /* CoreGraphics.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 5B9770B8149789C200791728 = { + isa = PBXGroup; + children = ( + 5B9770F014978CC700791728 /* MKNetworkKit */, + 5B97711314978FD300791728 /* RSOAuthEngine */, + 5B9770CD149789C200791728 /* InstapaperDemo */, + 5B9770C6149789C200791728 /* Frameworks */, + 5B9770C4149789C200791728 /* Products */, + ); + sourceTree = ""; + }; + 5B9770C4149789C200791728 /* Products */ = { + isa = PBXGroup; + children = ( + 5B9770C3149789C200791728 /* InstapaperDemo.app */, + ); + name = Products; + sourceTree = ""; + }; + 5B9770C6149789C200791728 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 5B97711114978F6100791728 /* Security.framework */, + 5B97710F14978DBC00791728 /* SystemConfiguration.framework */, + 5B97710D14978DB400791728 /* CFNetwork.framework */, + 5B9770C7149789C200791728 /* UIKit.framework */, + 5B9770C9149789C200791728 /* Foundation.framework */, + 5B9770CB149789C200791728 /* CoreGraphics.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 5B9770CD149789C200791728 /* InstapaperDemo */ = { + isa = PBXGroup; + children = ( + 5B9771211497926200791728 /* Instapaper */, + 5B9770D6149789C200791728 /* AppDelegate.h */, + 5B9770D7149789C200791728 /* AppDelegate.m */, + 5B9770D9149789C200791728 /* ViewController.h */, + 5B9770DA149789C200791728 /* ViewController.m */, + 5B9770DC149789C200791728 /* ViewController.xib */, + 5B667C4A14E20B59000881C6 /* AuthViewController.h */, + 5B667C4B14E20B59000881C6 /* AuthViewController.m */, + 5B667C6D14E2179D000881C6 /* AuthViewController.xib */, + 5B9770CE149789C200791728 /* Supporting Files */, + ); + path = InstapaperDemo; + sourceTree = ""; + }; + 5B9770CE149789C200791728 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 5BAA64D71497D8D300ED569D /* logo_cube_114.png */, + 5BAA64D51497D8CB00ED569D /* logo_cube_57.png */, + 5B9770CF149789C200791728 /* InstapaperDemo-Info.plist */, + 5B9770D0149789C200791728 /* InfoPlist.strings */, + 5B9770D3149789C200791728 /* main.m */, + 5B9770D5149789C200791728 /* InstapaperDemo-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 5B9770F014978CC700791728 /* MKNetworkKit */ = { + isa = PBXGroup; + children = ( + 5B9770F214978D5400791728 /* Categories */, + 5B97710214978D5400791728 /* Reachability */, + 5B9770FD14978D5400791728 /* MKNetworkEngine.h */, + 5B9770FE14978D5400791728 /* MKNetworkEngine.m */, + 5B9770FF14978D5400791728 /* MKNetworkKit.h */, + 5B97710014978D5400791728 /* MKNetworkOperation.h */, + 5B97710114978D5400791728 /* MKNetworkOperation.m */, + ); + name = MKNetworkKit; + path = MKNetworkKit/MKNetworkKit; + sourceTree = SOURCE_ROOT; + }; + 5B9770F214978D5400791728 /* Categories */ = { + isa = PBXGroup; + children = ( + 5B667C5414E212F6000881C6 /* NSData+Base64.h */, + 5B667C5514E212F6000881C6 /* NSData+Base64.m */, + 5B9770F514978D5400791728 /* NSDate+RFC1123.h */, + 5B9770F614978D5400791728 /* NSDate+RFC1123.m */, + 5B9770F714978D5400791728 /* NSDictionary+RequestEncoding.h */, + 5B9770F814978D5400791728 /* NSDictionary+RequestEncoding.m */, + 5B9770F914978D5400791728 /* NSString+MKNetworkKitAdditions.h */, + 5B9770FA14978D5400791728 /* NSString+MKNetworkKitAdditions.m */, + 5B9770FB14978D5400791728 /* UIAlertView+MKNetworkKitAdditions.h */, + 5B9770FC14978D5400791728 /* UIAlertView+MKNetworkKitAdditions.m */, + ); + path = Categories; + sourceTree = ""; + }; + 5B97710214978D5400791728 /* Reachability */ = { + isa = PBXGroup; + children = ( + 5B97710314978D5400791728 /* Reachability.h */, + 5B97710414978D5400791728 /* Reachability.m */, + ); + path = Reachability; + sourceTree = ""; + }; + 5B97711314978FD300791728 /* RSOAuthEngine */ = { + isa = PBXGroup; + children = ( + 5B97711714978FFD00791728 /* RSOAuthEngine.h */, + 5B97711814978FFD00791728 /* RSOAuthEngine.m */, + ); + path = RSOAuthEngine; + sourceTree = SOURCE_ROOT; + }; + 5B9771211497926200791728 /* Instapaper */ = { + isa = PBXGroup; + children = ( + 5B9771221497927C00791728 /* RSInstapaperEngine.h */, + 5B9771231497927C00791728 /* RSInstapaperEngine.m */, + ); + path = Instapaper; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 5B9770C2149789C200791728 /* InstapaperDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5B9770E1149789C200791728 /* Build configuration list for PBXNativeTarget "InstapaperDemo" */; + buildPhases = ( + 5B9770BF149789C200791728 /* Sources */, + 5B9770C0149789C200791728 /* Frameworks */, + 5B9770C1149789C200791728 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = InstapaperDemo; + productName = InstapaperDemo; + productReference = 5B9770C3149789C200791728 /* InstapaperDemo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 5B9770BA149789C200791728 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + ORGANIZATIONNAME = SharpCube; + }; + buildConfigurationList = 5B9770BD149789C200791728 /* Build configuration list for PBXProject "InstapaperDemo" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 5B9770B8149789C200791728; + productRefGroup = 5B9770C4149789C200791728 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 5B9770C2149789C200791728 /* InstapaperDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 5B9770C1149789C200791728 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5B9770D2149789C200791728 /* InfoPlist.strings in Resources */, + 5B9770DE149789C200791728 /* ViewController.xib in Resources */, + 5BAA64D61497D8CB00ED569D /* logo_cube_57.png in Resources */, + 5BAA64D81497D8D300ED569D /* logo_cube_114.png in Resources */, + 5B667C6B14E2179D000881C6 /* AuthViewController.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 5B9770BF149789C200791728 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5B9770D4149789C200791728 /* main.m in Sources */, + 5B9770D8149789C200791728 /* AppDelegate.m in Sources */, + 5B9770DB149789C200791728 /* ViewController.m in Sources */, + 5B97710614978D5400791728 /* NSDate+RFC1123.m in Sources */, + 5B97710714978D5400791728 /* NSDictionary+RequestEncoding.m in Sources */, + 5B97710814978D5400791728 /* NSString+MKNetworkKitAdditions.m in Sources */, + 5B97710914978D5400791728 /* UIAlertView+MKNetworkKitAdditions.m in Sources */, + 5B97710A14978D5400791728 /* MKNetworkEngine.m in Sources */, + 5B97710B14978D5400791728 /* MKNetworkOperation.m in Sources */, + 5B97710C14978D5400791728 /* Reachability.m in Sources */, + 5B97711A14978FFD00791728 /* RSOAuthEngine.m in Sources */, + 5B9771241497927C00791728 /* RSInstapaperEngine.m in Sources */, + 5B667C4D14E20B59000881C6 /* AuthViewController.m in Sources */, + 5B667C5614E212F6000881C6 /* NSData+Base64.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 5B667C6D14E2179D000881C6 /* AuthViewController.xib */ = { + isa = PBXVariantGroup; + children = ( + 5B667C6C14E2179D000881C6 /* en */, + ); + name = AuthViewController.xib; + sourceTree = ""; + }; + 5B9770D0149789C200791728 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 5B9770D1149789C200791728 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 5B9770DC149789C200791728 /* ViewController.xib */ = { + isa = PBXVariantGroup; + children = ( + 5B9770DD149789C200791728 /* en */, + ); + name = ViewController.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 5B9770DF149789C200791728 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 4.3; + PROVISIONING_PROFILE = ""; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 5B9770E0149789C200791728 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 4.3; + OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; + PROVISIONING_PROFILE = ""; + "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 5B9770E2149789C200791728 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "InstapaperDemo/InstapaperDemo-Prefix.pch"; + INFOPLIST_FILE = "InstapaperDemo/InstapaperDemo-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 5B9770E3149789C200791728 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "InstapaperDemo/InstapaperDemo-Prefix.pch"; + INFOPLIST_FILE = "InstapaperDemo/InstapaperDemo-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 5B9770BD149789C200791728 /* Build configuration list for PBXProject "InstapaperDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5B9770DF149789C200791728 /* Debug */, + 5B9770E0149789C200791728 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5B9770E1149789C200791728 /* Build configuration list for PBXNativeTarget "InstapaperDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5B9770E2149789C200791728 /* Debug */, + 5B9770E3149789C200791728 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 5B9770BA149789C200791728 /* Project object */; +} diff --git a/InstapaperDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/InstapaperDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..389a624 --- /dev/null +++ b/InstapaperDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/InstapaperDemo/AppDelegate.h b/InstapaperDemo/AppDelegate.h new file mode 100644 index 0000000..2399cdf --- /dev/null +++ b/InstapaperDemo/AppDelegate.h @@ -0,0 +1,35 @@ +// +// AppDelegate.h +// InstapaperDemo +// +// Created by Rodrigo Sieiro on 12/13/11. +// Copyright (c) 2011 Rodrigo Sieiro . 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 + +@class ViewController; + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; +@property (strong, nonatomic) ViewController *viewController; + +@end diff --git a/InstapaperDemo/AppDelegate.m b/InstapaperDemo/AppDelegate.m new file mode 100644 index 0000000..3e98089 --- /dev/null +++ b/InstapaperDemo/AppDelegate.m @@ -0,0 +1,82 @@ +// +// AppDelegate.m +// InstapaperDemo +// +// Created by Rodrigo Sieiro on 12/13/11. +// Copyright (c) 2011 Rodrigo Sieiro . 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 "AppDelegate.h" +#import "ViewController.h" + +@implementation AppDelegate + +@synthesize window = _window; +@synthesize viewController = _viewController; + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; + self.window.rootViewController = self.viewController; + [self.window makeKeyAndVisible]; + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application +{ + /* + Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. + */ +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + /* + Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + */ +} + +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + /* + Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. + */ +} + +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + /* + Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + */ +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + /* + Called when the application is about to terminate. + Save data if appropriate. + See also applicationDidEnterBackground:. + */ +} + +@end diff --git a/InstapaperDemo/AuthViewController.h b/InstapaperDemo/AuthViewController.h new file mode 100644 index 0000000..104ed4a --- /dev/null +++ b/InstapaperDemo/AuthViewController.h @@ -0,0 +1,46 @@ +// +// AuthViewController.h +// InstapaperDemo +// +// Created by Rodrigo Sieiro on 07/02/12. +// Copyright (c) 2012 Rodrigo Sieiro . 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 + +@protocol AuthViewControllerDelegate; + +@interface AuthViewController : UIViewController + +@property (assign, nonatomic) id delegate; +@property (unsafe_unretained, nonatomic) IBOutlet UITextField *usernameField; +@property (unsafe_unretained, nonatomic) IBOutlet UITextField *passwordField; + +- (IBAction)authenticate:(id)sender; +- (IBAction)cancelAuthentication:(id)sender; + +@end + +@protocol AuthViewControllerDelegate + +- (void)cancelAuthentication; +- (void)authenticateWithUsername:(NSString *)username password:(NSString *)password; + +@end diff --git a/InstapaperDemo/AuthViewController.m b/InstapaperDemo/AuthViewController.m new file mode 100644 index 0000000..911b822 --- /dev/null +++ b/InstapaperDemo/AuthViewController.m @@ -0,0 +1,87 @@ +// +// AuthViewController.m +// InstapaperDemo +// +// Created by Rodrigo Sieiro on 07/02/12. +// Copyright (c) 2012 Rodrigo Sieiro . 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 "AuthViewController.h" + +@implementation AuthViewController + +@synthesize delegate = _delegate; +@synthesize usernameField = _usernameField; +@synthesize passwordField = _passwordField; + +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + return self; +} + +#pragma mark - View lifecycle + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + [self.usernameField becomeFirstResponder]; +} + +- (void)viewDidUnload +{ + [self setUsernameField:nil]; + [self setPasswordField:nil]; + [super viewDidUnload]; +} + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + return (interfaceOrientation == UIInterfaceOrientationPortrait); +} + +#pragma mark - UITextField Delegate Methods + +- (BOOL)textFieldShouldReturn:(UITextField *)textField +{ + if (textField == self.usernameField) { + [self.passwordField becomeFirstResponder]; + } else if (textField == self.passwordField) { + [self authenticate:nil]; + } + + return YES; +} + +#pragma mark - Custom Methods + +- (IBAction)authenticate:(id)sender +{ + if (self.delegate) [self.delegate authenticateWithUsername:self.usernameField.text + password:self.passwordField.text]; +} + +- (IBAction)cancelAuthentication:(id)sender +{ + if (self.delegate) [self.delegate cancelAuthentication]; +} + +@end diff --git a/InstapaperDemo/Instapaper/RSInstapaperEngine.h b/InstapaperDemo/Instapaper/RSInstapaperEngine.h new file mode 100644 index 0000000..ae54214 --- /dev/null +++ b/InstapaperDemo/Instapaper/RSInstapaperEngine.h @@ -0,0 +1,59 @@ +// +// RSInstapaperEngine.h +// RSOAuthEngine +// +// Created by Rodrigo Sieiro on 12/8/11. +// Copyright (c) 2011 Rodrigo Sieiro . 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 "RSOAuthEngine.h" + +@protocol RSInstapaperEngineDelegate; + +typedef void (^RSInstapaperEngineCompletionBlock)(NSError *error); + +@interface RSInstapaperEngine : RSOAuthEngine +{ + RSInstapaperEngineCompletionBlock _oAuthCompletionBlock; + NSString *_screenName; +} + +@property (assign) id delegate; +@property (readonly) NSString *screenName; + +- (id)initWithDelegate:(id )delegate; +- (void)authenticateWithCompletionBlock:(RSInstapaperEngineCompletionBlock)completionBlock; +- (void)authenticateWithUsername:(NSString *)username password:(NSString *)password; +- (void)cancelAuthentication; +- (void)forgetStoredToken; + +- (void)bookmarkURL:(NSString *)url + title:(NSString *)title + description:(NSString *)description + completionBlock:(RSInstapaperEngineCompletionBlock)completionBlock; + +@end + +@protocol RSInstapaperEngineDelegate + +- (void)instapaperEngineNeedsAuthentication:(RSInstapaperEngine *)engine; +- (void)instapaperEngine:(RSInstapaperEngine *)engine statusUpdate:(NSString *)message; + +@end \ No newline at end of file diff --git a/InstapaperDemo/Instapaper/RSInstapaperEngine.m b/InstapaperDemo/Instapaper/RSInstapaperEngine.m new file mode 100644 index 0000000..e6fc1dd --- /dev/null +++ b/InstapaperDemo/Instapaper/RSInstapaperEngine.m @@ -0,0 +1,278 @@ +// +// RSInstapaperEngine.m +// RSOAuthEngine +// +// Created by Rodrigo Sieiro on 12/8/11. +// Copyright (c) 2011 Rodrigo Sieiro . 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 "RSInstapaperEngine.h" + +// Never share this information +#error Put your Consumer Key and Secret here, then remove this error +#define IP_CONSUMER_KEY @"" +#define IP_CONSUMER_SECRET @"" + +// Default instapaper hostname and paths +#define IP_HOSTNAME @"www.instapaper.com" +#define IP_ACCESS_TOKEN @"api/1/oauth/access_token" +#define IP_ADD_BOOKMARK @"api/1/bookmarks/add" + +@interface RSInstapaperEngine () + +- (void)removeOAuthTokenFromKeychain; +- (void)storeOAuthTokenInKeychain; +- (void)retrieveOAuthTokenFromKeychain; + +@end + +@implementation RSInstapaperEngine + +@synthesize delegate = _delegate; + +#pragma mark - Read-only Properties + +- (NSString *)screenName +{ + return _screenName; +} + +#pragma mark - Initialization + +- (id)initWithDelegate:(id )delegate +{ + self = [super initWithHostName:IP_HOSTNAME + customHeaderFields:nil + signatureMethod:RSOAuthHMAC_SHA1 + consumerKey:IP_CONSUMER_KEY + consumerSecret:IP_CONSUMER_SECRET]; + + if (self) { + _oAuthCompletionBlock = nil; + _screenName = nil; + self.delegate = delegate; + + // Retrieve OAuth access token (if previously stored) + [self retrieveOAuthTokenFromKeychain]; + } + + return self; +} + +#pragma mark - OAuth Access Token store/retrieve + +- (void)removeOAuthTokenFromKeychain +{ + // Build the keychain query + NSMutableDictionary *keychainQuery = [NSMutableDictionary dictionaryWithObjectsAndKeys: + (__bridge_transfer NSString *)kSecClassGenericPassword, (__bridge_transfer NSString *)kSecClass, + self.consumerKey, kSecAttrService, + self.consumerKey, kSecAttrAccount, + kCFBooleanTrue, kSecReturnAttributes, + nil]; + + // If there's a token stored for this user, delete it + SecItemDelete((__bridge_retained CFDictionaryRef) keychainQuery); +} + +- (void)storeOAuthTokenInKeychain +{ + // Build the keychain query + NSMutableDictionary *keychainQuery = [NSMutableDictionary dictionaryWithObjectsAndKeys: + (__bridge_transfer NSString *)kSecClassGenericPassword, (__bridge_transfer NSString *)kSecClass, + self.consumerKey, kSecAttrService, + self.consumerKey, kSecAttrAccount, + kCFBooleanTrue, kSecReturnAttributes, + nil]; + + CFTypeRef resData = NULL; + + // If there's a token stored for this user, delete it first + SecItemDelete((__bridge_retained CFDictionaryRef) keychainQuery); + + // Build the token dictionary + NSMutableDictionary *tokenDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys: + self.token, @"oauth_token", + self.tokenSecret, @"oauth_token_secret", + self.screenName, @"screen_name", + nil]; + + // Add the token dictionary to the query + [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:tokenDictionary] + forKey:(__bridge_transfer NSString *)kSecValueData]; + + // Add the token data to the keychain + // Even if we never use resData, replacing with NULL in the call throws EXC_BAD_ACCESS + SecItemAdd((__bridge_retained CFDictionaryRef)keychainQuery, (CFTypeRef *) &resData); +} + +- (void)retrieveOAuthTokenFromKeychain +{ + // Build the keychain query + NSMutableDictionary *keychainQuery = [NSMutableDictionary dictionaryWithObjectsAndKeys: + (__bridge_transfer NSString *)kSecClassGenericPassword, (__bridge_transfer NSString *)kSecClass, + self.consumerKey, kSecAttrService, + self.consumerKey, kSecAttrAccount, + kCFBooleanTrue, kSecReturnData, + kSecMatchLimitOne, kSecMatchLimit, + nil]; + + // Get the token data from the keychain + CFTypeRef resData = NULL; + + // Get the token dictionary from the keychain + if (SecItemCopyMatching((__bridge_retained CFDictionaryRef) keychainQuery, (CFTypeRef *) &resData) == noErr) + { + NSData *resultData = (__bridge_transfer NSData *)resData; + + if (resultData) + { + NSMutableDictionary *tokenDictionary = [NSKeyedUnarchiver unarchiveObjectWithData:resultData]; + + if (tokenDictionary) { + [self setAccessToken:[tokenDictionary objectForKey:@"oauth_token"] + secret:[tokenDictionary objectForKey:@"oauth_token_secret"]]; + + _screenName = [tokenDictionary objectForKey:@"screen_name"]; + } + } + } +} + +#pragma mark - OAuth Authentication Flow + +- (void)authenticateWithCompletionBlock:(RSInstapaperEngineCompletionBlock)completionBlock +{ + // First we reset the OAuth token, so we won't send previous tokens in the request + [self resetOAuthToken]; + + // Store the Completion Block to call after Authenticated + _oAuthCompletionBlock = [completionBlock copy]; + + [self.delegate instapaperEngine:self statusUpdate:@"Waiting for user authorization..."]; + [self.delegate instapaperEngineNeedsAuthentication:self]; +} + +- (void)authenticateWithUsername:(NSString *)username password:(NSString *)password +{ + // Fill the post body with the xAuth parameters + NSMutableDictionary *postParams = [NSMutableDictionary dictionaryWithObjectsAndKeys: + username, @"x_auth_username", + password, @"x_auth_password", + @"client_auth", @"x_auth_mode", + nil]; + + // Get the access token using xAuth + MKNetworkOperation *op = [self operationWithPath:IP_ACCESS_TOKEN + params:postParams + httpMethod:@"POST" + ssl:YES]; + + [op onCompletion:^(MKNetworkOperation *completedOperation) + { + // Fill the access token with the returned data + [self fillTokenWithResponseBody:[completedOperation responseString] type:RSOAuthAccessToken]; + + // Set the user's screen name + _screenName = [username copy]; + + // Store the OAuth access token + [self storeOAuthTokenInKeychain]; + + // Finished, return to previous method + if (_oAuthCompletionBlock) _oAuthCompletionBlock(nil); + _oAuthCompletionBlock = nil; + } + onError:^(NSError *error) + { + if (_oAuthCompletionBlock) _oAuthCompletionBlock(error); + _oAuthCompletionBlock = nil; + }]; + + [self.delegate instapaperEngine:self statusUpdate:@"Authenticating..."]; + [self enqueueSignedOperation:op]; +} + +- (void)cancelAuthentication +{ + NSDictionary *ui = [NSDictionary dictionaryWithObjectsAndKeys:@"Authentication cancelled.", NSLocalizedDescriptionKey, nil]; + NSError *error = [NSError errorWithDomain:@"com.sharpcube.RSInstapaperEngine.ErrorDomain" code:401 userInfo:ui]; + + if (_oAuthCompletionBlock) _oAuthCompletionBlock(error); + _oAuthCompletionBlock = nil; +} + +- (void)forgetStoredToken +{ + [self removeOAuthTokenFromKeychain]; + [self resetOAuthToken]; + _screenName = nil; +} + +#pragma mark - Public Methods + +- (void)bookmarkURL:(NSString *)url + title:(NSString *)title + description:(NSString *)description + completionBlock:(RSInstapaperEngineCompletionBlock)completionBlock +{ + if (!self.isAuthenticated) { + [self authenticateWithCompletionBlock:^(NSError *error) { + if (error) { + // Authentication failed, return the error + completionBlock(error); + } else { + // Authentication succeeded, call this method again + [self bookmarkURL:url + title:title + description:description + completionBlock:completionBlock]; + } + }]; + + // This method will be called again once the authentication completes + return; + } + + // Fill the post body with the tweet + NSMutableDictionary *postParams = [NSMutableDictionary dictionaryWithObjectsAndKeys: + url, @"url", + title, @"title", + description, @"description", + nil]; + + // Send the bookmark to Instapaper + MKNetworkOperation *op = [self operationWithPath:IP_ADD_BOOKMARK + params:postParams + httpMethod:@"POST" + ssl:YES]; + + // TODO: Actually check the response to get the data or the error + [op onCompletion:^(MKNetworkOperation *completedOperation) { + completionBlock(nil); + } onError:^(NSError *error) { + completionBlock(error); + }]; + + [self.delegate instapaperEngine:self statusUpdate:@"Adding the bookmark..."]; + [self enqueueSignedOperation:op]; +} + +@end diff --git a/InstapaperDemo/InstapaperDemo-Info.plist b/InstapaperDemo/InstapaperDemo-Info.plist new file mode 100644 index 0000000..6009745 --- /dev/null +++ b/InstapaperDemo/InstapaperDemo-Info.plist @@ -0,0 +1,54 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + InstaAdd! + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFiles + + logo_cube_57.png + logo_cube_114.png + + CFBundleIcons + + CFBundlePrimaryIcon + + CFBundleIconFiles + + logo_cube_57.png + logo_cube_114.png + + UIPrerenderedIcon + + + + CFBundleIdentifier + com.sharpcube.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + + diff --git a/InstapaperDemo/InstapaperDemo-Prefix.pch b/InstapaperDemo/InstapaperDemo-Prefix.pch new file mode 100644 index 0000000..66744fd --- /dev/null +++ b/InstapaperDemo/InstapaperDemo-Prefix.pch @@ -0,0 +1,15 @@ +// +// Prefix header for all source files of the 'InstapaperDemo' target in the 'InstapaperDemo' project +// + +#import + +#ifndef __IPHONE_4_0 +#warning "This project uses features only available in iOS SDK 4.0 and later." +#endif + +#ifdef __OBJC__ + #import + #import + #import "MKNetworkKit.h" +#endif diff --git a/InstapaperDemo/ViewController.h b/InstapaperDemo/ViewController.h new file mode 100644 index 0000000..7325b72 --- /dev/null +++ b/InstapaperDemo/ViewController.h @@ -0,0 +1,50 @@ +// +// ViewController.h +// InstapaperDemo +// +// Created by Rodrigo Sieiro on 12/13/11. +// Copyright (c) 2011 Rodrigo Sieiro . 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 +#import "RSInstapaperEngine.h" +#import "AuthViewController.h" + +@interface ViewController : UIViewController +{ + BOOL _keyboardIsShown; +} + +@property (strong, nonatomic) RSInstapaperEngine *instapaperEngine; +@property (strong, nonatomic) AuthViewController *authView; + +@property (unsafe_unretained, nonatomic) IBOutlet UITextField *urlTextField; +@property (unsafe_unretained, nonatomic) IBOutlet UITextField *titleTextField; +@property (unsafe_unretained, nonatomic) IBOutlet UITextView *textView; +@property (unsafe_unretained, nonatomic) IBOutlet UIBarButtonItem *sendButton; +@property (unsafe_unretained, nonatomic) IBOutlet UIBarButtonItem *clearButton; +@property (unsafe_unretained, nonatomic) IBOutlet UILabel *statusLabel; +@property (unsafe_unretained, nonatomic) IBOutlet UIScrollView *scrollView; + +- (IBAction)addBookmark:(id)sender; +- (IBAction)clearFields:(id)sender; +- (void)swipedRight:(UIGestureRecognizer *)recognizer; + +@end diff --git a/InstapaperDemo/ViewController.m b/InstapaperDemo/ViewController.m new file mode 100644 index 0000000..fec6837 --- /dev/null +++ b/InstapaperDemo/ViewController.m @@ -0,0 +1,261 @@ +// +// ViewController.m +// InstapaperDemo +// +// Created by Rodrigo Sieiro on 12/13/11. +// Copyright (c) 2011 Rodrigo Sieiro . 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 "ViewController.h" + +@implementation ViewController + +@synthesize instapaperEngine = _instapaperEngine; +@synthesize authView = _authView; +@synthesize urlTextField = _urlTextField; +@synthesize titleTextField = _titleTextField; +@synthesize textView = _textView; +@synthesize sendButton = _sendButton; +@synthesize clearButton = _clearButton; +@synthesize statusLabel = _statusLabel; +@synthesize scrollView = _scrollView; + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; +} + +#pragma mark - View Lifecycle + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + // register for keyboard notifications + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWillShow:) + name:UIKeyboardWillShowNotification + object:self.view.window]; + + // register for keyboard notifications + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWillHide:) + name:UIKeyboardWillHideNotification + object:self.view.window]; + + _keyboardIsShown = NO; + self.scrollView.contentSize = CGSizeMake(320, 388); + self.instapaperEngine = [[RSInstapaperEngine alloc] initWithDelegate:self]; + + // A right swipe on the status label will clear the stored token + UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipedRight:)]; + swipeRight.direction = UISwipeGestureRecognizerDirectionRight; + swipeRight.numberOfTouchesRequired = 1; + [self.statusLabel.superview addGestureRecognizer:swipeRight]; + + // Check if the user is already authenticated + if (self.instapaperEngine.isAuthenticated) { + self.statusLabel.text = [NSString stringWithFormat:@"Signed in as %@.", self.instapaperEngine.screenName]; + } else { + self.statusLabel.text = @"Not signed in."; + } + + [self.urlTextField becomeFirstResponder]; +} + +- (void)viewDidUnload +{ + [self setTextView:nil]; + [self setSendButton:nil]; + [self setInstapaperEngine:nil]; + [self setStatusLabel:nil]; + [self setScrollView:nil]; + [self setUrlTextField:nil]; + [self setTitleTextField:nil]; + [self setClearButton:nil]; + + // unregister for keyboard notifications while not visible. + [[NSNotificationCenter defaultCenter] removeObserver:self + name:UIKeyboardWillShowNotification + object:nil]; + + // unregister for keyboard notifications while not visible. + [[NSNotificationCenter defaultCenter] removeObserver:self + name:UIKeyboardWillHideNotification + object:nil]; + + [super viewDidUnload]; +} + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + return (interfaceOrientation == UIInterfaceOrientationPortrait); +} + +#pragma mark - Keyboard Show/Hide Notifications + +- (void)keyboardWillShow:(NSNotification *)n +{ + if (_keyboardIsShown) return; + + NSDictionary* userInfo = [n userInfo]; + CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; + + CGRect viewFrame = self.scrollView.frame; + viewFrame.size.height -= keyboardSize.height; + + [UIView animateWithDuration:0.3 animations:^{ + [self.scrollView setFrame:viewFrame]; + }]; + + _keyboardIsShown = YES; +} + +- (void)keyboardWillHide:(NSNotification *)n +{ + NSDictionary* userInfo = [n userInfo]; + CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; + + CGRect viewFrame = self.scrollView.frame; + viewFrame.size.height += keyboardSize.height; + + [UIView animateWithDuration:0.3 animations:^{ + [self.scrollView setFrame:viewFrame]; + }]; + + _keyboardIsShown = NO; +} + +#pragma mark - UITextField Delegate Methods + +- (BOOL)textFieldShouldReturn:(UITextField *)textField +{ + if (textField == self.urlTextField) { + [self.titleTextField becomeFirstResponder]; + } else if (textField == self.titleTextField) { + [self.textView becomeFirstResponder]; + } + + return YES; +} + +#pragma mark - RSInstapaperEngine Delegate Methods + +- (void)instapaperEngineNeedsAuthentication:(RSInstapaperEngine *)engine +{ + self.authView = [[AuthViewController alloc] initWithNibName:@"AuthViewController" bundle:nil]; + self.authView.delegate = self; + + [self presentModalViewController:self.authView animated:YES]; +} + +- (void)instapaperEngine:(RSInstapaperEngine *)engine statusUpdate:(NSString *)message +{ + self.statusLabel.text = message; +} + +#pragma mark - WebViewController Delegate Methods + +- (void)cancelAuthentication +{ + [self dismissModalViewControllerAnimated:YES]; + if (self.instapaperEngine) [self.instapaperEngine cancelAuthentication]; +} + +- (void)authenticateWithUsername:(NSString *)username password:(NSString *)password +{ + [self dismissModalViewControllerAnimated:YES]; + if (self.instapaperEngine) [self.instapaperEngine authenticateWithUsername:username password:password]; +} + +#pragma mark - Custom Methods + +- (void)swipedRight:(UIGestureRecognizer *)recognizer +{ + if (self.instapaperEngine) [self.instapaperEngine forgetStoredToken]; + self.statusLabel.text = @"Not signed in."; +} + +- (IBAction)addBookmark:(id)sender +{ + if (self.instapaperEngine) + { + self.sendButton.enabled = NO; + self.clearButton.enabled = NO; + + // Instapaper requires full URLs + if (![self.urlTextField.text hasPrefix:@"http://"]) + self.urlTextField.text = [NSString stringWithFormat:@"http://%@", self.urlTextField.text]; + + // TODO: Validate the contents of each field + [self.instapaperEngine bookmarkURL:self.urlTextField.text + title:self.titleTextField.text + description:self.textView.text + completionBlock:^(NSError *error) + { + if (error) { + NSString *errorDescription; + + // TODO: check for other type of errors + if (error.code == 401) { + errorDescription = @"Authentication failed."; + } else { + errorDescription = [error localizedDescription]; + } + + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" + message:errorDescription + delegate:nil + cancelButtonTitle:@"Dismiss" + otherButtonTitles:nil]; + [alert show]; + } else { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"InstaAdd!" + message:@"Bookmark added successfully!" + delegate:nil + cancelButtonTitle:@"Dismiss" + otherButtonTitles:nil]; + [alert show]; + + [self clearFields:nil]; + } + + self.sendButton.enabled = YES; + self.clearButton.enabled = YES; + + if (self.instapaperEngine.isAuthenticated) { + self.statusLabel.text = [NSString stringWithFormat:@"Signed in as %@.", self.instapaperEngine.screenName]; + } else { + self.statusLabel.text = @"Not signed in."; + } + }]; + } +} + +- (IBAction)clearFields:(id)sender +{ + self.urlTextField.text = @""; + self.titleTextField.text = @""; + self.textView.text = @""; + + [self.urlTextField becomeFirstResponder]; +} + +@end diff --git a/InstapaperDemo/en.lproj/AuthViewController.xib b/InstapaperDemo/en.lproj/AuthViewController.xib new file mode 100644 index 0000000..b8c0683 --- /dev/null +++ b/InstapaperDemo/en.lproj/AuthViewController.xib @@ -0,0 +1,400 @@ + + + + 1280 + 11C74 + 1938 + 1138.23 + 567.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 933 + + + IBUITextField + IBUINavigationItem + IBUIBarButtonItem + IBUIView + IBUINavigationBar + IBProxyObject + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + PluginDependencyRecalculationVersion + + + + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + + + + 290 + {320, 44} + + + + _NS:260 + IBCocoaTouchFramework + + + + Instapaper + + IBCocoaTouchFramework + 1 + + 1 + + + Login + IBCocoaTouchFramework + 2 + + + IBCocoaTouchFramework + + + + + + 292 + {{20, 74}, {280, 31}} + + + + _NS:304 + NO + YES + IBCocoaTouchFramework + 0 + + 3 + E-mail or Username + + 3 + MAA + + 2 + + + YES + 17 + + 1 + 7 + 4 + IBCocoaTouchFramework + + + 1 + 14 + + + Helvetica + 14 + 16 + + + + + 292 + {{20, 124}, {280, 31}} + + + _NS:304 + NO + YES + IBCocoaTouchFramework + 0 + + 3 + Password (if you have one) + + 3 + MAA + + + YES + 17 + + 1 + 9 + YES + IBCocoaTouchFramework + + + + + + {{0, 20}, {320, 460}} + + + + + 10 + + 549453824 + {512, 1} + + + + + + TU0AKgAACAjFzNT/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/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/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/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/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/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/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/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/wANAQAAAwAAAAECAAAAAQEAAwAAAAEAAQAAAQIAAwAAAAQAAAiqAQMAAwAA +AAEAAQAAAQYAAwAAAAEAAgAAAREABAAAAAEAAAAIARIAAwAAAAEAAQAAARUAAwAAAAEABAAAARYAAwAA +AAEAAQAAARcABAAAAAEAAAgAARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAQAAAiyAAAAAAAI +AAgACAAIAAEAAQABAAE + + + + + + 3 + MCAwAA + + + groupTableViewBackgroundColor + + + IBCocoaTouchFramework + + + + + + + view + + + + 3 + + + + usernameField + + + + 11 + + + + passwordField + + + + 14 + + + + delegate + + + + 12 + + + + delegate + + + + 13 + + + + authenticate: + + + + 15 + + + + cancelAuthentication: + + + + 16 + + + + + + 0 + + + + + + 1 + + + + + + + + + + -1 + + + File's Owner + + + -2 + + + + + 4 + + + + + + + + 5 + + + + + + + + + 6 + + + + + 7 + + + + + 10 + + + + + 9 + + + + + + + AuthViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + + + 16 + + + + + AuthViewController + UIViewController + + id + id + + + + authenticate: + id + + + cancelAuthentication: + id + + + + UITextField + UITextField + + + + passwordField + UITextField + + + usernameField + UITextField + + + + IBProjectSource + ./Classes/AuthViewController.h + + + + + 0 + IBCocoaTouchFramework + YES + 3 + 933 + + diff --git a/InstapaperDemo/en.lproj/InfoPlist.strings b/InstapaperDemo/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/InstapaperDemo/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/InstapaperDemo/en.lproj/ViewController.xib b/InstapaperDemo/en.lproj/ViewController.xib new file mode 100644 index 0000000..05402a0 --- /dev/null +++ b/InstapaperDemo/en.lproj/ViewController.xib @@ -0,0 +1,692 @@ + + + + 1280 + 11C74 + 1938 + 1138.23 + 567.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 933 + + + IBProxyObject + IBUIBarButtonItem + IBUILabel + IBUITextField + IBUINavigationBar + IBUINavigationItem + IBUITextView + IBUIScrollView + IBUIView + + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + PluginDependencyRecalculationVersion + + + + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + + + + 290 + {320, 44} + + + + _NS:260 + IBCocoaTouchFramework + + + + InstaAdd! + + Clear + IBCocoaTouchFramework + 1 + + + + IBCocoaTouchFramework + 2 + + 0 + + IBCocoaTouchFramework + + + + + + 290 + + + + 292 + {320, 28} + + + + _NS:328 + NO + YES + 7 + NO + IBCocoaTouchFramework + Not signed in. + + 1 + MSAxIDEAA + + 1 + + + + 1 + NO + 10 + 1 + + 2 + 12 + + + Helvetica-Bold + 12 + 16 + + + + {{0, 44}, {320, 28}} + + + + _NS:196 + + 3 + MAA + + IBCocoaTouchFramework + + + + 274 + + + + 258 + {{0, 80}, {320, 308}} + + + + _NS:639 + + 1 + MSAxIDEAA + + YES + YES + + IBCocoaTouchFramework + NO + NO + NO + NO + + + 2 + IBCocoaTouchFramework + + + 1 + 14 + + + Helvetica + 14 + 16 + + + + + 290 + {{51, 0}, {269, 40}} + + + + _NS:304 + + 3 + MQA + + NO + YES + IBCocoaTouchFramework + 0 + + + 3 + MAA + + 2 + + + YES + 17 + + 1 + 3 + 4 + IBCocoaTouchFramework + + + + + + + 292 + {{11, 9}, {42, 21}} + + + + _NS:328 + NO + YES + 7 + NO + IBCocoaTouchFramework + URL: + + 3 + MC42NjY2NjY2NjY3AA + + + 1 + 10 + + + + + + 290 + {{51, 40}, {269, 40}} + + + + _NS:304 + + NO + YES + IBCocoaTouchFramework + 0 + + + 3 + MAA + + + YES + 17 + + 2 + 4 + IBCocoaTouchFramework + + + + + + + 292 + {{11, 49}, {42, 21}} + + + + _NS:328 + NO + YES + 7 + NO + IBCocoaTouchFramework + Title: + + + 1 + 10 + + + + + + 292 + {{0, 38}, {320, 1}} + + + + _NS:196 + + IBCocoaTouchFramework + + + + 292 + {{0, 80}, {320, 1}} + + + _NS:196 + + IBCocoaTouchFramework + + + {{0, 72}, {320, 388}} + + + + _NS:190 + + YES + YES + IBCocoaTouchFramework + NO + + + {{0, 20}, {320, 460}} + + + + + 10 + + 549453824 + {512, 1} + + + + + + TU0AKgAACAjFzNT/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/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/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/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/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/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/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/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/wANAQAAAwAAAAECAAAAAQEAAwAAAAEAAQAAAQIAAwAAAAQAAAiqAQMAAwAA +AAEAAQAAAQYAAwAAAAEAAgAAAREABAAAAAEAAAAIARIAAwAAAAEAAQAAARUAAwAAAAEABAAAARYAAwAA +AAEAAQAAARcABAAAAAEAAAgAARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAQAAAiyAAAAAAAI +AAgACAAIAAEAAQABAAE + + + + + + 3 + MCAwAA + + + groupTableViewBackgroundColor + + NO + + IBCocoaTouchFramework + + + + + + + view + + + + 7 + + + + sendButton + + + + 16 + + + + statusLabel + + + + 20 + + + + textView + + + + 14 + + + + scrollView + + + + 38 + + + + urlTextField + + + + 39 + + + + titleTextField + + + + 40 + + + + clearButton + + + + 46 + + + + addBookmark: + + + + 44 + + + + delegate + + + + 41 + + + + delegate + + + + 42 + + + + clearFields: + + + + 45 + + + + + + 0 + + + + + + -1 + + + File's Owner + + + -2 + + + + + 6 + + + + + + + + + + 10 + + + + + + + + 11 + + + + + + + + + 12 + + + + + 18 + + + + + + + + 19 + + + + + 23 + + + + + + + + + + + + + + 13 + + + + + 24 + + + + + 26 + + + + + 27 + + + + + 28 + + + + + 29 + + + + + 25 + + + + + 43 + + + + + + + ViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + + + 46 + + + + + ViewController + UIViewController + + id + id + + + + addBookmark: + id + + + clearFields: + id + + + + UIBarButtonItem + UIScrollView + UIBarButtonItem + UILabel + UITextView + UITextField + UITextField + + + + clearButton + UIBarButtonItem + + + scrollView + UIScrollView + + + sendButton + UIBarButtonItem + + + statusLabel + UILabel + + + textView + UITextView + + + titleTextField + UITextField + + + urlTextField + UITextField + + + + IBProjectSource + ./Classes/ViewController.h + + + + + 0 + IBCocoaTouchFramework + YES + 3 + 933 + + diff --git a/InstapaperDemo/main.m b/InstapaperDemo/main.m new file mode 100644 index 0000000..49888f5 --- /dev/null +++ b/InstapaperDemo/main.m @@ -0,0 +1,35 @@ +// +// main.m +// InstapaperDemo +// +// Created by Rodrigo Sieiro on 12/13/11. +// Copyright (c) 2011 Rodrigo Sieiro . 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 + +#import "AppDelegate.h" + +int main(int argc, char *argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +}