Permalink
Browse files

initial commit

  • Loading branch information...
0 parents commit 5f55020eb620aedd3f54b9f0277ab3cd1b0107c1 Greg Allen committed Jan 29, 2010
4 .gitignore
@@ -0,0 +1,4 @@
+build
+*.mode1v3
+*.pbxuser
+*.perspectivev3
761 AddTask.xib
@@ -0,0 +1,761 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">1060</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.CocoaPlugin</string>
+ <string key="NS.object.0">740</string>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="4"/>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</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="NSCustomObject" id="1001">
+ <string key="NSClassName">NSObject</string>
+ </object>
+ <object class="NSCustomObject" id="1003">
+ <string key="NSClassName">FirstResponder</string>
+ </object>
+ <object class="NSCustomObject" id="1004">
+ <string key="NSClassName">NSApplication</string>
+ </object>
+ <object class="NSWindowTemplate" id="201007230">
+ <int key="NSWindowStyleMask">31</int>
+ <int key="NSWindowBacking">2</int>
+ <string key="NSWindowRect">{{230, 450}, {276, 91}}</string>
+ <int key="NSWTFlags">-1535639552</int>
+ <string key="NSWindowTitle">Add Task</string>
+ <string key="NSWindowClass">NSWindow</string>
+ <nil key="NSViewClass"/>
+ <object class="NSView" key="NSWindowView" id="1000608662">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">256</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSTextField" id="76525039">
+ <reference key="NSNextResponder" ref="1000608662"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{20, 49}, {236, 22}}</string>
+ <reference key="NSSuperview" ref="1000608662"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSTextFieldCell" key="NSCell" id="843611152">
+ <int key="NSCellFlags">-1804468671</int>
+ <int key="NSCellFlags2">272630784</int>
+ <string key="NSContents"/>
+ <object class="NSFont" key="NSSupport" id="1070372354">
+ <string key="NSName">LucidaGrande</string>
+ <double key="NSSize">13</double>
+ <int key="NSfFlags">1044</int>
+ </object>
+ <reference key="NSControlView" ref="76525039"/>
+ <bool key="NSDrawsBackground">YES</bool>
+ <object class="NSColor" key="NSBackgroundColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">textBackgroundColor</string>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ </object>
+ </object>
+ <object class="NSColor" key="NSTextColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">textColor</string>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MAA</bytes>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSButton" id="201207751">
+ <reference key="NSNextResponder" ref="1000608662"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{194, 19}, {62, 23}}</string>
+ <reference key="NSSuperview" ref="1000608662"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="140485819">
+ <int key="NSCellFlags">-2080244224</int>
+ <int key="NSCellFlags2">134217728</int>
+ <string key="NSContents">Add</string>
+ <reference key="NSSupport" ref="1070372354"/>
+ <reference key="NSControlView" ref="201207751"/>
+ <int key="NSButtonFlags">-2033434369</int>
+ <int key="NSButtonFlags2">162</int>
+ <string key="NSAlternateContents"/>
+ <string key="NSKeyEquivalent"/>
+ <int key="NSPeriodicDelay">400</int>
+ <int key="NSPeriodicInterval">75</int>
+ </object>
+ </object>
+ <object class="NSButton" id="301323410">
+ <reference key="NSNextResponder" ref="1000608662"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{118, 19}, {68, 23}}</string>
+ <reference key="NSSuperview" ref="1000608662"/>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="177310845">
+ <int key="NSCellFlags">-2080244224</int>
+ <int key="NSCellFlags2">134217728</int>
+ <string key="NSContents">Cancel</string>
+ <reference key="NSSupport" ref="1070372354"/>
+ <reference key="NSControlView" ref="301323410"/>
+ <int key="NSButtonFlags">-2033434369</int>
+ <int key="NSButtonFlags2">162</int>
+ <string key="NSAlternateContents"/>
+ <string key="NSKeyEquivalent"/>
+ <int key="NSPeriodicDelay">400</int>
+ <int key="NSPeriodicInterval">75</int>
+ </object>
+ </object>
+ </object>
+ <string key="NSFrameSize">{276, 91}</string>
+ <reference key="NSSuperview"/>
+ </object>
+ <string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string>
+ <string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </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">-2</int>
+ <reference key="object" ref="1001"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="1003"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">First Responder</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-3</int>
+ <reference key="object" ref="1004"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">Application</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">3</int>
+ <reference key="object" ref="201007230"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1000608662"/>
+ </object>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">4</int>
+ <reference key="object" ref="1000608662"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="301323410"/>
+ <reference ref="201207751"/>
+ <reference ref="76525039"/>
+ </object>
+ <reference key="parent" ref="201007230"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">5</int>
+ <reference key="object" ref="301323410"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="177310845"/>
+ </object>
+ <reference key="parent" ref="1000608662"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">6</int>
+ <reference key="object" ref="201207751"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="140485819"/>
+ </object>
+ <reference key="parent" ref="1000608662"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">7</int>
+ <reference key="object" ref="76525039"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="843611152"/>
+ </object>
+ <reference key="parent" ref="1000608662"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">8</int>
+ <reference key="object" ref="843611152"/>
+ <reference key="parent" ref="76525039"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">9</int>
+ <reference key="object" ref="140485819"/>
+ <reference key="parent" ref="201207751"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">10</int>
+ <reference key="object" ref="177310845"/>
+ <reference key="parent" ref="301323410"/>
+ </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>10.IBPluginDependency</string>
+ <string>3.IBEditorWindowLastContentRect</string>
+ <string>3.IBPluginDependency</string>
+ <string>3.IBWindowTemplateEditedContentRect</string>
+ <string>3.NSWindowTemplate.visibleAtLaunch</string>
+ <string>4.IBPluginDependency</string>
+ <string>5.IBPluginDependency</string>
+ <string>6.IBPluginDependency</string>
+ <string>7.IBPluginDependency</string>
+ <string>8.IBPluginDependency</string>
+ <string>9.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>{{1085, 661}, {276, 91}}</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>{{1085, 661}, {276, 91}}</string>
+ <boolean value="YES"/>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</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">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">JSON/NSObject+SBJSON.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">JSON/SBJsonWriter.h</string>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSActionCell</string>
+ <string key="superclassName">NSCell</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSActionCell.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSApplication</string>
+ <string key="superclassName">NSResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="863771742">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSApplication.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSApplication</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="405422936">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSApplicationScripting.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSApplication</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="224662362">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSColorPanel.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSApplication</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSHelpManager.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSApplication</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSPageLayout.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSApplication</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSUserInterfaceItemSearching.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSApplication</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">BWToolkitFramework.framework/Headers/NSApplication+BWAdditions.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSButton</string>
+ <string key="superclassName">NSControl</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSButton.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSButtonCell</string>
+ <string key="superclassName">NSActionCell</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSButtonCell.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSCell</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSCell.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSControl</string>
+ <string key="superclassName">NSView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="419684954">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSControl.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSFormatter</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">Foundation.framework/Headers/NSFormatter.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSMenu</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="299365019">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSMenu.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">AppKit.framework/Headers/NSAccessibility.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <reference key="sourceIdentifier" ref="863771742"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <reference key="sourceIdentifier" ref="405422936"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <reference key="sourceIdentifier" ref="224662362"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <reference key="sourceIdentifier" ref="419684954"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSDictionaryController.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">AppKit.framework/Headers/NSDragging.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">AppKit.framework/Headers/NSFontManager.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">AppKit.framework/Headers/NSFontPanel.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">AppKit.framework/Headers/NSKeyValueBinding.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <reference key="sourceIdentifier" ref="299365019"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSNibLoading.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">AppKit.framework/Headers/NSOutlineView.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">AppKit.framework/Headers/NSPasteboard.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">AppKit.framework/Headers/NSSavePanel.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">AppKit.framework/Headers/NSTableView.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">AppKit.framework/Headers/NSToolbarItem.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="33193387">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSView.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/NSArchiver.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/NSClassDescription.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/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/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/NSObjectScripting.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/NSPortCoder.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/NSScriptClassDescription.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/NSScriptKeyValueCoding.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/NSScriptObjectSpecifiers.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/NSScriptWhoseTests.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/NSURLDownload.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSInterfaceStyle.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSResponder</string>
+ <string key="superclassName">NSObject</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSResponder.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSTextField</string>
+ <string key="superclassName">NSControl</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSTextField.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSTextFieldCell</string>
+ <string key="superclassName">NSActionCell</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSTextFieldCell.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSClipView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSMenuItem.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSRulerView.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSView</string>
+ <string key="superclassName">NSResponder</string>
+ <reference key="sourceIdentifier" ref="33193387"/>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSView</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">BWToolkitFramework.framework/Headers/NSView+BWAdditions.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSWindow</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSDrawer.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSWindow</string>
+ <string key="superclassName">NSResponder</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSWindow.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSWindow</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">AppKit.framework/Headers/NSWindowScripting.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
+ <string key="className">NSWindow</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBFrameworkSource</string>
+ <string key="minorKey">BWToolkitFramework.framework/Headers/NSWindow+BWAdditions.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.CocoaPlugin.macosx</string>
+ <integer value="1060" key="NS.object.0"/>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
+ <integer value="3000" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <string key="IBDocument.LastKnownRelativeProjectPath">SimpleRTM.xcodeproj</string>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ </data>
+</archive>
78 EVRZRtmApi.h
@@ -0,0 +1,78 @@
+/*
+
+ The MIT License
+
+ Copyright (c) 2009 Konstantin Kudryashov <ever.zet@gmail.com>
+
+ 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 <Cocoa/Cocoa.h>
+#import <CommonCrypto/CommonDigest.h>
+#import "JSON.h"
+
+
+@interface EVRZRtmApi : NSObject {
+ NSString* apiKey;
+ NSString* apiSecret;
+ NSString* token;
+ NSDate* lastApiCall;
+}
+
+@property (retain) NSString* apiKey;
+@property (retain) NSString* apiSecret;
+@property (retain) NSString* token;
+@property (retain) NSDate* lastApiCall;
+
++ (EVRZRtmApi*)instance;
+
+// Initializators
+- (id)initWithApiKey:(NSString*)anApiKey andApiSecret:(NSString*)anApiSecret;
+
+// Helpers
++ (NSString*)rtmDateFromDate:(NSDate*)aDate;
++ (NSDate*)dateFromRtmDate:(NSString*)anSqlDate;
+
+// Authorization
+- (NSString*)frob;
+- (NSString*)authUrlForPerms:(NSString*)aPerms withFrob:(NSString*)aFrob;
+- (NSString*)tokenWithFrob:(NSString*)aFrob;
+
+// Often methods
+- (NSString*)timeline;
+
+// Response error checking
+- (BOOL)noErrorsInResponse:(NSDictionary*)anResponse;
+- (NSString*)errorMsgInResponse:(NSDictionary*)anResponse;
+- (id)errorWithResponse:(NSDictionary*)anResponse;
+
+// Calling methods
+- (NSDictionary*)dataByCallingMethod:(NSString*)aMethod andParameters:(NSDictionary*)aParameters;
+- (NSDictionary*)dataByCallingMethod:(NSString*)aMethod andParameters:(NSDictionary*)aParameters withToken:(BOOL)useToken;
+
+// Generating urls with parameters, method name & token
+- (NSString*)urlStringWithMethod:(NSString*)aMethod andParameters:(NSDictionary*)aParameters;
+- (NSString*)urlStringWithMethod:(NSString*)aMethod andParameters:(NSDictionary*)aParameters withToken:(BOOL)useToken;
+
+// Generating url parameters & api_sig
+- (NSString*)urlParametersWithDictionary:(NSDictionary*)aParameters;
+- (NSString*)apiSigFromParameters:(NSDictionary*)aParameters;
+
+@end
281 EVRZRtmApi.m
@@ -0,0 +1,281 @@
+/*
+
+ The MIT License
+
+ Copyright (c) 2009 Konstantin Kudryashov <ever.zet@gmail.com>
+
+ 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 "EVRZRtmApi.h"
+
+static EVRZRtmApi* LTRtmApiInstance;
+
+NSString* md5(NSString *str)
+{
+ const char *cStr = [str UTF8String];
+ unsigned char result[CC_MD5_DIGEST_LENGTH];
+ CC_MD5(cStr, strlen(cStr), result);
+ return [[NSString stringWithFormat:
+ @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+ result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
+ result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]
+ ] lowercaseString];
+}
+
+NSComparisonResult sortParameterKeysByChars(NSString* string1, NSString* string2, NSInteger charNum)
+{
+ if ([string1 length] == (charNum + 1) || [string2 length] == (charNum + 1))
+ {
+ return NSOrderedSame;
+ }
+
+ char v1 = [string1 characterAtIndex:charNum];
+ char v2 = [string2 characterAtIndex:charNum];
+
+ if (v1 < v2)
+ {
+ return NSOrderedAscending;
+ }
+ else if (v1 > v2)
+ {
+ return NSOrderedDescending;
+ }
+ else
+ {
+ return sortParameterKeysByChars(string1, string2, charNum + 1);
+ }
+}
+
+NSComparisonResult sortParameterKeys(NSString* string1, NSString* string2, void *context)
+{
+ return sortParameterKeysByChars(string1, string2, 0);
+}
+
+@implementation EVRZRtmApi
+
+@synthesize apiKey;
+@synthesize apiSecret;
+@synthesize token;
+@synthesize lastApiCall;
+
++ (EVRZRtmApi*)instance
+{
+ return LTRtmApiInstance;
+}
+
+- (id)init
+{
+ return [self initWithApiKey:@"" andApiSecret:@""];
+}
+
+- (id)initWithApiKey:(NSString*)anApiKey andApiSecret:(NSString*)anApiSecret
+{
+ if (!(self = [super init]))
+ {
+ return nil;
+ }
+
+ [self setApiKey:anApiKey];
+ [self setApiSecret:anApiSecret];
+
+ LTRtmApiInstance = self;
+
+ return self;
+}
+
+- (void)dealloc
+{
+ [apiKey release];
+ [apiSecret release];
+ [token release];
+ [lastApiCall release];
+
+ [super dealloc];
+}
+
++ (NSString*)rtmDateFromDate:(NSDate*)aDate
+{
+ NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
+ [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"];
+ [dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]];
+ NSString* dateString = [dateFormatter stringFromDate:aDate];
+ [dateFormatter release];
+
+ return dateString;
+}
+
++ (NSDate*)dateFromRtmDate:(NSString*)anSqlDate
+{
+ NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
+ [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"];
+ [dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]];
+ NSDate* date = [dateFormatter dateFromString:anSqlDate];
+ [dateFormatter release];
+
+ return date;
+}
+
+- (NSString*)timeline
+{
+ NSDictionary* response = [self dataByCallingMethod:@"rtm.timelines.create" andParameters:[NSDictionary dictionary] withToken:YES];
+
+ if ([self noErrorsInResponse:response])
+ {
+ return [response objectForKey:@"timeline"];
+ }
+ else
+ {
+ return [self errorWithResponse:response];
+ }
+}
+
+- (NSString*)frob
+{
+ NSDictionary* response = [self dataByCallingMethod:@"rtm.auth.getFrob" andParameters:[NSDictionary dictionary]];
+
+ if ([self noErrorsInResponse:response])
+ {
+ return [response objectForKey:@"frob"];
+ }
+ else
+ {
+ return [self errorWithResponse:response];
+ }
+}
+
+- (NSString*)authUrlForPerms:(NSString*)aPerms withFrob:(NSString*)aFrob
+{
+ NSDictionary* parameters = [NSDictionary dictionaryWithObjectsAndKeys:
+ apiKey, @"api_key",
+ aPerms, @"perms",
+ aFrob, @"frob", nil];
+ NSString* parametersString = [self urlParametersWithDictionary:parameters];
+
+ return [NSString stringWithFormat:@"http://www.rememberthemilk.com/services/auth/?%@api_sig=%@",
+ parametersString, [self apiSigFromParameters:parameters]];
+}
+
+- (NSString*)tokenWithFrob:(NSString*)aFrob
+{
+ NSDictionary* parameters = [NSDictionary dictionaryWithObjectsAndKeys:aFrob, @"frob", nil];
+ NSDictionary* response = [self dataByCallingMethod:@"rtm.auth.getToken" andParameters:parameters];
+
+ if ([self noErrorsInResponse:response])
+ {
+ return [[response objectForKey:@"auth"] objectForKey:@"token"];
+ }
+ else
+ {
+ return [self errorWithResponse:response];
+ }
+}
+
+- (BOOL)noErrorsInResponse:(NSDictionary*)anResponse
+{
+ return ([[anResponse objectForKey:@"stat"] compare:@"ok"] == NSOrderedSame);
+}
+
+- (NSString*)errorMsgInResponse:(NSDictionary*)anResponse
+{
+ return [[anResponse objectForKey:@"err"] objectForKey:@"msg"];
+}
+
+- (id)errorWithResponse:(NSDictionary*)anResponse
+{
+ NSLog(@"error: %@", [self errorMsgInResponse:anResponse]);
+
+ return nil;
+}
+
+- (NSDictionary*)dataByCallingMethod:(NSString*)aMethod andParameters:(NSDictionary*)aParameters
+{
+ return [self dataByCallingMethod:aMethod andParameters:aParameters withToken:NO];
+}
+
+- (NSDictionary*)dataByCallingMethod:(NSString*)aMethod andParameters:(NSDictionary*)aParameters withToken:(BOOL)useToken
+{
+ // Checking that last API call was made more than a second ago & if not - waiting for a second (RTM recomendations)
+ if (lastApiCall && (([lastApiCall timeIntervalSinceNow] * -1.0) < 1.0))
+ {
+ [NSThread sleepForTimeInterval:1.0 - ([lastApiCall timeIntervalSinceNow] * -1)];
+ }
+
+ NSURL* url = [NSURL URLWithString:[self urlStringWithMethod:aMethod andParameters:aParameters withToken:useToken]];
+ NSString* response = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
+ [self setLastApiCall:[NSDate date]];
+
+ return [[response JSONValue] objectForKey:@"rsp"];
+}
+
+- (NSString*)urlParametersWithDictionary:(NSDictionary*)aParameters
+{
+ NSMutableString* parametersString = [NSMutableString string];
+ NSArray* keys = [aParameters allKeys];
+
+ for (int i = 0; i < [keys count]; i++)
+ {
+ NSString* key = [NSString stringWithString:[keys objectAtIndex:i]];
+ [parametersString appendFormat:@"%@=%@&", key, [aParameters objectForKey:key]];
+ }
+
+ return [NSString stringWithString:parametersString];
+}
+
+- (NSString*)urlStringWithMethod:(NSString*)aMethod andParameters:(NSDictionary*)aParameters
+{
+ return [self urlStringWithMethod:aMethod andParameters:aParameters withToken:NO];
+}
+
+- (NSString*)urlStringWithMethod:(NSString*)aMethod andParameters:(NSDictionary*)aParameters withToken:(BOOL)useToken
+{
+ NSMutableDictionary* parameters = [[aParameters mutableCopy] autorelease];
+ [parameters setObject:apiKey forKey:@"api_key"];
+ [parameters setObject:aMethod forKey:@"method"];
+ [parameters setObject:@"json" forKey:@"format"];
+ [parameters setObject:[NSString stringWithFormat:@"%d", random()] forKey:@"nocache"];
+ if (useToken)
+ {
+ [parameters setObject:token forKey:@"auth_token"];
+ }
+ NSString* parametersString = [self urlParametersWithDictionary:parameters];
+ NSString* signedParameters = [self apiSigFromParameters:parameters];
+ NSString* url = [[NSString stringWithFormat:@"http://api.rememberthemilk.com/services/rest/?%@api_sig=%@",
+ parametersString, signedParameters] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
+ NSLog(@"%@", url);
+
+ return url;
+}
+
+- (NSString*)apiSigFromParameters:(NSDictionary*)aParameters
+{
+ NSArray* sortedKeys = [[aParameters allKeys] sortedArrayUsingFunction:sortParameterKeys context:nil];
+ NSMutableString* parametersString = [NSMutableString stringWithString:apiSecret];
+
+ for (int i = 0; i < [sortedKeys count]; i++)
+ {
+ NSString* key = [NSString stringWithString:[sortedKeys objectAtIndex:i]];
+ [parametersString appendFormat:@"%@%@", key, [aParameters objectForKey:key]];
+ }
+
+ return [md5(parametersString) lowercaseString];
+}
+
+@end
2 English.lproj/InfoPlist.strings
@@ -0,0 +1,2 @@
+/* Localized versions of Info.plist keys */
+
4,701 English.lproj/MainMenu.xib
4,701 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
50 JSON/JSON.h
@@ -0,0 +1,50 @@
+/*
+ Copyright (C) 2009 Stig Brautaset. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may be used
+ to endorse or promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ @mainpage A strict JSON parser and generator for Objective-C
+
+ JSON (JavaScript Object Notation) is a lightweight data-interchange
+ format. This framework provides two apis for parsing and generating
+ JSON. One standard object-based and a higher level api consisting of
+ categories added to existing Objective-C classes.
+
+ Learn more on the http://code.google.com/p/json-framework project site.
+
+ This framework does its best to be as strict as possible, both in what it
+ accepts and what it generates. For example, it does not support trailing commas
+ in arrays or objects. Nor does it support embedded comments, or
+ anything else not in the JSON specification. This is considered a feature.
+
+*/
+
+#import "SBJSON.h"
+#import "NSObject+SBJSON.h"
+#import "NSString+SBJSON.h"
+
68 JSON/NSObject+SBJSON.h
@@ -0,0 +1,68 @@
+/*
+ Copyright (C) 2009 Stig Brautaset. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may be used
+ to endorse or promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Foundation/Foundation.h>
+
+
+/**
+ @brief Adds JSON generation to Foundation classes
+
+ This is a category on NSObject that adds methods for returning JSON representations
+ of standard objects to the objects themselves. This means you can call the
+ -JSONRepresentation method on an NSArray object and it'll do what you want.
+ */
+@interface NSObject (NSObject_SBJSON)
+
+/**
+ @brief Returns a string containing the receiver encoded as a JSON fragment.
+
+ This method is added as a category on NSObject but is only actually
+ supported for the following objects:
+ @li NSDictionary
+ @li NSArray
+ @li NSString
+ @li NSNumber (also used for booleans)
+ @li NSNull
+
+ @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed.
+ */
+- (NSString *)JSONFragment;
+
+/**
+ @brief Returns a string containing the receiver encoded in JSON.
+
+ This method is added as a category on NSObject but is only actually
+ supported for the following objects:
+ @li NSDictionary
+ @li NSArray
+ */
+- (NSString *)JSONRepresentation;
+
+@end
+
53 JSON/NSObject+SBJSON.m
@@ -0,0 +1,53 @@
+/*
+ Copyright (C) 2009 Stig Brautaset. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may be used
+ to endorse or promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "NSObject+SBJSON.h"
+#import "SBJsonWriter.h"
+
+@implementation NSObject (NSObject_SBJSON)
+
+- (NSString *)JSONFragment {
+ SBJsonWriter *jsonWriter = [SBJsonWriter new];
+ NSString *json = [jsonWriter stringWithFragment:self];
+ if (!json)
+ NSLog(@"-JSONFragment failed. Error trace is: %@", [jsonWriter errorTrace]);
+ [jsonWriter release];
+ return json;
+}
+
+- (NSString *)JSONRepresentation {
+ SBJsonWriter *jsonWriter = [SBJsonWriter new];
+ NSString *json = [jsonWriter stringWithObject:self];
+ if (!json)
+ NSLog(@"-JSONRepresentation failed. Error trace is: %@", [jsonWriter errorTrace]);
+ [jsonWriter release];
+ return json;
+}
+
+@end
58 JSON/NSString+SBJSON.h
@@ -0,0 +1,58 @@
+/*
+ Copyright (C) 2009 Stig Brautaset. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may be used
+ to endorse or promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Foundation/Foundation.h>
+
+/**
+ @brief Adds JSON parsing methods to NSString
+
+This is a category on NSString that adds methods for parsing the target string.
+*/
+@interface NSString (NSString_SBJSON)
+
+
+/**
+ @brief Returns the object represented in the receiver, or nil on error.
+
+ Returns a a scalar object represented by the string's JSON fragment representation.
+
+ @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed.
+ */
+- (id)JSONFragmentValue;
+
+/**
+ @brief Returns the NSDictionary or NSArray represented by the current string's JSON representation.
+
+ Returns the dictionary or array represented in the receiver, or nil on error.
+
+ Returns the NSDictionary or NSArray represented by the current string's JSON representation.
+ */
+- (id)JSONValue;
+
+@end
55 JSON/NSString+SBJSON.m
@@ -0,0 +1,55 @@
+/*
+ Copyright (C) 2007-2009 Stig Brautaset. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may be used
+ to endorse or promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "NSString+SBJSON.h"
+#import "SBJsonParser.h"
+
+@implementation NSString (NSString_SBJSON)
+
+- (id)JSONFragmentValue
+{
+ SBJsonParser *jsonParser = [SBJsonParser new];
+ id repr = [jsonParser fragmentWithString:self];
+ if (!repr)
+ NSLog(@"-JSONFragmentValue failed. Error trace is: %@", [jsonParser errorTrace]);
+ [jsonParser release];
+ return repr;
+}
+
+- (id)JSONValue
+{
+ SBJsonParser *jsonParser = [SBJsonParser new];
+ id repr = [jsonParser objectWithString:self];
+ if (!repr)
+ NSLog(@"-JSONValue failed. Error trace is: %@", [jsonParser errorTrace]);
+ [jsonParser release];
+ return repr;
+}
+
+@end
75 JSON/SBJSON.h
@@ -0,0 +1,75 @@
+/*
+ Copyright (C) 2007-2009 Stig Brautaset. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may be used
+ to endorse or promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Foundation/Foundation.h>
+#import "SBJsonParser.h"
+#import "SBJsonWriter.h"
+
+/**
+ @brief Facade for SBJsonWriter/SBJsonParser.
+
+ Requests are forwarded to instances of SBJsonWriter and SBJsonParser.
+ */
+@interface SBJSON : SBJsonBase <SBJsonParser, SBJsonWriter> {
+
+@private
+ SBJsonParser *jsonParser;
+ SBJsonWriter *jsonWriter;
+}
+
+
+/// Return the fragment represented by the given string
+- (id)fragmentWithString:(NSString*)jsonrep
+ error:(NSError**)error;
+
+/// Return the object represented by the given string
+- (id)objectWithString:(NSString*)jsonrep
+ error:(NSError**)error;
+
+/// Parse the string and return the represented object (or scalar)
+- (id)objectWithString:(id)value
+ allowScalar:(BOOL)x
+ error:(NSError**)error;
+
+
+/// Return JSON representation of an array or dictionary
+- (NSString*)stringWithObject:(id)value
+ error:(NSError**)error;
+
+/// Return JSON representation of any legal JSON value
+- (NSString*)stringWithFragment:(id)value
+ error:(NSError**)error;
+
+/// Return JSON representation (or fragment) for the given object
+- (NSString*)stringWithObject:(id)value
+ allowScalar:(BOOL)x
+ error:(NSError**)error;
+
+
+@end
212 JSON/SBJSON.m
@@ -0,0 +1,212 @@
+/*
+ Copyright (C) 2007-2009 Stig Brautaset. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may be used
+ to endorse or promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "SBJSON.h"
+
+@implementation SBJSON
+
+- (id)init {
+ self = [super init];
+ if (self) {
+ jsonWriter = [SBJsonWriter new];
+ jsonParser = [SBJsonParser new];
+ [self setMaxDepth:512];
+
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [jsonWriter release];
+ [jsonParser release];
+ [super dealloc];
+}
+
+#pragma mark Writer
+
+
+- (NSString *)stringWithObject:(id)obj {
+ NSString *repr = [jsonWriter stringWithObject:obj];
+ if (repr)
+ return repr;
+
+ [errorTrace release];
+ errorTrace = [[jsonWriter errorTrace] mutableCopy];
+ return nil;
+}
+
+/**
+ Returns a string containing JSON representation of the passed in value, or nil on error.
+ If nil is returned and @p error is not NULL, @p *error can be interrogated to find the cause of the error.
+
+ @param value any instance that can be represented as a JSON fragment
+ @param allowScalar wether to return json fragments for scalar objects
+ @param error used to return an error by reference (pass NULL if this is not desired)
+
+@deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed.
+ */
+- (NSString*)stringWithObject:(id)value allowScalar:(BOOL)allowScalar error:(NSError**)error {
+
+ NSString *json = allowScalar ? [jsonWriter stringWithFragment:value] : [jsonWriter stringWithObject:value];
+ if (json)
+ return json;
+
+ [errorTrace release];
+ errorTrace = [[jsonWriter errorTrace] mutableCopy];
+
+ if (error)
+ *error = [errorTrace lastObject];
+ return nil;
+}
+
+/**
+ Returns a string containing JSON representation of the passed in value, or nil on error.
+ If nil is returned and @p error is not NULL, @p error can be interrogated to find the cause of the error.
+
+ @param value any instance that can be represented as a JSON fragment
+ @param error used to return an error by reference (pass NULL if this is not desired)
+
+ @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed.
+ */
+- (NSString*)stringWithFragment:(id)value error:(NSError**)error {
+ return [self stringWithObject:value
+ allowScalar:YES
+ error:error];
+}
+
+/**
+ Returns a string containing JSON representation of the passed in value, or nil on error.
+ If nil is returned and @p error is not NULL, @p error can be interrogated to find the cause of the error.
+
+ @param value a NSDictionary or NSArray instance
+ @param error used to return an error by reference (pass NULL if this is not desired)
+ */
+- (NSString*)stringWithObject:(id)value error:(NSError**)error {
+ return [self stringWithObject:value
+ allowScalar:NO
+ error:error];
+}
+
+#pragma mark Parsing
+
+- (id)objectWithString:(NSString *)repr {
+ id obj = [jsonParser objectWithString:repr];
+ if (obj)
+ return obj;
+
+ [errorTrace release];
+ errorTrace = [[jsonParser errorTrace] mutableCopy];
+
+ return nil;
+}
+
+/**
+ Returns the object represented by the passed-in string or nil on error. The returned object can be
+ a string, number, boolean, null, array or dictionary.
+
+ @param value the json string to parse
+ @param allowScalar whether to return objects for JSON fragments
+ @param error used to return an error by reference (pass NULL if this is not desired)
+
+ @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed.
+ */
+- (id)objectWithString:(id)value allowScalar:(BOOL)allowScalar error:(NSError**)error {
+
+ id obj = allowScalar ? [jsonParser fragmentWithString:value] : [jsonParser objectWithString:value];
+ if (obj)
+ return obj;
+
+ [errorTrace release];
+ errorTrace = [[jsonParser errorTrace] mutableCopy];
+
+ if (error)
+ *error = [errorTrace lastObject];
+ return nil;
+}
+
+/**
+ Returns the object represented by the passed-in string or nil on error. The returned object can be
+ a string, number, boolean, null, array or dictionary.
+
+ @param repr the json string to parse
+ @param error used to return an error by reference (pass NULL if this is not desired)
+
+ @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed.
+ */
+- (id)fragmentWithString:(NSString*)repr error:(NSError**)error {
+ return [self objectWithString:repr
+ allowScalar:YES
+ error:error];
+}
+
+/**
+ Returns the object represented by the passed-in string or nil on error. The returned object
+ will be either a dictionary or an array.
+
+ @param repr the json string to parse
+ @param error used to return an error by reference (pass NULL if this is not desired)
+ */
+- (id)objectWithString:(NSString*)repr error:(NSError**)error {
+ return [self objectWithString:repr
+ allowScalar:NO
+ error:error];
+}
+
+
+
+#pragma mark Properties - parsing
+
+- (NSUInteger)maxDepth {
+ return jsonParser.maxDepth;
+}
+
+- (void)setMaxDepth:(NSUInteger)d {
+ jsonWriter.maxDepth = jsonParser.maxDepth = d;
+}
+
+
+#pragma mark Properties - writing
+
+- (BOOL)humanReadable {
+ return jsonWriter.humanReadable;
+}
+
+- (void)setHumanReadable:(BOOL)x {
+ jsonWriter.humanReadable = x;
+}
+
+- (BOOL)sortKeys {
+ return jsonWriter.sortKeys;
+}
+
+- (void)setSortKeys:(BOOL)x {
+ jsonWriter.sortKeys = x;
+}
+
+@end
86 JSON/SBJsonBase.h
@@ -0,0 +1,86 @@
+/*
+ Copyright (C) 2009 Stig Brautaset. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may be used
+ to endorse or promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Foundation/Foundation.h>
+
+extern NSString * SBJSONErrorDomain;
+
+
+enum {
+ EUNSUPPORTED = 1,
+ EPARSENUM,
+ EPARSE,
+ EFRAGMENT,
+ ECTRL,
+ EUNICODE,
+ EDEPTH,
+ EESCAPE,
+ ETRAILCOMMA,
+ ETRAILGARBAGE,
+ EEOF,
+ EINPUT
+};
+
+/**
+ @brief Common base class for parsing & writing.
+
+ This class contains the common error-handling code and option between the parser/writer.
+ */
+@interface SBJsonBase : NSObject {
+ NSMutableArray *errorTrace;
+
+@protected
+ NSUInteger depth, maxDepth;
+}
+
+/**
+ @brief The maximum recursing depth.
+
+ Defaults to 512. If the input is nested deeper than this the input will be deemed to be
+ malicious and the parser returns nil, signalling an error. ("Nested too deep".) You can
+ turn off this security feature by setting the maxDepth value to 0.
+ */
+@property NSUInteger maxDepth;
+
+/**
+ @brief Return an error trace, or nil if there was no errors.
+
+ Note that this method returns the trace of the last method that failed.
+ You need to check the return value of the call you're making to figure out
+ if the call actually failed, before you know call this method.
+ */
+ @property(copy,readonly) NSArray* errorTrace;
+
+/// @internal for use in subclasses to add errors to the stack trace
+- (void)addErrorWithCode:(NSUInteger)code description:(NSString*)str;
+
+/// @internal for use in subclasess to clear the error before a new parsing attempt
+- (void)clearErrorTrace;
+
+@end
78 JSON/SBJsonBase.m
@@ -0,0 +1,78 @@
+/*
+ Copyright (C) 2009 Stig Brautaset. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may be used
+ to endorse or promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "SBJsonBase.h"
+NSString * SBJSONErrorDomain = @"org.brautaset.JSON.ErrorDomain";
+
+
+@implementation SBJsonBase
+
+@synthesize errorTrace;
+@synthesize maxDepth;
+
+- (id)init {
+ self = [super init];
+ if (self)
+ self.maxDepth = 512;
+ return self;
+}
+
+- (void)dealloc {
+ [errorTrace release];
+ [super dealloc];
+}
+
+- (void)addErrorWithCode:(NSUInteger)code description:(NSString*)str {
+ NSDictionary *userInfo;
+ if (!errorTrace) {
+ errorTrace = [NSMutableArray new];
+ userInfo = [NSDictionary dictionaryWithObject:str forKey:NSLocalizedDescriptionKey];
+
+ } else {
+ userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
+ str, NSLocalizedDescriptionKey,
+ [errorTrace lastObject], NSUnderlyingErrorKey,
+ nil];
+ }
+
+ NSError *error = [NSError errorWithDomain:SBJSONErrorDomain code:code userInfo:userInfo];
+
+ [self willChangeValueForKey:@"errorTrace"];
+ [errorTrace addObject:error];
+ [self didChangeValueForKey:@"errorTrace"];
+}
+
+- (void)clearErrorTrace {
+ [self willChangeValueForKey:@"errorTrace"];
+ [errorTrace release];
+ errorTrace = nil;
+ [self didChangeValueForKey:@"errorTrace"];
+}
+
+@end
87 JSON/SBJsonParser.h
@@ -0,0 +1,87 @@
+/*
+ Copyright (C) 2009 Stig Brautaset. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may be used
+ to endorse or promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <Foundation/Foundation.h>
+#import "SBJsonBase.h"
+
+/**
+ @brief Options for the parser class.
+
+ This exists so the SBJSON facade can implement the options in the parser without having to re-declare them.
+ */
+@protocol SBJsonParser
+
+/**
+ @brief Return the object represented by the given string.
+
+ Returns the object represented by the passed-in string or nil on error. The returned object can be
+ a string, number, boolean, null, array or dictionary.
+
+ @param repr the json string to parse
+ */
+- (id)objectWithString:(NSString *)repr;
+
+@end
+
+
+/**
+ @brief The JSON parser class.
+
+ JSON is mapped to Objective-C types in the following way:
+
+ @li Null -> NSNull
+ @li String -> NSMutableString
+ @li Array -> NSMutableArray
+ @li Object -> NSMutableDictionary
+ @li Boolean -> NSNumber (initialised with -initWithBool:)
+ @li Number -> NSDecimalNumber
+
+ Since Objective-C doesn't have a dedicated class for boolean values, these turns into NSNumber
+ instances. These are initialised with the -initWithBool: method, and
+ round-trip back to JSON properly. (They won't silently suddenly become 0 or 1; they'll be
+ represented as 'true' and 'false' again.)
+
+ JSON numbers turn into NSDecimalNumber instances,
+ as we can thus avoid any loss of precision. (JSON allows ridiculously large numbers.)
+
+ */
+@interface SBJsonParser : SBJsonBase <SBJsonParser> {
+
+@private
+ const char *c;
+}
+
+@end
+
+// don't use - exists for backwards compatibility with 2.1.x only. Will be removed in 2.3.
+@interface SBJsonParser (Private)
+- (id)fragmentWithString:(id)repr;
+@end
+
+
475 JSON/SBJsonParser.m
@@ -0,0 +1,475 @@
+/*
+ Copyright (C) 2009 Stig Brautaset. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of the author nor the names of its contributors may be used
+ to endorse or promote products derived from this software without specific
+ prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "SBJsonParser.h"
+
+@interface SBJsonParser ()
+
+- (BOOL)scanValue:(NSObject **)o;
+
+- (BOOL)scanRestOfArray:(NSMutableArray **)o;
+- (BOOL)scanRestOfDictionary:(NSMutableDictionary **)o;
+- (BOOL)scanRestOfNull:(NSNull **)o;
+- (BOOL)scanRestOfFalse:(NSNumber **)o;
+- (BOOL)scanRestOfTrue:(NSNumber **)o;
+- (BOOL)scanRestOfString:(NSMutableString **)o;
+
+// Cannot manage without looking at the first digit
+- (BOOL)scanNumber:(NSNumber **)o;
+
+- (BOOL)scanHexQuad:(unichar *)x;
+- (BOOL)scanUnicodeChar:(unichar *)x;
+
+- (BOOL)scanIsAtEnd;
+
+@end
+
+#define skipWhitespace(c) while (isspace(*c)) c++
+#define skipDigits(c) while (isdigit(*c)) c++
+
+
+@implementation SBJsonParser
+
+static char ctrl[0x22];
+
++ (void)initialize
+{
+ ctrl[0] = '\"';
+ ctrl[1] = '\\';
+ for (int i = 1; i < 0x20; i++)
+ ctrl[i+1] = i;
+ ctrl[0x21] = 0;
+}
+
+/**
+ @deprecated This exists in order to provide fragment support in older APIs in one more version.
+ It should be removed in the next major version.
+ */
+- (id)fragmentWithString:(id)repr {
+ [self clearErrorTrace];
+
+ if (!repr) {
+ [self addErrorWithCode:EINPUT description:@"Input was 'nil'"];
+ return nil;
+ }
+
+ depth = 0;
+ c = [repr UTF8String];
+
+ id o;
+ if (![self scanValue:&o]) {
+ return nil;
+ }
+
+ // We found some valid JSON. But did it also contain something else?
+ if (![self scanIsAtEnd]) {
+ [self addErrorWithCode:ETRAILGARBAGE description:@"Garbage after JSON"];
+ return nil;
+ }
+
+ NSAssert1(o, @"Should have a valid object from %@", repr);
+ return o;
+}
+
+- (id)objectWithString:(NSString *)repr {
+
+ id o = [self fragmentWithString:repr];
+ if (!o)
+ return nil;
+
+ // Check that the object we've found is a valid JSON container.
+ if (![o isKindOfClass:[NSDictionary class]] && ![o isKindOfClass:[NSArray class]]) {
+ [self addErrorWithCode:EFRAGMENT description:@"Valid fragment, but not JSON"];
+ return nil;
+ }
+
+ return o;
+}
+
+/*
+ In contrast to the public methods, it is an error to omit the error parameter here.
+ */
+- (BOOL)scanValue:(NSObject **)o
+{
+ skipWhitespace(c);
+
+ switch (*c++) {
+ case '{':
+ return [self scanRestOfDictionary:(NSMutableDictionary **)o];
+ break;
+ case '[':
+ return [self scanRestOfArray:(NSMutableArray **)o];
+ break;
+ case '"':
+ return [self scanRestOfString:(NSMutableString **)o];
+ break;
+ case 'f':
+ return [self scanRestOfFalse:(NSNumber **)o];
+ break;
+ case 't':
+ return [self scanRestOfTrue:(NSNumber **)o];
+ break;
+ case 'n':
+ return [self scanRestOfNull:(NSNull **)o];
+ break;
+ case '-':
+ case '0'...'9':
+ c--; // cannot verify number correctly without the first character
+ return [self scanNumber:(NSNumber **)o];
+ break;
+ case '+':
+ [self addErrorWithCode:EPARSENUM description: @"Leading + disallowed in number"];
+ return NO;
+ break;
+ case 0x0:
+ [self addErrorWithCode:EEOF description:@"Unexpected end of string"];
+ return NO;
+ break;
+ default:
+ [self addErrorWithCode:EPARSE description: @"Unrecognised leading character"];
+ return NO;
+ break;
+ }
+
+ NSAssert(0, @"Should never get here");
+ return NO;
+}
+
+- (BOOL)scanRestOfTrue:(NSNumber **)o
+{
+ if (!strncmp(c, "rue", 3)) {
+ c += 3;
+ *o = [NSNumber numberWithBool:YES];
+ return YES;
+ }
+ [self addErrorWithCode:EPARSE description:@"Expected 'true'"];
+ return NO;
+}
+
+- (BOOL)scanRestOfFalse:(NSNumber **)o
+{
+ if (!strncmp(c, "alse", 4)) {
+ c += 4;
+ *o = [NSNumber numberWithBool:NO];
+ return YES;
+ }
+ [self addErrorWithCode:EPARSE description: @"Expected 'false'"];
+ return NO;
+}
+
+- (BOOL)scanRestOfNull:(NSNull **)o {
+ if (!strncmp(c, "ull", 3)) {
+ c += 3;
+ *o = [NSNull null];
+ return YES;
+ }
+ [self addErrorWithCode:EPARSE description: @"Expected 'null'"];
+ return NO;
+}
+
+- (BOOL)scanRestOfArray:(NSMutableArray **)o {
+ if (maxDepth && ++depth > maxDepth) {
+ [self addErrorWithCode:EDEPTH description: @"Nested too deep"];
+ return NO;
+ }
+
+ *o = [NSMutableArray arrayWithCapacity:8];
+
+ for (; *c ;) {
+ id v;
+
+ skipWhitespace(c);
+ if (*c == ']' && c++) {
+ depth--;
+ return YES;
+ }
+
+ if (![self scanValue:&v]) {
+ [self addErrorWithCode:EPARSE description:@"Expected value while parsing array"];
+ return NO;
+ }
+
+ [*o addObject:v];
+
+ skipWhitespace(c);
+ if (*c == ',' && c++) {
+ skipWhitespace(c);
+ if (*c == ']') {
+ [self addErrorWithCode:ETRAILCOMMA description: @"Trailing comma disallowed in array"];
+ return NO;
+ }
+ }
+ }
+
+ [self addErrorWithCode:EEOF description: @"End of input while parsing array"];
+ return NO;
+}
+
+- (BOOL)scanRestOfDictionary:(NSMutableDictionary **)o
+{
+ if (maxDepth && ++depth > maxDepth) {
+ [self addErrorWithCode:EDEPTH description: @"Nested too deep"];
+ return NO;
+ }
+
+ *o = [NSMutableDictionary dictionaryWithCapacity:7];