├── .gitignore ├── Examples └── BasicRequests │ ├── .gitignore │ ├── AccountInfo.template.h │ ├── BasicRequests-Prefix.pch │ ├── BasicRequests.xcodeproj │ └── project.pbxproj │ ├── BasicRequestsDemo.h │ ├── BasicRequestsDemo.m │ ├── RequestOperation.h │ ├── RequestOperation.m │ └── main.m ├── README.markdown └── Source ├── BKAPIContext+ProtectedMethods.h ├── BKAPIContext.h ├── BKAPIContext.m ├── BKAreaListRequest.h ├── BKAreaListRequest.m ├── BKCheckVersionRequest.h ├── BKCheckVersionRequest.m ├── BKEditCaseRequest.h ├── BKEditCaseRequest.m ├── BKError.h ├── BKError.m ├── BKListRequest.h ├── BKListRequest.m ├── BKListWorkingScheduleRequest.h ├── BKListWorkingScheduleRequest.m ├── BKLogOffRequest.h ├── BKLogOffRequest.m ├── BKLogOnRequest.h ├── BKLogOnRequest.m ├── BKMailRequest.h ├── BKMailRequest.m ├── BKMarkAsViewedRequest.h ├── BKMarkAsViewedRequest.m ├── BKPrivateUtilities.h ├── BKQueryCaseRequest.h ├── BKQueryCaseRequest.m ├── BKQueryEventRequest.h ├── BKQueryEventRequest.m ├── BKRequest.h ├── BKRequest.m ├── BKRequestOperation.h ├── BKRequestOperation.m ├── BKSetCurrentFilterRequest.h ├── BKSetCurrentFilterRequest.m ├── BKXMLMapper.h ├── BKXMLMapper.m └── BugzKit.h /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | *.pbxuser 3 | *.mode1v3 4 | *.tm_build_errors 5 | .DS_Store 6 | project.xcworkspace 7 | xcuserdata 8 | -------------------------------------------------------------------------------- /Examples/BasicRequests/.gitignore: -------------------------------------------------------------------------------- 1 | AccountInfo.h 2 | -------------------------------------------------------------------------------- /Examples/BasicRequests/AccountInfo.template.h: -------------------------------------------------------------------------------- 1 | // 2 | // AccountInfo.template.h 3 | // 4 | // Copyright (c) 2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | // copy this file to AccountInfo.h and furnish your account info 29 | // REMEMBER DO NOT CHECK IN THE REAL FILE INTO YOUR SOURCE REPOSITORY 30 | 31 | #define DEMO_ENDPOINT_STRING @"https://someacmecompany.fogbugz.com" 32 | #define DEMO_USER_NAME @"janedoe@example.com" 33 | #define DEMO_USER_PASSWORD @"" 34 | -------------------------------------------------------------------------------- /Examples/BasicRequests/BasicRequests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // BasicRequests-Prefix.pch 3 | // 4 | // Copyright (c) 2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #ifdef __OBJC__ 29 | #import 30 | #endif 31 | -------------------------------------------------------------------------------- /Examples/BasicRequests/BasicRequests.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6A77314C131DDD1B0081015A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6A77314B131DDD1B0081015A /* Foundation.framework */; }; 11 | 6A773158131DDD880081015A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A773157131DDD880081015A /* main.m */; }; 12 | 6A77315C131DDDFC0081015A /* RequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A77315B131DDDFC0081015A /* RequestOperation.m */; }; 13 | 6A773184131DE2190081015A /* BKAPIContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A773161131DE2190081015A /* BKAPIContext.m */; }; 14 | 6A773185131DE2190081015A /* BKAreaListRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A773163131DE2190081015A /* BKAreaListRequest.m */; }; 15 | 6A773186131DE2190081015A /* BKCheckVersionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A773165131DE2190081015A /* BKCheckVersionRequest.m */; }; 16 | 6A773187131DE2190081015A /* BKEditCaseRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A773167131DE2190081015A /* BKEditCaseRequest.m */; }; 17 | 6A773188131DE2190081015A /* BKError.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A773169131DE2190081015A /* BKError.m */; }; 18 | 6A773189131DE2190081015A /* BKListRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A77316B131DE2190081015A /* BKListRequest.m */; }; 19 | 6A77318A131DE2190081015A /* BKListWorkingScheduleRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A77316D131DE2190081015A /* BKListWorkingScheduleRequest.m */; }; 20 | 6A77318B131DE2190081015A /* BKLogOffRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A77316F131DE2190081015A /* BKLogOffRequest.m */; }; 21 | 6A77318C131DE2190081015A /* BKLogOnRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A773171131DE2190081015A /* BKLogOnRequest.m */; }; 22 | 6A77318D131DE2190081015A /* BKMailRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A773173131DE2190081015A /* BKMailRequest.m */; }; 23 | 6A77318E131DE2190081015A /* BKMarkAsViewedRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A773175131DE2190081015A /* BKMarkAsViewedRequest.m */; }; 24 | 6A77318F131DE2190081015A /* BKQueryCaseRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A773178131DE2190081015A /* BKQueryCaseRequest.m */; }; 25 | 6A773190131DE2190081015A /* BKQueryEventRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A77317A131DE2190081015A /* BKQueryEventRequest.m */; }; 26 | 6A773191131DE2190081015A /* BKRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A77317C131DE2190081015A /* BKRequest.m */; }; 27 | 6A773192131DE2190081015A /* BKRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A77317E131DE2190081015A /* BKRequestOperation.m */; }; 28 | 6A773193131DE2190081015A /* BKSetCurrentFilterRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A773180131DE2190081015A /* BKSetCurrentFilterRequest.m */; }; 29 | 6A773194131DE2190081015A /* BKXMLMapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A773182131DE2190081015A /* BKXMLMapper.m */; }; 30 | 6A7731A8131DF0A30081015A /* BasicRequestsDemo.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A7731A7131DF0A30081015A /* BasicRequestsDemo.m */; }; 31 | /* End PBXBuildFile section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | 6A773147131DDD1B0081015A /* BasicRequests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = BasicRequests; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | 6A77314B131DDD1B0081015A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 36 | 6A773156131DDD880081015A /* BasicRequests-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "BasicRequests-Prefix.pch"; sourceTree = ""; }; 37 | 6A773157131DDD880081015A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 38 | 6A77315A131DDDFC0081015A /* RequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RequestOperation.h; sourceTree = ""; }; 39 | 6A77315B131DDDFC0081015A /* RequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RequestOperation.m; sourceTree = ""; }; 40 | 6A77315F131DE2190081015A /* BKAPIContext+ProtectedMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "BKAPIContext+ProtectedMethods.h"; sourceTree = ""; }; 41 | 6A773160131DE2190081015A /* BKAPIContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKAPIContext.h; sourceTree = ""; }; 42 | 6A773161131DE2190081015A /* BKAPIContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BKAPIContext.m; sourceTree = ""; }; 43 | 6A773162131DE2190081015A /* BKAreaListRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKAreaListRequest.h; sourceTree = ""; }; 44 | 6A773163131DE2190081015A /* BKAreaListRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BKAreaListRequest.m; sourceTree = ""; }; 45 | 6A773164131DE2190081015A /* BKCheckVersionRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKCheckVersionRequest.h; sourceTree = ""; }; 46 | 6A773165131DE2190081015A /* BKCheckVersionRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BKCheckVersionRequest.m; sourceTree = ""; }; 47 | 6A773166131DE2190081015A /* BKEditCaseRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKEditCaseRequest.h; sourceTree = ""; }; 48 | 6A773167131DE2190081015A /* BKEditCaseRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BKEditCaseRequest.m; sourceTree = ""; }; 49 | 6A773168131DE2190081015A /* BKError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKError.h; sourceTree = ""; }; 50 | 6A773169131DE2190081015A /* BKError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BKError.m; sourceTree = ""; }; 51 | 6A77316A131DE2190081015A /* BKListRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKListRequest.h; sourceTree = ""; }; 52 | 6A77316B131DE2190081015A /* BKListRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BKListRequest.m; sourceTree = ""; }; 53 | 6A77316C131DE2190081015A /* BKListWorkingScheduleRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKListWorkingScheduleRequest.h; sourceTree = ""; }; 54 | 6A77316D131DE2190081015A /* BKListWorkingScheduleRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BKListWorkingScheduleRequest.m; sourceTree = ""; }; 55 | 6A77316E131DE2190081015A /* BKLogOffRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKLogOffRequest.h; sourceTree = ""; }; 56 | 6A77316F131DE2190081015A /* BKLogOffRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BKLogOffRequest.m; sourceTree = ""; }; 57 | 6A773170131DE2190081015A /* BKLogOnRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKLogOnRequest.h; sourceTree = ""; }; 58 | 6A773171131DE2190081015A /* BKLogOnRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BKLogOnRequest.m; sourceTree = ""; }; 59 | 6A773172131DE2190081015A /* BKMailRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKMailRequest.h; sourceTree = ""; }; 60 | 6A773173131DE2190081015A /* BKMailRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BKMailRequest.m; sourceTree = ""; }; 61 | 6A773174131DE2190081015A /* BKMarkAsViewedRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKMarkAsViewedRequest.h; sourceTree = ""; }; 62 | 6A773175131DE2190081015A /* BKMarkAsViewedRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BKMarkAsViewedRequest.m; sourceTree = ""; }; 63 | 6A773176131DE2190081015A /* BKPrivateUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKPrivateUtilities.h; sourceTree = ""; }; 64 | 6A773177131DE2190081015A /* BKQueryCaseRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKQueryCaseRequest.h; sourceTree = ""; }; 65 | 6A773178131DE2190081015A /* BKQueryCaseRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BKQueryCaseRequest.m; sourceTree = ""; }; 66 | 6A773179131DE2190081015A /* BKQueryEventRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKQueryEventRequest.h; sourceTree = ""; }; 67 | 6A77317A131DE2190081015A /* BKQueryEventRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BKQueryEventRequest.m; sourceTree = ""; }; 68 | 6A77317B131DE2190081015A /* BKRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKRequest.h; sourceTree = ""; }; 69 | 6A77317C131DE2190081015A /* BKRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BKRequest.m; sourceTree = ""; }; 70 | 6A77317D131DE2190081015A /* BKRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKRequestOperation.h; sourceTree = ""; }; 71 | 6A77317E131DE2190081015A /* BKRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BKRequestOperation.m; sourceTree = ""; }; 72 | 6A77317F131DE2190081015A /* BKSetCurrentFilterRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKSetCurrentFilterRequest.h; sourceTree = ""; }; 73 | 6A773180131DE2190081015A /* BKSetCurrentFilterRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BKSetCurrentFilterRequest.m; sourceTree = ""; }; 74 | 6A773181131DE2190081015A /* BKXMLMapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BKXMLMapper.h; sourceTree = ""; }; 75 | 6A773182131DE2190081015A /* BKXMLMapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BKXMLMapper.m; sourceTree = ""; }; 76 | 6A773183131DE2190081015A /* BugzKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BugzKit.h; sourceTree = ""; }; 77 | 6A7731A5131DEE8E0081015A /* AccountInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccountInfo.h; sourceTree = ""; }; 78 | 6A7731A6131DF0A30081015A /* BasicRequestsDemo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BasicRequestsDemo.h; sourceTree = ""; }; 79 | 6A7731A7131DF0A30081015A /* BasicRequestsDemo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BasicRequestsDemo.m; sourceTree = ""; }; 80 | /* End PBXFileReference section */ 81 | 82 | /* Begin PBXFrameworksBuildPhase section */ 83 | 6A773144131DDD1B0081015A /* Frameworks */ = { 84 | isa = PBXFrameworksBuildPhase; 85 | buildActionMask = 2147483647; 86 | files = ( 87 | 6A77314C131DDD1B0081015A /* Foundation.framework in Frameworks */, 88 | ); 89 | runOnlyForDeploymentPostprocessing = 0; 90 | }; 91 | /* End PBXFrameworksBuildPhase section */ 92 | 93 | /* Begin PBXGroup section */ 94 | 6A77313A131DDD140081015A = { 95 | isa = PBXGroup; 96 | children = ( 97 | 6A7731A5131DEE8E0081015A /* AccountInfo.h */, 98 | 6A7731A6131DF0A30081015A /* BasicRequestsDemo.h */, 99 | 6A7731A7131DF0A30081015A /* BasicRequestsDemo.m */, 100 | 6A773156131DDD880081015A /* BasicRequests-Prefix.pch */, 101 | 6A77315A131DDDFC0081015A /* RequestOperation.h */, 102 | 6A77315B131DDDFC0081015A /* RequestOperation.m */, 103 | 6A773157131DDD880081015A /* main.m */, 104 | 6A77315E131DE2190081015A /* BugzKit */, 105 | 6A77314A131DDD1B0081015A /* Frameworks */, 106 | 6A773148131DDD1B0081015A /* Products */, 107 | ); 108 | sourceTree = ""; 109 | }; 110 | 6A773148131DDD1B0081015A /* Products */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 6A773147131DDD1B0081015A /* BasicRequests */, 114 | ); 115 | name = Products; 116 | sourceTree = ""; 117 | }; 118 | 6A77314A131DDD1B0081015A /* Frameworks */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 6A77314B131DDD1B0081015A /* Foundation.framework */, 122 | ); 123 | name = Frameworks; 124 | sourceTree = ""; 125 | }; 126 | 6A77315E131DE2190081015A /* BugzKit */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 6A77315F131DE2190081015A /* BKAPIContext+ProtectedMethods.h */, 130 | 6A773160131DE2190081015A /* BKAPIContext.h */, 131 | 6A773161131DE2190081015A /* BKAPIContext.m */, 132 | 6A773162131DE2190081015A /* BKAreaListRequest.h */, 133 | 6A773163131DE2190081015A /* BKAreaListRequest.m */, 134 | 6A773164131DE2190081015A /* BKCheckVersionRequest.h */, 135 | 6A773165131DE2190081015A /* BKCheckVersionRequest.m */, 136 | 6A773166131DE2190081015A /* BKEditCaseRequest.h */, 137 | 6A773167131DE2190081015A /* BKEditCaseRequest.m */, 138 | 6A773168131DE2190081015A /* BKError.h */, 139 | 6A773169131DE2190081015A /* BKError.m */, 140 | 6A77316A131DE2190081015A /* BKListRequest.h */, 141 | 6A77316B131DE2190081015A /* BKListRequest.m */, 142 | 6A77316C131DE2190081015A /* BKListWorkingScheduleRequest.h */, 143 | 6A77316D131DE2190081015A /* BKListWorkingScheduleRequest.m */, 144 | 6A77316E131DE2190081015A /* BKLogOffRequest.h */, 145 | 6A77316F131DE2190081015A /* BKLogOffRequest.m */, 146 | 6A773170131DE2190081015A /* BKLogOnRequest.h */, 147 | 6A773171131DE2190081015A /* BKLogOnRequest.m */, 148 | 6A773172131DE2190081015A /* BKMailRequest.h */, 149 | 6A773173131DE2190081015A /* BKMailRequest.m */, 150 | 6A773174131DE2190081015A /* BKMarkAsViewedRequest.h */, 151 | 6A773175131DE2190081015A /* BKMarkAsViewedRequest.m */, 152 | 6A773176131DE2190081015A /* BKPrivateUtilities.h */, 153 | 6A773177131DE2190081015A /* BKQueryCaseRequest.h */, 154 | 6A773178131DE2190081015A /* BKQueryCaseRequest.m */, 155 | 6A773179131DE2190081015A /* BKQueryEventRequest.h */, 156 | 6A77317A131DE2190081015A /* BKQueryEventRequest.m */, 157 | 6A77317B131DE2190081015A /* BKRequest.h */, 158 | 6A77317C131DE2190081015A /* BKRequest.m */, 159 | 6A77317D131DE2190081015A /* BKRequestOperation.h */, 160 | 6A77317E131DE2190081015A /* BKRequestOperation.m */, 161 | 6A77317F131DE2190081015A /* BKSetCurrentFilterRequest.h */, 162 | 6A773180131DE2190081015A /* BKSetCurrentFilterRequest.m */, 163 | 6A773181131DE2190081015A /* BKXMLMapper.h */, 164 | 6A773182131DE2190081015A /* BKXMLMapper.m */, 165 | 6A773183131DE2190081015A /* BugzKit.h */, 166 | ); 167 | name = BugzKit; 168 | path = ../../Source; 169 | sourceTree = ""; 170 | }; 171 | /* End PBXGroup section */ 172 | 173 | /* Begin PBXNativeTarget section */ 174 | 6A773146131DDD1B0081015A /* BasicRequests */ = { 175 | isa = PBXNativeTarget; 176 | buildConfigurationList = 6A773153131DDD1B0081015A /* Build configuration list for PBXNativeTarget "BasicRequests" */; 177 | buildPhases = ( 178 | 6A773143131DDD1B0081015A /* Sources */, 179 | 6A773144131DDD1B0081015A /* Frameworks */, 180 | ); 181 | buildRules = ( 182 | ); 183 | dependencies = ( 184 | ); 185 | name = BasicRequests; 186 | productName = BasicRequests; 187 | productReference = 6A773147131DDD1B0081015A /* BasicRequests */; 188 | productType = "com.apple.product-type.tool"; 189 | }; 190 | /* End PBXNativeTarget section */ 191 | 192 | /* Begin PBXProject section */ 193 | 6A77313C131DDD140081015A /* Project object */ = { 194 | isa = PBXProject; 195 | buildConfigurationList = 6A77313F131DDD140081015A /* Build configuration list for PBXProject "BasicRequests" */; 196 | compatibilityVersion = "Xcode 3.2"; 197 | developmentRegion = English; 198 | hasScannedForEncodings = 0; 199 | knownRegions = ( 200 | en, 201 | ); 202 | mainGroup = 6A77313A131DDD140081015A; 203 | productRefGroup = 6A773148131DDD1B0081015A /* Products */; 204 | projectDirPath = ""; 205 | projectRoot = ""; 206 | targets = ( 207 | 6A773146131DDD1B0081015A /* BasicRequests */, 208 | ); 209 | }; 210 | /* End PBXProject section */ 211 | 212 | /* Begin PBXSourcesBuildPhase section */ 213 | 6A773143131DDD1B0081015A /* Sources */ = { 214 | isa = PBXSourcesBuildPhase; 215 | buildActionMask = 2147483647; 216 | files = ( 217 | 6A773158131DDD880081015A /* main.m in Sources */, 218 | 6A77315C131DDDFC0081015A /* RequestOperation.m in Sources */, 219 | 6A773184131DE2190081015A /* BKAPIContext.m in Sources */, 220 | 6A773185131DE2190081015A /* BKAreaListRequest.m in Sources */, 221 | 6A773186131DE2190081015A /* BKCheckVersionRequest.m in Sources */, 222 | 6A773187131DE2190081015A /* BKEditCaseRequest.m in Sources */, 223 | 6A773188131DE2190081015A /* BKError.m in Sources */, 224 | 6A773189131DE2190081015A /* BKListRequest.m in Sources */, 225 | 6A77318A131DE2190081015A /* BKListWorkingScheduleRequest.m in Sources */, 226 | 6A77318B131DE2190081015A /* BKLogOffRequest.m in Sources */, 227 | 6A77318C131DE2190081015A /* BKLogOnRequest.m in Sources */, 228 | 6A77318D131DE2190081015A /* BKMailRequest.m in Sources */, 229 | 6A77318E131DE2190081015A /* BKMarkAsViewedRequest.m in Sources */, 230 | 6A77318F131DE2190081015A /* BKQueryCaseRequest.m in Sources */, 231 | 6A773190131DE2190081015A /* BKQueryEventRequest.m in Sources */, 232 | 6A773191131DE2190081015A /* BKRequest.m in Sources */, 233 | 6A773192131DE2190081015A /* BKRequestOperation.m in Sources */, 234 | 6A773193131DE2190081015A /* BKSetCurrentFilterRequest.m in Sources */, 235 | 6A773194131DE2190081015A /* BKXMLMapper.m in Sources */, 236 | 6A7731A8131DF0A30081015A /* BasicRequestsDemo.m in Sources */, 237 | ); 238 | runOnlyForDeploymentPostprocessing = 0; 239 | }; 240 | /* End PBXSourcesBuildPhase section */ 241 | 242 | /* Begin XCBuildConfiguration section */ 243 | 6A773141131DDD140081015A /* Debug */ = { 244 | isa = XCBuildConfiguration; 245 | buildSettings = { 246 | }; 247 | name = Debug; 248 | }; 249 | 6A773142131DDD140081015A /* Release */ = { 250 | isa = XCBuildConfiguration; 251 | buildSettings = { 252 | }; 253 | name = Release; 254 | }; 255 | 6A773154131DDD1B0081015A /* Debug */ = { 256 | isa = XCBuildConfiguration; 257 | buildSettings = { 258 | ALWAYS_SEARCH_USER_PATHS = NO; 259 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 260 | COPY_PHASE_STRIP = NO; 261 | GCC_C_LANGUAGE_STANDARD = gnu99; 262 | GCC_DYNAMIC_NO_PIC = NO; 263 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 264 | GCC_OPTIMIZATION_LEVEL = 0; 265 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 266 | GCC_PREFIX_HEADER = "BasicRequests-Prefix.pch"; 267 | GCC_PREPROCESSOR_DEFINITIONS = DEBUG; 268 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 270 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 271 | GCC_WARN_UNUSED_VARIABLE = YES; 272 | MACOSX_DEPLOYMENT_TARGET = 10.6; 273 | ONLY_ACTIVE_ARCH = YES; 274 | PRODUCT_NAME = "$(TARGET_NAME)"; 275 | SDKROOT = macosx; 276 | }; 277 | name = Debug; 278 | }; 279 | 6A773155131DDD1B0081015A /* Release */ = { 280 | isa = XCBuildConfiguration; 281 | buildSettings = { 282 | ALWAYS_SEARCH_USER_PATHS = NO; 283 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 284 | COPY_PHASE_STRIP = YES; 285 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 286 | GCC_C_LANGUAGE_STANDARD = gnu99; 287 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 288 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 289 | GCC_PREFIX_HEADER = "BasicRequests-Prefix.pch"; 290 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 291 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 292 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 293 | GCC_WARN_UNUSED_VARIABLE = YES; 294 | MACOSX_DEPLOYMENT_TARGET = 10.6; 295 | PRODUCT_NAME = "$(TARGET_NAME)"; 296 | SDKROOT = macosx; 297 | }; 298 | name = Release; 299 | }; 300 | /* End XCBuildConfiguration section */ 301 | 302 | /* Begin XCConfigurationList section */ 303 | 6A77313F131DDD140081015A /* Build configuration list for PBXProject "BasicRequests" */ = { 304 | isa = XCConfigurationList; 305 | buildConfigurations = ( 306 | 6A773141131DDD140081015A /* Debug */, 307 | 6A773142131DDD140081015A /* Release */, 308 | ); 309 | defaultConfigurationIsVisible = 0; 310 | defaultConfigurationName = Release; 311 | }; 312 | 6A773153131DDD1B0081015A /* Build configuration list for PBXNativeTarget "BasicRequests" */ = { 313 | isa = XCConfigurationList; 314 | buildConfigurations = ( 315 | 6A773154131DDD1B0081015A /* Debug */, 316 | 6A773155131DDD1B0081015A /* Release */, 317 | ); 318 | defaultConfigurationIsVisible = 0; 319 | }; 320 | /* End XCConfigurationList section */ 321 | }; 322 | rootObject = 6A77313C131DDD140081015A /* Project object */; 323 | } 324 | -------------------------------------------------------------------------------- /Examples/BasicRequests/BasicRequestsDemo.h: -------------------------------------------------------------------------------- 1 | // 2 | // BasicRequestsDemo.h 3 | // 4 | // Copyright (c) 2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import 29 | 30 | @interface BasicRequestsDemo : NSObject 31 | { 32 | NSOperationQueue *opQueue; 33 | 34 | BOOL runloopRunning; 35 | NSMessagePort *messagePort; 36 | } 37 | - (void)prepareRunloop; 38 | - (void)enterRunloop; 39 | - (void)quitRunloop; 40 | - (void)run; 41 | @end 42 | -------------------------------------------------------------------------------- /Examples/BasicRequests/BasicRequestsDemo.m: -------------------------------------------------------------------------------- 1 | // 2 | // BasicRequestsDemo.m 3 | // 4 | // Copyright (c) 2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BasicRequestsDemo.h" 29 | #import "RequestOperation.h" 30 | 31 | #import "AccountInfo.h" 32 | 33 | static const NSTimeInterval kRunloopTickInterval = 5.0; 34 | 35 | @implementation BasicRequestsDemo 36 | - (void)dealloc 37 | { 38 | [opQueue waitUntilAllOperationsAreFinished]; 39 | [opQueue release], opQueue = nil; 40 | [messagePort release], messagePort = nil; 41 | } 42 | 43 | - (id)init 44 | { 45 | self = [super init]; 46 | if (self) { 47 | opQueue = [[NSOperationQueue alloc] init]; 48 | } 49 | return self; 50 | } 51 | 52 | - (void)prepareRunloop 53 | { 54 | if (messagePort) { 55 | return; 56 | } 57 | 58 | messagePort = [[NSPort alloc] init]; 59 | [[NSRunLoop currentRunLoop] addPort:messagePort forMode:NSDefaultRunLoopMode]; 60 | runloopRunning = YES; 61 | } 62 | 63 | - (void)enterRunloop 64 | { 65 | while (runloopRunning) { 66 | [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:kRunloopTickInterval]]; 67 | } 68 | 69 | [[NSRunLoop currentRunLoop] removePort:messagePort forMode:NSDefaultRunLoopMode]; 70 | [messagePort invalidate]; 71 | [messagePort release]; 72 | messagePort = nil; 73 | } 74 | 75 | - (void)quitRunloop 76 | { 77 | if (!messagePort) { 78 | return; 79 | } 80 | 81 | NSPortMessage *message = [[[NSPortMessage alloc] initWithSendPort:messagePort receivePort:messagePort components:nil] autorelease]; 82 | [message setMsgid:0]; 83 | [message sendBeforeDate:[NSDate date]]; 84 | runloopRunning = NO; 85 | } 86 | 87 | - (void)run 88 | { 89 | BKAPIContext *context = [[BKAPIContext alloc] init]; 90 | context.serviceRoot = [NSURL URLWithString:DEMO_ENDPOINT_STRING]; 91 | 92 | [self prepareRunloop]; 93 | 94 | NSBlockOperation *convergeBlockOp = [[[NSBlockOperation alloc] init] autorelease]; 95 | 96 | BKCheckVersionRequest *checkVersionReq = [[[BKCheckVersionRequest alloc] initWithAPIContext:context] autorelease]; 97 | RequestOperation *checkVersionReqOp = [[[RequestOperation alloc] initWithRequest:checkVersionReq] autorelease]; 98 | 99 | checkVersionReqOp.onCompletion = ^(void) { 100 | NSLog(@"Check version completed, response: %@", checkVersionReq.processedResponse); 101 | }; 102 | 103 | checkVersionReqOp.onFailure = ^(void) { 104 | NSLog(@"Check version request failed, error: %@", checkVersionReq.error); 105 | }; 106 | 107 | BKLogOnRequest *logOnReq = [[[BKLogOnRequest alloc] initWithAPIContext:context accountName:DEMO_USER_NAME password:DEMO_USER_PASSWORD] autorelease]; 108 | RequestOperation *logOnReqOp = [[[RequestOperation alloc] initWithRequest:logOnReq] autorelease]; 109 | 110 | logOnReqOp.onCompletion = ^(void) { 111 | NSLog(@"Logged on, response: %@", logOnReq.processedResponse); 112 | 113 | // we can only create meaningful requests after successful login, because they require the auth token 114 | NSArray *lists = [NSArray arrayWithObjects:BKProjectList, BKMilestoneList, BKPeopleList, nil]; 115 | for (NSString *listName in lists) { 116 | BKListRequest *listReq = [[[BKListRequest alloc] initWithAPIContext:context list:listName parameters:nil] autorelease]; 117 | RequestOperation *listReqOp = [[[RequestOperation alloc] initWithRequest:listReq] autorelease]; 118 | 119 | listReqOp.onCompletion = ^(void) { 120 | NSLog(@"List '%@' fetched: %@", listName, listReq.fetchedList); 121 | }; 122 | 123 | listReqOp.onFailure = ^(void) { 124 | NSLog(@"List '%@' fetch failed", listName); 125 | }; 126 | 127 | // each list req op depends on the login request op 128 | [listReqOp addDependency:logOnReqOp]; 129 | 130 | // and the converge block op depends on the newly dynamically added list request op 131 | // (now you know why people love NSOperationQueue?) 132 | [convergeBlockOp addDependency:listReqOp]; 133 | 134 | // ... and add them to the op queue 135 | [opQueue addOperation:listReqOp]; 136 | } 137 | }; 138 | 139 | logOnReqOp.onFailure = ^(void) { 140 | NSLog(@"Failed logging on, error: %@", logOnReq.error); 141 | }; 142 | 143 | [convergeBlockOp addDependency:checkVersionReqOp]; 144 | [logOnReqOp addDependency:checkVersionReqOp]; 145 | 146 | [convergeBlockOp addDependency:logOnReqOp]; 147 | 148 | [opQueue addOperation:checkVersionReqOp]; 149 | [opQueue addOperation:logOnReqOp]; 150 | [opQueue addOperation:convergeBlockOp]; 151 | 152 | 153 | // see http://borkwarellc.wordpress.com/2010/09/06/block-retain-cycles/ why we need to do this: 154 | __block BasicRequestsDemo *blockSelf = self; 155 | 156 | [convergeBlockOp addExecutionBlock:^(void) { 157 | BOOL someOpFailedOrCancelled = NO; 158 | for (RequestOperation *op in [convergeBlockOp dependencies]) { 159 | if ([op isKindOfClass:[RequestOperation class]] && ([op isCancelled] || op.request.error != nil)) { 160 | someOpFailedOrCancelled = YES; 161 | break; 162 | } 163 | } 164 | 165 | if (someOpFailedOrCancelled) { 166 | NSLog(@"Some operation failed or got cancelled."); 167 | [blockSelf quitRunloop]; 168 | } 169 | else { 170 | NSLog(@"All dependent operations successfully ran."); 171 | 172 | // now we need to logout 173 | if (![logOnReqOp isCancelled] && logOnReq.error == nil) { 174 | BKLogOffRequest *logOffReq = [[[BKLogOffRequest alloc] initWithAPIContext:context] autorelease]; 175 | RequestOperation *logOffReqOp = [[[RequestOperation alloc] initWithRequest:logOffReq] autorelease]; 176 | 177 | logOffReqOp.onCompletion = ^(void) { 178 | NSLog(@"Successfully logged out."); 179 | [blockSelf quitRunloop]; 180 | }; 181 | 182 | logOffReqOp.onFailure = ^(void) { 183 | NSLog(@"Failed logging out, error: %@", logOffReq.error); 184 | [blockSelf quitRunloop]; 185 | }; 186 | 187 | [logOffReqOp addDependency:convergeBlockOp]; 188 | [opQueue addOperation:logOffReqOp]; 189 | } 190 | else { 191 | [blockSelf quitRunloop]; 192 | } 193 | } 194 | }]; 195 | 196 | [self enterRunloop]; 197 | [context release]; 198 | } 199 | @end 200 | -------------------------------------------------------------------------------- /Examples/BasicRequests/RequestOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // RequestOperation.h 3 | // 4 | // Copyright (c) 2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BugzKit.h" 29 | 30 | @interface RequestOperation : BKRequestOperation 31 | { 32 | // remember to provide the actual ivars in 32-bit app 33 | // (auto synthesize is 64-bit ABI only) 34 | } 35 | 36 | // we implement a very simple, synchronous (in each thread) data fetch operation, which is not cancellable 37 | // (i.e. it either completes, fails, or blocks its own thread until timeout) 38 | @property (copy) void (^onCompletion)(); 39 | @property (copy) void (^onFailure)(); 40 | @end 41 | -------------------------------------------------------------------------------- /Examples/BasicRequests/RequestOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // RequestOperation.m 3 | // 4 | // Copyright (c) 2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "RequestOperation.h" 29 | 30 | @implementation RequestOperation 31 | @synthesize onCompletion; 32 | @synthesize onFailure; 33 | 34 | - (void)dealloc 35 | { 36 | [onCompletion release], onCompletion = nil; 37 | [onFailure release], onFailure = nil; 38 | [super dealloc]; 39 | } 40 | 41 | - (void)fetchMappedXMLData 42 | { 43 | NSLog(@"%s, making request: %@", __PRETTY_FUNCTION__, request.requestURL); 44 | 45 | NSError *error = NULL; 46 | NSData *data = [NSData dataWithContentsOfURL:request.requestURL options:0 error:&error]; 47 | if (error || !data) { 48 | request.error = error ? error : [NSError errorWithDomain:[[NSBundle mainBundle] bundleIdentifier] code:-1 userInfo:nil]; 49 | } 50 | else { 51 | request.rawXMLMappedResponse = [BKXMLMapper dictionaryMappedFromXMLData:data]; 52 | } 53 | } 54 | 55 | - (void)cancelFetch 56 | { 57 | // in production code, cancel your HTTP request here 58 | } 59 | 60 | - (void)dispatchSelector:(SEL)inSelector 61 | { 62 | // The default behavior is to invoke the selector in the same thread 63 | // In production code, you might want to handle your -handleRequestStarted in e.g. main thread, so dispatch the selector here 64 | [super dispatchSelector:inSelector]; 65 | } 66 | 67 | // Override these (no need to call super if overriden) 68 | - (void)handleRequestStarted 69 | { 70 | // invoke callback when the op gets started (when it's the op's turn to run) 71 | } 72 | 73 | - (void)handleRequestCancelled 74 | { 75 | // invoke callback when the op gets cancelled 76 | } 77 | 78 | - (void)processRequestCompletion 79 | { 80 | // invoked in the same thread of the -main 81 | if (onCompletion) { 82 | onCompletion(); 83 | 84 | // zap the block references to break retain cycle (esp. if the block references to the op) 85 | self.onCompletion = nil; 86 | self.onFailure = nil; 87 | } 88 | } 89 | 90 | - (void)handleRequestCompleted 91 | { 92 | // invoke callback when the request (not the op) is completed successfully 93 | } 94 | 95 | - (void)handleRequestFailed 96 | { 97 | // invoke callback when the op failed (data fetch failed, etc.) 98 | if (onFailure) { 99 | onFailure(); 100 | 101 | // zap the block references to break retain cycle (esp. if the block references to the op) 102 | self.onCompletion = nil; 103 | self.onFailure = nil; 104 | } 105 | } 106 | 107 | - (void)handleRequestOperationEnded 108 | { 109 | // invoke callback when the op is completed (even if it gets cancelled) 110 | } 111 | 112 | - (void)handleDependencyCancellation 113 | { 114 | // you can decide if you want to cancel this op's dependencies if this op gets cancelled 115 | for (RequestOperation *op in [self dependencies]) { 116 | if (![op isKindOfClass:[RequestOperation class]]) { 117 | continue; 118 | } 119 | 120 | if ([op isCancelled] || op.request.error != nil) { 121 | [self cancel]; 122 | return; 123 | } 124 | } 125 | } 126 | @end 127 | -------------------------------------------------------------------------------- /Examples/BasicRequests/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // 4 | // Copyright (c) 2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BasicRequestsDemo.h" 29 | 30 | int main (int argc, const char * argv[]) 31 | { 32 | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 33 | 34 | BasicRequestsDemo *demo = [[BasicRequestsDemo alloc] init]; 35 | [demo run]; 36 | [demo release]; 37 | 38 | [pool drain]; 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | BugzKit 2 | ======= 3 | 4 | BugzKit is an Objective-C library for the FogBugz API. This is what we at Lithoglyph used to develop LadyBugz, a FogBugz client for the Mac. 5 | 6 | Since Lithoglyph has discontinued developing the application, I think we should open up the library so as to give the app (at least in spirit) a new life. This library should be useful in creating new FogBugz clients on both the Mac and the iOS platforms. 7 | 8 | 9 | Design Concepts 10 | --------------- 11 | 12 | Basically, the library is designed to separate request objects (objects that encapsulate API request details) from request operations (the actual worker objects that make the HTTP requests and handle the response). This allows the library to be used in a multithreaded app, backed by NSOperation objects and operation queues. 13 | 14 | 15 | Walking Through the BasicRequests Demo 16 | -------------------------------------- 17 | 18 | Perhaps the best way to understand how this framework can be used is to walk through the `Examples/BasicRequests` sample. 19 | 20 | To build the example, first checkout this project, then go to `Examples/BasicRequests`, and make a copy of `AccountInfo.template.h` and name it `AccountInfo.h`, and fill in your FogBugz account details. 21 | 22 | The Xcode project file `BasicRequests.xcodeproj` is made using Xcode 4, but I've also tested with the latest Xcode 3.2.5. Please note that the sample app is built with 64-bit Debug config. I haven't tested it on any 32-bit config and there might be things you want to take care of (I've commented those things in the source code). 23 | 24 | In this sample app (note: a command-line tool), we want to do a few things: 25 | 26 | * Check the API availability 27 | * Login 28 | * Fetch three lists -- projects, people, milestones 29 | * Logout 30 | 31 | If we draw a dependency graph, it will look like this: 32 | 33 |
34 | 35 |
36 | 37 | Apparently, each task depends on the successful execution of the previous task. 38 | 39 | BugzKit solves the dependency problem by separating "request objects" from "request operations". 40 | 41 | A "request object" (like `BKLogOnRequest`, `BKListRequest`) encapsulates the information required to make a request (URL, auth token, parameters, HTTP method, etc.) and also handles the received information. 42 | 43 | A "request operation" is an object that actually makes the HTTP request and pass the received data to the request object. It also handles error, cancellation, status callback, among many other things. 44 | 45 | BugzKit only provides you `BKRequestOperation`, a skeleton. You need to fill in the details how you want to make the requests and handles the many states that a network operation involves. In the sample app, I've supplied a simple `RequestOperation` class, which uses `-[NSData dataWithContentsOfURL:]` to make the HTTP/HTTPS request. In reality you want to use a more sophisticated way so that you can cancel the ongoing requests, among many other things you want to do. `NSURLConnection` is what you're looking for. Many people in the Mac/iOS community uses [ASIHTTPRequest](http://allseeing-i.com/ASIHTTPRequest/). I have my own HTTP request class in the [ObjectiveFlickr](https://github.com/lukhnos/objectiveflickr) library, too. 46 | 47 | Take a look at `RequestOperation.m`, and you'll understand why I leave so many implementation details to you. 48 | 49 | After the request operation has received the HTTP payload, it has to convert the raw byte stream into meaningful data. FogBugz uses XML, and BugzKit supplies a `BKXMLMapper` helper class to first parse the XML then map the elements to an NSDictionary, much like what many XML-to-JSON libraries do. Using NSDictionary and NSArray objects to manipulate structured data is easier than dealing with XML. 50 | 51 | A very important note here: `BKXMLMapper` has an option to let you use `NSXMLParser` (default) or libxml2. Unfortunately neither library is thread-safe and garbage collection-compatible. `BKXMLMapper` takes care of the thread-safe issue by using putting using the `@synchronized` block. If you want to make a number of large requests at the same time, the XML parsing phase can become a bottleneck. And that they leak memory in GC is one of the reason LadyBugz couldn't use GC. FogBugz API actually only uses a small subset of XML, and it should be possible to pick an efficient, thread-safe, GC-compatible XML parser to work with BugzKit. 52 | 53 | After the request operation has the NSDictionary object at hand, it passes the dictionary to the request object's `rawXMLMappedResponse` property. It is at this stage that the request object *processes* the data, and determines if there's an error. If there's no error, the untyped `processedResponse` (more accurately, the `id`-typed) will contain the processed response, the type of which (usually either NSDictionary or NSArray) depends on the nature of the request. If an error is the response from the server, the `error` property will be set an NSError object. 54 | 55 | Once we have a basic request operation class, we can start do the real work. For each task listed above, we: 56 | 57 | 1. Create a request object 58 | 2. Create a request operation object and load the request object into the operation (at initialization) 59 | 3. Specify how we want to handle successful completion or failure for each operation 60 | 4. Add dependency (see Apple's `NSOperation` API documentation on how this works) 61 | 5. Add the operation to an operation queue 62 | 63 | In our sample, we also have a `convergeBlockOperation` which is a plain-vanilla `NSBlockOperation`. The operation gets executed after all its dependencies are done. If none of its dependencies failed, then the operation schedules a logout request operation. 64 | 65 | The sample app also schedules a runloop in the main thread and only quits the runloop when the last operation requests so. 66 | 67 | 68 | Coverage of this API Library 69 | ---------------------------- 70 | 71 | A lot of things in FogBugz are not covered in the API library, such as Wiki and time tracking. It should not be hard to extend the library for those purposes. 72 | 73 | `BKEditCaseRequest` and `BKMailRequest` are capable of handling file attachments for you. When you initialize those objects, there's an init method that takes an array of URLs as one of its arguments. Those URLs must be file URLs, and the request objects will create the necessary temp files for you under the hood, and you can use the `requestInputStream` property to get a read stream for the raw bytes data, which you send as the multipart HTTP request body. 74 | 75 | The definitive FogBugz API guide is of course http://fogbugz.stackexchange.com/fogbugz-xml-api. 76 | 77 | Finally, this library does not make any guarantee that the library is up to date. 78 | 79 | 80 | Copyright 81 | --------- 82 | 83 | Copyright (c) 2009-2011 Lukhnos D. Liu. 84 | 85 | This library is released under the MIT License. 86 | 87 | 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: 88 | 89 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 90 | 91 | * 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. 92 | -------------------------------------------------------------------------------- /Source/BKAPIContext+ProtectedMethods.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKAPIContext+ProtectedMethods.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKAPIContext.h" 29 | 30 | @interface BKAPIContext (ProtectedMethods) 31 | - (void)setMajorVersion:(NSUInteger)inVersion; 32 | - (void)setMinorVersion:(NSUInteger)inVersion; 33 | - (void)setEndpoint:(NSURL *)inEndpoint; 34 | - (void)setAuthToken:(NSString *)inAuthToken; 35 | @end 36 | -------------------------------------------------------------------------------- /Source/BKAPIContext.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKAPIContext.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import 29 | 30 | @interface BKAPIContext : NSObject 31 | { 32 | NSURL *serviceRoot; 33 | 34 | NSUInteger majorVersion; 35 | NSUInteger minorVersion; 36 | NSURL *endpoint; 37 | NSString *authToken; 38 | } 39 | @property (retain) NSURL *serviceRoot; 40 | 41 | @property (readonly) NSUInteger majorVersion; 42 | @property (readonly) NSUInteger minorVersion; 43 | @property (readonly) NSURL *endpoint; 44 | @property (readonly) NSString *authToken; 45 | @end 46 | -------------------------------------------------------------------------------- /Source/BKAPIContext.m: -------------------------------------------------------------------------------- 1 | // 2 | // BKAPIContext.m 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKAPIContext.h" 29 | #import "BKAPIContext+ProtectedMethods.h" 30 | #import "BKPrivateUtilities.h" 31 | 32 | @implementation BKAPIContext 33 | - (void)dealloc 34 | { 35 | [serviceRoot release]; 36 | [endpoint release]; 37 | [authToken release]; 38 | [super dealloc]; 39 | } 40 | 41 | - (NSString *)description 42 | { 43 | return [NSString stringWithFormat:@"<%@: %p> {serviceRoot: %@, API version: %@, endpoint: %@, authToken: %@}", [self class], self, BKQuotedString([serviceRoot absoluteString]), [NSString stringWithFormat:@"%jd.%jd", (uintmax_t)majorVersion, (uintmax_t)minorVersion], BKQuotedString([endpoint absoluteString]), BKQuotedString(authToken)]; 44 | } 45 | 46 | - (NSURL *)serviceRoot 47 | { 48 | return [[serviceRoot copy] autorelease]; 49 | } 50 | 51 | - (void)setServiceRoot:(NSURL *)inRoot 52 | { 53 | BKRetainAssign(serviceRoot, inRoot); 54 | majorVersion = 0; 55 | minorVersion = 0; 56 | BKReleaseClean(endpoint); 57 | BKReleaseClean(authToken); 58 | } 59 | 60 | @synthesize serviceRoot; 61 | @synthesize majorVersion; 62 | @synthesize minorVersion; 63 | @synthesize endpoint; 64 | @synthesize authToken; 65 | @end 66 | 67 | @implementation BKAPIContext (ProtectedMethods) 68 | - (void)setMajorVersion:(NSUInteger)inVersion 69 | { 70 | majorVersion = inVersion; 71 | } 72 | 73 | - (void)setMinorVersion:(NSUInteger)inVersion 74 | { 75 | minorVersion = inVersion; 76 | } 77 | 78 | - (void)setAuthToken:(NSString *)inAuthToken 79 | { 80 | BKRetainAssign(authToken, inAuthToken); 81 | } 82 | 83 | - (void)setEndpoint:(NSURL *)inEndpoint 84 | { 85 | BKRetainAssign(endpoint, inEndpoint); 86 | } 87 | @end 88 | -------------------------------------------------------------------------------- /Source/BKAreaListRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKAreaListRequest.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKListRequest.h" 29 | 30 | @interface BKAreaListRequest : BKListRequest 31 | + (id)requestWithAPIContext:(BKAPIContext *)inAPIContext projectID:(NSUInteger)inProjectID writableItemsOnly:(BOOL)inListOnlyWritables DEPRECATED_ATTRIBUTE; 32 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext projectID:(NSUInteger)inProjectID writableItemsOnly:(BOOL)inListOnlyWritables; 33 | 34 | @property (readonly) NSUInteger projectID; 35 | @end 36 | -------------------------------------------------------------------------------- /Source/BKAreaListRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // BKAreaListRequest.m 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKAreaListRequest.h" 29 | 30 | @implementation BKAreaListRequest 31 | + (id)requestWithAPIContext:(BKAPIContext *)inAPIContext projectID:(NSUInteger)inProjectID writableItemsOnly:(BOOL)inListOnlyWritables 32 | { 33 | return [[[self alloc] initWithAPIContext:inAPIContext projectID:inProjectID writableItemsOnly:inListOnlyWritables] autorelease]; 34 | } 35 | 36 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext projectID:(NSUInteger)inProjectID writableItemsOnly:(BOOL)inListOnlyWritables 37 | { 38 | self = [super initWithAPIContext:inAPIContext list:BKAreaList writableItemsOnly:inListOnlyWritables]; 39 | if (self) { 40 | [(NSMutableDictionary *)requestParameterDict setObject:[NSNumber numberWithUnsignedInteger:inProjectID] forKey:@"ixProject"]; 41 | } 42 | 43 | return self; 44 | } 45 | 46 | - (NSUInteger)projectID 47 | { 48 | return (NSUInteger)[[requestParameterDict objectForKey:@"ixProject"] integerValue]; 49 | } 50 | @end 51 | -------------------------------------------------------------------------------- /Source/BKCheckVersionRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKCheckVersionRequest.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKRequest.h" 29 | 30 | @interface BKCheckVersionRequest : BKRequest 31 | @end 32 | -------------------------------------------------------------------------------- /Source/BKCheckVersionRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // BKCheckVersionRequest.m 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKCheckVersionRequest.h" 29 | #import "BKAPIContext+ProtectedMethods.h" 30 | 31 | @implementation BKCheckVersionRequest 32 | - (NSURL *)requestURL 33 | { 34 | return [NSURL URLWithString:@"api.xml" relativeToURL:APIContext.serviceRoot]; 35 | } 36 | 37 | - (id)postprocessResponse:(NSDictionary *)inXMLMappedResponse 38 | { 39 | [APIContext setEndpoint:[NSURL URLWithString:[inXMLMappedResponse objectForKey:@"url"] relativeToURL:APIContext.serviceRoot]]; 40 | [APIContext setMajorVersion:[[inXMLMappedResponse objectForKey:@"version"] integerValue]]; 41 | [APIContext setMinorVersion:[[inXMLMappedResponse objectForKey:@"minversion"] integerValue]]; 42 | return [super postprocessResponse:inXMLMappedResponse]; 43 | } 44 | @end 45 | -------------------------------------------------------------------------------- /Source/BKEditCaseRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKEditCaseRequest.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKRequest.h" 29 | 30 | @interface BKEditCaseRequest : BKRequest 31 | { 32 | NSDictionary *parameters; 33 | 34 | NSString *multipartSeparator; 35 | NSString *tempFilename; 36 | NSArray *attachmentURLs; 37 | } 38 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext editAction:(NSString *)inAction parameters:(NSDictionary *)inParameters; 39 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext editAction:(NSString *)inAction caseNumber:(NSUInteger)inCaseNumber parameters:(NSDictionary *)inParameters; 40 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext editAction:(NSString *)inAction caseNumber:(NSUInteger)inCaseNumber parameters:(NSDictionary *)inParameters attachmentURLs:(NSArray *)inURLs attachmentsFromBugEventID:(NSUInteger)inEventID; 41 | @property (readonly) NSDictionary *editedCase; 42 | @property (readonly) NSString *editAction; 43 | @end 44 | 45 | extern NSString *const BKAssignCaseAction; 46 | extern NSString *const BKCloseCaseAction; 47 | extern NSString *const BKEditCaseAction; 48 | extern NSString *const BKEmailCaseAction; 49 | extern NSString *const BKForwardCaseAction; 50 | extern NSString *const BKNewCaseAction; 51 | extern NSString *const BKReactivateCaseAction; 52 | extern NSString *const BKReopenCaseAction; 53 | extern NSString *const BKReplyCaseAction; 54 | extern NSString *const BKResolveCaseAction; 55 | -------------------------------------------------------------------------------- /Source/BKEditCaseRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // BKEditCaseRequest.m 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKEditCaseRequest.h" 29 | #import "BKPrivateUtilities.h" 30 | 31 | NSString *const BKAssignCaseAction = @"assign"; 32 | NSString *const BKCloseCaseAction = @"close"; 33 | NSString *const BKEditCaseAction = @"edit"; 34 | NSString *const BKEmailCaseAction = @"email"; 35 | NSString *const BKForwardCaseAction = @"forward"; 36 | NSString *const BKNewCaseAction = @"new"; 37 | NSString *const BKReactivateCaseAction = @"reactivate"; 38 | NSString *const BKReopenCaseAction = @"reopen"; 39 | NSString *const BKReplyCaseAction = @"reply"; 40 | NSString *const BKResolveCaseAction = @"resolve"; 41 | 42 | @implementation BKEditCaseRequest 43 | - (void)cleanUpTempFile 44 | { 45 | if (![tempFilename length]) { 46 | return; 47 | } 48 | 49 | BOOL isDir = NO; 50 | NSFileManager *fileManager = [[NSFileManager alloc] init]; 51 | if ([fileManager fileExistsAtPath:tempFilename isDirectory:&isDir]) { 52 | 53 | NSError *ourError = NULL; 54 | BOOL __unused removeResult = [[NSFileManager defaultManager] removeItemAtPath:tempFilename error:&ourError]; 55 | NSAssert2(removeResult, @"Must remove the temp file at: %@, error: %@", tempFilename, ourError); 56 | } 57 | [fileManager release]; 58 | } 59 | 60 | - (void)prepareTempFile 61 | { 62 | if ([tempFilename length]) { 63 | return; 64 | } 65 | 66 | NSString *bundleID = [[[NSBundle bundleForClass:[self class]] infoDictionary] objectForKey:(id)kCFBundleIdentifierKey]; 67 | NSString *filenameRoot = [NSTemporaryDirectory() stringByAppendingFormat:@"%@.%@.data-XXXXXX", NSStringFromClass([self class]), bundleID]; 68 | 69 | const char *filenameUTF8 = [filenameRoot UTF8String]; 70 | char *writableFilename = (char *)calloc(1, strlen(filenameUTF8) + 1); 71 | strncpy(writableFilename, filenameUTF8, strlen(filenameUTF8)); 72 | 73 | mktemp(writableFilename); 74 | tempFilename = [[NSString alloc] initWithUTF8String:writableFilename]; 75 | 76 | // build the multipart form 77 | NSMutableString *multipartBegin = [NSMutableString string]; 78 | NSMutableString *multipartEnd = [NSMutableString string]; 79 | 80 | for (NSString *key in requestParameterDict) { 81 | NSString *value = [requestParameterDict objectForKey:key]; 82 | [multipartBegin appendFormat:@"--%@\r\nContent-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n", multipartSeparator, key, value]; 83 | } 84 | 85 | 86 | // add filename, if nil, generate a UUID 87 | 88 | [multipartEnd appendFormat:@"--%@--", multipartSeparator]; 89 | 90 | 91 | // create the write stream 92 | NSOutputStream *outputStream = [NSOutputStream outputStreamToFileAtPath:tempFilename append:NO]; 93 | [outputStream open]; 94 | 95 | const char *UTF8String; 96 | size_t writeLength; 97 | UTF8String = [multipartBegin UTF8String]; 98 | writeLength = strlen(UTF8String); 99 | 100 | size_t __unused actualWrittenLength; 101 | actualWrittenLength = [outputStream write:(uint8_t *)UTF8String maxLength:writeLength]; 102 | NSAssert(actualWrittenLength == writeLength, @"Must write multipartBegin"); 103 | 104 | NSUInteger fileIndex = 1; 105 | for (NSURL *u in attachmentURLs) { 106 | // TODO: Speed this part up (measure performance first) 107 | NSData *d = [NSData dataWithContentsOfURL:u]; 108 | 109 | // TODO: Ensure the correctness 110 | NSString *lastPathComponent = [u lastPathComponent]; 111 | 112 | NSMutableString *fileHeader = [NSMutableString string]; 113 | 114 | [fileHeader appendFormat:@"--%@\r\nContent-Disposition: form-data; name=\"File%ju\"; filename=\"%@\"\r\n", multipartSeparator, (uintmax_t)fileIndex, lastPathComponent]; 115 | [fileHeader appendFormat:@"Content-Type: %@\r\n\r\n", @"application/octet-stream"]; 116 | 117 | 118 | UTF8String = [fileHeader UTF8String]; 119 | writeLength = strlen(UTF8String); 120 | actualWrittenLength = [outputStream write:(uint8_t *)UTF8String maxLength:writeLength]; 121 | NSAssert(actualWrittenLength == writeLength, @"Must write fileHeader"); 122 | 123 | actualWrittenLength = [outputStream write:[d bytes] maxLength:[d length]]; 124 | NSAssert(actualWrittenLength == [d length], @"Must write binary data"); 125 | 126 | NSString *fileEnd = @"\r\n"; 127 | 128 | UTF8String = [fileEnd UTF8String]; 129 | writeLength = strlen(UTF8String); 130 | actualWrittenLength = [outputStream write:(uint8_t *)UTF8String maxLength:writeLength]; 131 | NSAssert(actualWrittenLength == writeLength, @"Must write fileHeader"); 132 | 133 | fileIndex++; 134 | } 135 | 136 | 137 | UTF8String = [multipartEnd UTF8String]; 138 | writeLength = strlen(UTF8String); 139 | actualWrittenLength = [outputStream write:(uint8_t *)UTF8String maxLength:writeLength]; 140 | NSAssert(actualWrittenLength == writeLength, @"Must write multipartEnd"); 141 | [outputStream close]; 142 | } 143 | 144 | - (void)dealloc 145 | { 146 | [self cleanUpTempFile]; 147 | [multipartSeparator release]; 148 | [tempFilename release]; 149 | [attachmentURLs release]; 150 | [super dealloc]; 151 | } 152 | 153 | - (void)finalize 154 | { 155 | [self cleanUpTempFile]; 156 | [super finalize]; 157 | } 158 | 159 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext editAction:(NSString *)inAction caseNumber:(NSUInteger)inCaseNumber parameters:(NSDictionary *)inParameters attachmentURLs:(NSArray *)inURLs attachmentsFromBugEventID:(NSUInteger)inEventID; 160 | { 161 | self = [super initWithAPIContext:inAPIContext]; 162 | if (self) { 163 | NSMutableDictionary *d = [NSMutableDictionary dictionary]; 164 | 165 | [d setObject:inAPIContext.authToken forKey:@"token"]; 166 | [d setObject:inAction forKey:@"cmd"]; 167 | 168 | if (inCaseNumber) { 169 | [d setObject:[NSString stringWithFormat:@"%ju", (uintmax_t)inCaseNumber] forKey:@"ixBug"]; 170 | } 171 | 172 | if (inEventID) { 173 | [d setObject:[NSString stringWithFormat:@"%ju", (uintmax_t)inEventID] forKey:@"ixBugEventAttachment"]; 174 | } 175 | 176 | if ([inURLs count]) { 177 | [d setObject:[NSString stringWithFormat:@"%ju", (uintmax_t)[inURLs count]] forKey:@"nFileCount"]; 178 | } 179 | 180 | if (inParameters) { 181 | [d addEntriesFromDictionary:inParameters]; 182 | } 183 | 184 | requestParameterDict = [d retain]; 185 | 186 | if ([inURLs count]) { 187 | attachmentURLs = [[NSArray alloc] initWithArray:inURLs]; 188 | } 189 | 190 | multipartSeparator = [BKGenerateUUID() retain]; 191 | } 192 | 193 | return self; 194 | } 195 | 196 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext editAction:(NSString *)inAction caseNumber:(NSUInteger)inCaseNumber parameters:(NSDictionary *)inParameters 197 | { 198 | return [self initWithAPIContext:inAPIContext editAction:inAction caseNumber:inCaseNumber parameters:inParameters attachmentURLs:nil attachmentsFromBugEventID:0]; 199 | } 200 | 201 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext editAction:(NSString *)inAction parameters:(NSDictionary *)inParameters 202 | { 203 | return [self initWithAPIContext:inAPIContext editAction:inAction caseNumber:0 parameters:inParameters attachmentURLs:nil attachmentsFromBugEventID:0]; 204 | } 205 | 206 | - (id)postprocessResponse:(NSDictionary *)inXMLMappedResponse 207 | { 208 | id result = [inXMLMappedResponse valueForKeyPath:@"case"]; 209 | if (!result) { 210 | result = [NSDictionary dictionary]; 211 | } 212 | 213 | return result; 214 | } 215 | 216 | - (NSString *)editAction 217 | { 218 | return [requestParameterDict objectForKey:@"cmd"]; 219 | } 220 | 221 | - (NSDictionary *)editedCase 222 | { 223 | return processedResponse; 224 | } 225 | 226 | 227 | - (BOOL)usesPOSTRequest 228 | { 229 | return YES; 230 | } 231 | 232 | - (NSString *)HTTPRequestContentType 233 | { 234 | return [attachmentURLs count] ? [NSString stringWithFormat:@"multipart/form-data; boundary=%@", multipartSeparator] : [super HTTPRequestContentType]; 235 | } 236 | 237 | - (NSUInteger)requestInputStreamSize 238 | { 239 | if (![attachmentURLs count]) { 240 | return 0; 241 | } 242 | 243 | [self prepareTempFile]; 244 | NSError *fileError = NULL; 245 | NSDictionary *info = [[NSFileManager defaultManager] attributesOfItemAtPath:tempFilename error:&fileError]; 246 | return [[info objectForKey:NSFileSize] unsignedIntegerValue]; 247 | } 248 | 249 | - (NSInputStream *)requestInputStream 250 | { 251 | if (![attachmentURLs count]) { 252 | return 0; 253 | } 254 | 255 | [self prepareTempFile]; 256 | return [NSInputStream inputStreamWithFileAtPath:tempFilename]; 257 | } 258 | 259 | - (NSData *)requestData 260 | { 261 | return [attachmentURLs count] ? nil : [super requestData]; 262 | } 263 | @end 264 | -------------------------------------------------------------------------------- /Source/BKError.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKError.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import 29 | 30 | // TODO: Remove these 31 | extern NSString *const BKConnectionErrorDomain; 32 | extern NSString *const BKAPIErrorDomain; 33 | 34 | typedef enum { 35 | // TODO: Remove these 36 | BKConnecitonLostError = -1, 37 | BKConnectionTimeoutError = -2, 38 | BKConnectionServerHTTPError = -3, // e.g. 404 39 | BKConnectionCannotPerformHTTPRequestError = -4, // performMethod: returns NO 40 | 41 | BKAPIMalformedResponseError = -100, 42 | BKUnknownError = -9999, 43 | 44 | BKNotInitializedError = 0, 45 | BKLogOnIncorrectUsernameOrPasswordError = 1, 46 | BKLogOnMultipleMatchesForUsernameError = 2, 47 | BKNotLoggedOnError = 3, 48 | BKArgumentMissingFromQueryError = 4, 49 | BKEditingCaseNotFoundError = 5, 50 | BKEditingCaseActionNotPermitted = 6, 51 | BKTimeTrackingError = 7, 52 | BKNewCaseCannotWriteToAnyProjectError = 8, 53 | BKCaseChangedSinceLastViewError = 9, 54 | BKSearchError = 10, 55 | BKWikiCreationError = 12, 56 | BKWikiPermissionError = 13, 57 | BKWikiLoadError = 14, 58 | BKWikiTemplateError = 15, 59 | BKWikiCommitError = 16, 60 | BKNoSuchProjectError = 17, 61 | BKNoSuchUserError = 18, 62 | BKAreaCreationError = 19, 63 | BKMilestoneCreationError = 20, 64 | BKProjectCreationError = 21, 65 | BKUserCreationError = 22, 66 | BKProjectPercentTimeError = 23, 67 | BKNoSuchMilestoneError = 24, 68 | BKMilestoneExecutionOrderViolationError = 25 69 | } BKErrorCode; 70 | -------------------------------------------------------------------------------- /Source/BKError.m: -------------------------------------------------------------------------------- 1 | // 2 | // BKError.m 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKError.h" 29 | 30 | NSString *const BKConnectionErrorDomain = @"BKBugzConnectionErrorDomain"; 31 | NSString *const BKAPIErrorDomain = @"BKBugzAPIErrorDomain"; 32 | -------------------------------------------------------------------------------- /Source/BKListRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKListRequest.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKRequest.h" 29 | 30 | @interface BKListRequest : BKRequest 31 | { 32 | NSString *listType; 33 | } 34 | + (id)requestWithAPIContext:(BKAPIContext *)inAPIContext list:(NSString *)inListType writableItemsOnly:(BOOL)inListOnlyWritables DEPRECATED_ATTRIBUTE; 35 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext list:(NSString *)inListType writableItemsOnly:(BOOL)inListOnlyWritables; 36 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext list:(NSString *)inListType parameters:(NSDictionary *)inParameters; 37 | 38 | @property (readonly) NSString *listType; 39 | @property (readonly) NSArray *fetchedList; 40 | @end 41 | 42 | extern NSString *const BKAreaList; 43 | extern NSString *const BKCategoryList; 44 | extern NSString *const BKFilterList; 45 | extern NSString *const BKMailboxList; 46 | extern NSString *const BKMilestoneList; 47 | extern NSString *const BKPeopleList; 48 | extern NSString *const BKPriorityList; 49 | extern NSString *const BKProjectList; 50 | extern NSString *const BKStatusList; 51 | extern NSString *const BKSnippetList; 52 | 53 | extern NSString *const BKPeopleListIncludeNormalUsersParameterKey; 54 | extern NSString *const BKPeopleListIncludeVirtualUsersParameterKey; 55 | -------------------------------------------------------------------------------- /Source/BKListRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // BKListRequest.m 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKListRequest.h" 29 | #import "BKError.h" 30 | 31 | NSString *const BKAreaList = @"BKAreaList"; 32 | NSString *const BKCategoryList = @"BKCategoryList"; 33 | NSString *const BKFilterList = @"BKFilterList"; 34 | NSString *const BKMailboxList = @"BKMailboxList"; 35 | NSString *const BKMilestoneList = @"BKMilestoneList"; 36 | NSString *const BKPeopleList = @"BKPeopleList"; 37 | NSString *const BKPriorityList = @"BKPriorityList"; 38 | NSString *const BKProjectList = @"BKProjectList"; 39 | NSString *const BKStatusList = @"BKStatusList"; 40 | NSString *const BKSnippetList = @"BKSnippetList"; 41 | 42 | NSString *const BKPeopleListIncludeNormalUsersParameterKey = @"fIncludeNormal"; 43 | NSString *const BKPeopleListIncludeVirtualUsersParameterKey = @"fIncludeVirtual"; 44 | 45 | static NSString *kListCommandKey = @"kListCommandKey"; 46 | static NSString *kListResultValueKeyPathKey = @"kListResultValueKeyPathKey"; 47 | static NSString *kFirstLevelValueKey = @"kFirstLevelValueKey"; 48 | 49 | @interface BKListRequest (PrivateMethods) 50 | + (NSDictionary *)listParameterDictionary; 51 | + (NSString *)commandForListType:(NSString *)inListType; 52 | + (NSString *)resultValueKeyPathKey:(NSString *)inListType; 53 | + (NSString *)firstLevelValueKey:(NSString *)inListType; 54 | @end 55 | 56 | @implementation BKListRequest 57 | + (NSDictionary *)listParameterDictionary 58 | 59 | { 60 | static NSDictionary *parameterDictionary = nil; 61 | 62 | @synchronized(self) { 63 | if (!parameterDictionary) { 64 | parameterDictionary = [[NSMutableDictionary dictionary] retain]; 65 | 66 | #define POPULATE(dict, key, cmd, kvPath, lvk) do { [(NSMutableDictionary *)dict setObject:[NSDictionary dictionaryWithObjectsAndKeys:cmd, kListCommandKey, kvPath, kListResultValueKeyPathKey, lvk, kFirstLevelValueKey, nil] forKey:key]; } while(0); 67 | POPULATE(parameterDictionary, BKFilterList, @"listFilters", @"filters.filter", @"filters"); 68 | POPULATE(parameterDictionary, BKProjectList, @"listProjects", @"projects.project", @"projects"); 69 | POPULATE(parameterDictionary, BKAreaList, @"listAreas", @"areas.area", @"areas"); 70 | POPULATE(parameterDictionary, BKCategoryList, @"listCategories", @"categories.category", @"categories"); 71 | POPULATE(parameterDictionary, BKPriorityList, @"listPriorities", @"priorities.priority", @"priorities"); 72 | POPULATE(parameterDictionary, BKPeopleList, @"listPeople", @"people.person", @"people"); 73 | POPULATE(parameterDictionary, BKSnippetList, @"listSnippets", @"snippets.snippet", @"snippets"); 74 | POPULATE(parameterDictionary, BKStatusList, @"listStatuses", @"statuses.status", @"statuses"); 75 | POPULATE(parameterDictionary, BKMilestoneList, @"listFixFors", @"fixfors.fixfor", @"fixfors"); 76 | POPULATE(parameterDictionary, BKMailboxList, @"listMailboxes", @"mailboxes.mailbox", @"mailboxes"); 77 | #undef POPULATE 78 | } 79 | } 80 | 81 | return parameterDictionary; 82 | } 83 | 84 | + (NSString *)commandForListType:(NSString *)inListType 85 | { 86 | return [[[self listParameterDictionary] objectForKey:inListType] objectForKey:kListCommandKey]; 87 | } 88 | 89 | + (NSString *)resultValueKeyPathKey:(NSString *)inListType 90 | { 91 | return [[[self listParameterDictionary] objectForKey:inListType] objectForKey:kListResultValueKeyPathKey]; 92 | } 93 | 94 | + (NSString *)firstLevelValueKey:(NSString *)inListType 95 | { 96 | return [[[self listParameterDictionary] objectForKey:inListType] objectForKey:kFirstLevelValueKey]; 97 | } 98 | 99 | - (void)dealloc 100 | { 101 | [listType release]; 102 | [super dealloc]; 103 | } 104 | 105 | + (id)requestWithAPIContext:(BKAPIContext *)inAPIContext list:(NSString *)inListType writableItemsOnly:(BOOL)inListOnlyWritables 106 | { 107 | return [[[self alloc] initWithAPIContext:inAPIContext list:inListType writableItemsOnly:inListOnlyWritables] autorelease]; 108 | } 109 | 110 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext list:(NSString *)inListType writableItemsOnly:(BOOL)inListOnlyWritables 111 | { 112 | return [self initWithAPIContext:inAPIContext list:inListType parameters:(inListOnlyWritables ? [NSDictionary dictionary] : [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:inListOnlyWritables], @"fWrite", nil])]; 113 | } 114 | 115 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext list:(NSString *)inListType parameters:(NSDictionary *)inParameters 116 | { 117 | self = [super initWithAPIContext:inAPIContext]; 118 | 119 | if (self) { 120 | listType = [inListType retain]; 121 | requestParameterDict = [[NSMutableDictionary alloc] init]; 122 | 123 | [(NSMutableDictionary *)requestParameterDict setObject:[[self class] commandForListType:listType] forKey:@"cmd"]; 124 | [(NSMutableDictionary *)requestParameterDict setObject:inAPIContext.authToken forKey:@"token"]; 125 | 126 | if ([inParameters count]) { 127 | [(NSMutableDictionary *)requestParameterDict addEntriesFromDictionary:inParameters]; 128 | } 129 | } 130 | 131 | return self; 132 | } 133 | 134 | - (NSError *)validateResponse:(NSDictionary *)inXMLMappedResponse 135 | { 136 | if (![inXMLMappedResponse objectForKey:[[self class] firstLevelValueKey:listType]]) { 137 | // it's perfectly ok for BKMailboxList to return nothing 138 | if ([listType isEqualToString:BKMailboxList]) { 139 | return nil; 140 | } 141 | 142 | return [NSError errorWithDomain:BKAPIErrorDomain code:BKAPIMalformedResponseError userInfo:nil]; 143 | } 144 | 145 | return [super validateResponse:inXMLMappedResponse]; 146 | } 147 | 148 | - (id)postprocessResponse:(NSDictionary *)inXMLMappedResponse 149 | { 150 | id result = nil; 151 | 152 | if ([inXMLMappedResponse isKindOfClass:[NSDictionary class]]) { 153 | @try { 154 | result = [inXMLMappedResponse valueForKeyPath:[[self class] resultValueKeyPathKey:listType]]; 155 | } 156 | @catch (NSException *exception) { 157 | } 158 | } 159 | 160 | if (!result) { 161 | result = [NSArray array]; 162 | } 163 | 164 | return result; 165 | } 166 | 167 | - (NSArray *)fetchedList 168 | { 169 | return [processedResponse isKindOfClass:[NSArray class]] ? processedResponse : nil; 170 | } 171 | 172 | @synthesize listType; 173 | @end 174 | -------------------------------------------------------------------------------- /Source/BKListWorkingScheduleRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKListWorkingScheduleRequest.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKRequest.h" 29 | 30 | @interface BKListWorkingScheduleRequest : BKRequest 31 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext personID:(NSUInteger)inPersonID; 32 | @property (readonly) NSDictionary *fetchedWorkingSchedule; 33 | @end 34 | 35 | extern const NSUInteger BKSiteWorkingSchedulePersonID; 36 | -------------------------------------------------------------------------------- /Source/BKListWorkingScheduleRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // BKListWorkingScheduleRequest.m 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKListWorkingScheduleRequest.h" 29 | 30 | const NSUInteger BKSiteWorkingSchedulePersonID = 1; 31 | 32 | @implementation BKListWorkingScheduleRequest 33 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext personID:(NSUInteger)inPersonID 34 | { 35 | self = [super initWithAPIContext:inAPIContext]; 36 | if (self) { 37 | NSMutableDictionary *d = [NSMutableDictionary dictionary]; 38 | 39 | [d setObject:inAPIContext.authToken forKey:@"token"]; 40 | [d setObject:@"listWorkingSchedule" forKey:@"cmd"]; 41 | 42 | if (inPersonID) { 43 | [d setObject:[NSString stringWithFormat:@"%jd", (uintmax_t)inPersonID] forKey:@"ixPerson"]; 44 | } 45 | 46 | requestParameterDict = [d retain]; 47 | } 48 | 49 | return self; 50 | } 51 | 52 | - (id)postprocessResponse:(NSDictionary *)inXMLMappedResponse 53 | { 54 | id result = [inXMLMappedResponse valueForKeyPath:@"workingSchedule"]; 55 | if (!result) { 56 | result = [NSDictionary dictionary]; 57 | } 58 | 59 | return result; 60 | } 61 | 62 | - (NSDictionary *)fetchedWorkingSchedule 63 | { 64 | return [processedResponse isKindOfClass:[NSDictionary class]] ? processedResponse : nil; 65 | } 66 | @end 67 | -------------------------------------------------------------------------------- /Source/BKLogOffRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKLogOffRequest.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKRequest.h" 29 | 30 | @interface BKLogOffRequest : BKRequest 31 | @end 32 | -------------------------------------------------------------------------------- /Source/BKLogOffRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // BKLogOffRequest.m 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKLogOffRequest.h" 29 | #import "BKAPIContext+ProtectedMethods.h" 30 | 31 | @implementation BKLogOffRequest : BKRequest 32 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext 33 | { 34 | self = [super initWithAPIContext:inAPIContext]; 35 | if (self) { 36 | requestParameterDict = [[NSDictionary dictionaryWithObjectsAndKeys:@"logoff", @"cmd", inAPIContext.authToken, @"token", nil] retain]; 37 | } 38 | 39 | return self; 40 | } 41 | 42 | - (id)postprocessResponse:(NSDictionary *)inXMLMappedResponse 43 | { 44 | [APIContext setAuthToken:nil]; 45 | return nil; 46 | } 47 | @end 48 | -------------------------------------------------------------------------------- /Source/BKLogOnRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKLogOnRequest.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKRequest.h" 29 | 30 | @interface BKLogOnRequest : BKRequest 31 | + (id)requestWithAPIContext:(BKAPIContext *)inAPIContext accountName:(NSString *)inAccountName password:(NSString *)inPassword DEPRECATED_ATTRIBUTE; 32 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext accountName:(NSString *)inAccountName password:(NSString *)inPassword; 33 | @end 34 | -------------------------------------------------------------------------------- /Source/BKLogOnRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // BKLogOnRequest.m 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKLogOnRequest.h" 29 | #import "BKAPIContext+ProtectedMethods.h" 30 | #import "BKPrivateUtilities.h" 31 | 32 | @implementation BKLogOnRequest : BKRequest 33 | + (id)requestWithAPIContext:(BKAPIContext *)inAPIContext accountName:(NSString *)inAccountName password:(NSString *)inPassword 34 | { 35 | return [[[self alloc] initWithAPIContext:inAPIContext accountName:inAccountName password:inPassword] autorelease]; 36 | } 37 | 38 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext accountName:(NSString *)inAccountName password:(NSString *)inPassword 39 | { 40 | self = [super initWithAPIContext:inAPIContext]; 41 | if (self) { 42 | requestParameterDict = [[NSDictionary dictionaryWithObjectsAndKeys:@"logon", @"cmd", BKNotNil(inAccountName), @"email", BKNotNil(inPassword), @"password", nil] retain]; 43 | } 44 | 45 | return self; 46 | } 47 | 48 | - (void)postprocessError:(NSError *)inError 49 | { 50 | [APIContext setAuthToken:nil]; 51 | } 52 | 53 | - (id)postprocessResponse:(NSDictionary *)inXMLMappedResponse 54 | { 55 | NSString *token = [inXMLMappedResponse objectForKey:@"token"]; 56 | [APIContext setAuthToken:token]; 57 | 58 | return token; 59 | } 60 | @end 61 | -------------------------------------------------------------------------------- /Source/BKMailRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKMailRequest.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKEditCaseRequest.h" 29 | 30 | @interface BKMailRequest : BKEditCaseRequest 31 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext editAction:(NSString *)inAction caseNumber:(NSUInteger)inCaseNumber parameters:(NSDictionary *)inParameters text:(NSString *)inText subject:(NSString *)inSubject from:(NSString *)inFrom to:(NSString *)inTo CC:(NSString *)inCC BCC:(NSString *)inBCC attachmentURLs:(NSArray *)inURLs attachmentsFromBugEventID:(NSUInteger)inEventID; 32 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext editAction:(NSString *)inAction caseNumber:(NSUInteger)inCaseNumber text:(NSString *)inText subject:(NSString *)inSubject from:(NSString *)inFrom to:(NSString *)inTo CC:(NSString *)inCC BCC:(NSString *)inBCC attachmentURLs:(NSArray *)inURLs attachmentsFromBugEventID:(NSUInteger)inEventID; 33 | @end 34 | -------------------------------------------------------------------------------- /Source/BKMailRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // BKMailRequest.m 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKMailRequest.h" 29 | 30 | @implementation BKMailRequest 31 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext editAction:(NSString *)inAction caseNumber:(NSUInteger)inCaseNumber parameters:(NSDictionary *)inParameters text:(NSString *)inText subject:(NSString *)inSubject from:(NSString *)inFrom to:(NSString *)inTo CC:(NSString *)inCC BCC:(NSString *)inBCC attachmentURLs:(NSArray *)inURLs attachmentsFromBugEventID:(NSUInteger)inEventID; 32 | { 33 | NSMutableDictionary *params = [NSMutableDictionary dictionary]; 34 | if (inParameters) { 35 | [params addEntriesFromDictionary:inParameters]; 36 | } 37 | 38 | if ([inSubject length]) { 39 | [params setObject:inSubject forKey:@"sSubject"]; 40 | } 41 | 42 | if ([inText length]) { 43 | [params setObject:inText forKey:@"sEvent"]; 44 | } 45 | 46 | if ([inFrom length]) { 47 | [params setObject:inFrom forKey:@"sFrom"]; 48 | } 49 | 50 | if ([inTo length]) { 51 | [params setObject:inTo forKey:@"sTo"]; 52 | } 53 | 54 | if ([inCC length]) { 55 | [params setObject:inCC forKey:@"sCC"]; 56 | } 57 | 58 | if ([inBCC length]) { 59 | [params setObject:inBCC forKey:@"sBCC"]; 60 | } 61 | 62 | self = [super initWithAPIContext:inAPIContext editAction:inAction caseNumber:inCaseNumber parameters:params attachmentURLs:inURLs attachmentsFromBugEventID:inEventID]; 63 | if (self) { 64 | } 65 | 66 | return self; 67 | } 68 | 69 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext editAction:(NSString *)inAction caseNumber:(NSUInteger)inCaseNumber text:(NSString *)inText subject:(NSString *)inSubject from:(NSString *)inFrom to:(NSString *)inTo CC:(NSString *)inCC BCC:(NSString *)inBCC attachmentURLs:(NSArray *)inURLs attachmentsFromBugEventID:(NSUInteger)inEventID 70 | { 71 | return [self initWithAPIContext:inAPIContext editAction:inAction caseNumber:inCaseNumber parameters:nil text:inText subject:inSubject from:inFrom to:inTo CC:inCC BCC:inBCC attachmentURLs:inURLs attachmentsFromBugEventID:inEventID]; 72 | } 73 | @end 74 | -------------------------------------------------------------------------------- /Source/BKMarkAsViewedRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKMarkAsViewedRequest.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKRequest.h" 29 | 30 | @interface BKMarkAsViewedRequest : BKRequest 31 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext caseNumber:(NSUInteger)inCaseNumber; 32 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext caseNumber:(NSUInteger)inCaseNumber eventID:(NSUInteger)inEventID; 33 | @end 34 | -------------------------------------------------------------------------------- /Source/BKMarkAsViewedRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // BKMarkAsViewedRequest.m 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKMarkAsViewedRequest.h" 29 | 30 | @implementation BKMarkAsViewedRequest 31 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext caseNumber:(NSUInteger)inCaseNumber 32 | { 33 | return [self initWithAPIContext:inAPIContext caseNumber:inCaseNumber eventID:NSUIntegerMax]; 34 | } 35 | 36 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext caseNumber:(NSUInteger)inCaseNumber eventID:(NSUInteger)inEventID 37 | { 38 | self = [super initWithAPIContext:inAPIContext]; 39 | if (self) { 40 | NSMutableDictionary *d = [NSMutableDictionary dictionary]; 41 | 42 | [d setObject:inAPIContext.authToken forKey:@"token"]; 43 | [d setObject:@"view" forKey:@"cmd"]; 44 | [d setObject:[NSString stringWithFormat:@"%jd", (uintmax_t)inCaseNumber] forKey:@"ixBug"]; 45 | 46 | if (inEventID != NSUIntegerMax) { 47 | [d setObject:[NSString stringWithFormat:@"%jd", (uintmax_t)inEventID] forKey:@"ixBugEvent"]; 48 | } 49 | 50 | requestParameterDict = [d retain]; 51 | } 52 | 53 | return self; 54 | } 55 | @end 56 | -------------------------------------------------------------------------------- /Source/BKPrivateUtilities.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKPrivateUtilities.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import 29 | 30 | #define BKRetainAssign(foo, bar) do { id tmp = foo; foo = [(id)bar retain]; [tmp release]; } while(0) 31 | #define BKReleaseClean(foo) do { id tmp = (foo); foo = nil; [tmp release]; } while(0) 32 | #define BKAutoreleasedCopy(foo) ([[foo copy] autorelease]) 33 | 34 | #define BKNotNil(x) (x ? (id)x : (id)[NSNull null]) 35 | #define BKNotNSNull(x) (x == [NSNull null] ? nil : x) 36 | 37 | NS_INLINE NSString *BKEscapedURLStringFromNSString(NSString *inStr) 38 | { 39 | CFStringRef escaped = CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)inStr, NULL, CFSTR("&+"), kCFStringEncodingUTF8); 40 | 41 | #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 42 | return (NSString *)[escaped autorelease]; 43 | #else 44 | return (NSString *)[NSMakeCollectable(escaped) autorelease]; 45 | #endif 46 | } 47 | 48 | NS_INLINE NSString *BKPlistString(id plist) 49 | { 50 | NSString *error; 51 | NSData *data = [NSPropertyListSerialization dataFromPropertyList:plist format:NSPropertyListXMLFormat_v1_0 errorDescription:&error]; 52 | 53 | if (!data) { 54 | return @"(not a valid plist)"; 55 | } 56 | 57 | return [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]; 58 | } 59 | 60 | NS_INLINE NSString *BKQuotedString(id s) 61 | { 62 | if (s) { 63 | if ([s isKindOfClass:[NSURL class]]) { 64 | return [NSString stringWithFormat:@"\"%@\"", [s absoluteString]]; 65 | } 66 | 67 | return [NSString stringWithFormat:@"\"%@\"", [s description]]; 68 | } 69 | 70 | return nil; 71 | } 72 | 73 | NS_INLINE NSString *BKGenerateUUID() 74 | { 75 | CFUUIDRef uuid = CFUUIDCreate(NULL); 76 | CFStringRef uuidStr = CFUUIDCreateString(NULL, uuid); 77 | CFRelease(uuid); 78 | return [NSMakeCollectable(uuidStr) autorelease]; 79 | } 80 | -------------------------------------------------------------------------------- /Source/BKQueryCaseRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKQueryCaseRequest.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKRequest.h" 29 | 30 | @interface BKQueryCaseRequest : BKRequest 31 | + (id)requestWithAPIContext:(BKAPIContext *)inAPIContext query:(NSString *)inQuery columns:(NSArray *)inColumnNames DEPRECATED_ATTRIBUTE; 32 | + (id)requestWithAPIContext:(BKAPIContext *)inAPIContext query:(NSString *)inQuery columns:(NSArray *)inColumnNames maximum:(NSUInteger)inMaximum DEPRECATED_ATTRIBUTE; 33 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext query:(NSString *)inQuery columns:(NSArray *)inColumnNames; 34 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext query:(NSString *)inQuery columns:(NSArray *)inColumnNames maximum:(NSUInteger)inMaximum; 35 | 36 | @property (readonly) NSArray *fetchedCases; 37 | @property (readonly) NSString *query; 38 | @end 39 | -------------------------------------------------------------------------------- /Source/BKQueryCaseRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // BKQueryCaseRequest.m 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKQueryCaseRequest.h" 29 | 30 | @implementation BKQueryCaseRequest : BKRequest 31 | + (id)requestWithAPIContext:(BKAPIContext *)inAPIContext query:(NSString *)inQuery columns:(NSArray *)inColumnNames 32 | { 33 | return [[[self alloc] initWithAPIContext:inAPIContext query:inQuery columns:inColumnNames maximum:NSUIntegerMax] autorelease]; 34 | } 35 | 36 | + (id)requestWithAPIContext:(BKAPIContext *)inAPIContext query:(NSString *)inQuery columns:(NSArray *)inColumnNames maximum:(NSUInteger)inMaximum 37 | { 38 | return [[[self alloc] initWithAPIContext:inAPIContext query:inQuery columns:inColumnNames maximum:inMaximum] autorelease]; 39 | } 40 | 41 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext query:(NSString *)inQuery columns:(NSArray *)inColumnNames maximum:(NSUInteger)inMaximum 42 | { 43 | self = [super initWithAPIContext:inAPIContext]; 44 | if (self) { 45 | NSMutableDictionary *d = [NSMutableDictionary dictionary]; 46 | 47 | [d setObject:inAPIContext.authToken forKey:@"token"]; 48 | [d setObject:@"search" forKey:@"cmd"]; 49 | 50 | if (inQuery) { 51 | [d setObject:inQuery forKey:@"q"]; 52 | } 53 | 54 | if ([inColumnNames count]) { 55 | [d setObject:[inColumnNames componentsJoinedByString:@","] forKey:@"cols"]; 56 | } 57 | 58 | if (inMaximum && inMaximum != NSUIntegerMax) { 59 | [d setObject:[NSString stringWithFormat:@"%jd", (uintmax_t)inMaximum] forKey:@"max"]; 60 | } 61 | 62 | requestParameterDict = [d retain]; 63 | } 64 | 65 | return self; 66 | } 67 | 68 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext query:(NSString *)inQuery columns:(NSArray *)inColumnNames 69 | { 70 | return [self initWithAPIContext:inAPIContext query:inQuery columns:inColumnNames maximum:NSUIntegerMax]; 71 | } 72 | 73 | - (id)postprocessResponse:(NSDictionary *)inXMLMappedResponse 74 | { 75 | id result = [inXMLMappedResponse valueForKeyPath:@"cases.case"]; 76 | if (!result) { 77 | result = [NSArray array]; 78 | } 79 | 80 | return result; 81 | } 82 | 83 | - (NSArray *)fetchedCases 84 | { 85 | return processedResponse; 86 | } 87 | 88 | - (NSString *)query 89 | { 90 | return [requestParameterDict objectForKey:@"q"]; 91 | } 92 | @end 93 | -------------------------------------------------------------------------------- /Source/BKQueryEventRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKQueryEventRequest.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKQueryCaseRequest.h" 29 | 30 | // TODO: Deprecate this class 31 | @interface BKQueryEventRequest : BKQueryCaseRequest 32 | + (id)requestWithAPIContext:(BKAPIContext *)inAPIContext caseNumber:(NSUInteger)inCaseNumber DEPRECATED_ATTRIBUTE; 33 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext caseNumber:(NSUInteger)inCaseNumber; 34 | 35 | @property (readonly) NSArray *fetchedEvents; 36 | @end 37 | -------------------------------------------------------------------------------- /Source/BKQueryEventRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // BKQueryEventRequest.m 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKQueryEventRequest.h" 29 | 30 | @implementation BKQueryEventRequest : BKQueryCaseRequest 31 | + (id)requestWithAPIContext:(BKAPIContext *)inAPIContext caseNumber:(NSUInteger)inCaseNumber 32 | { 33 | return [[[self alloc] initWithAPIContext:inAPIContext caseNumber:inCaseNumber] autorelease]; 34 | } 35 | 36 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext caseNumber:(NSUInteger)inCaseNumber 37 | { 38 | self = [super initWithAPIContext:inAPIContext query:[NSString stringWithFormat:@"%ju", (uintmax_t)inCaseNumber] columns:[NSArray arrayWithObject:@"events"]]; 39 | if (self) { 40 | } 41 | 42 | return self; 43 | } 44 | 45 | - (NSArray *)fetchedEvents 46 | { 47 | NSArray *cases = [self fetchedCases]; 48 | 49 | if ([cases count]) { 50 | return [[cases objectAtIndex:0] valueForKeyPath:@"events.event"]; 51 | } 52 | 53 | return [NSArray array]; 54 | } 55 | @end 56 | -------------------------------------------------------------------------------- /Source/BKRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKRequest.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKAPIContext.h" 29 | 30 | @class BKRequest; 31 | 32 | @interface BKRequest : NSObject 33 | { 34 | BKAPIContext *APIContext; 35 | NSDictionary *requestParameterDict; 36 | 37 | NSDictionary *rawXMLMappedResponse; 38 | id processedResponse; 39 | NSError *error; 40 | } 41 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext; 42 | 43 | // methods to be overriden by subclasses 44 | - (void)postprocessError:(NSError *)inError; 45 | - (id)postprocessResponse:(NSDictionary *)inXMLMappedResponse; 46 | - (NSError *)validateResponse:(NSDictionary *)inXMLMappedResponse; 47 | 48 | // properties used by request drivers 49 | @property (readonly, nonatomic) NSString *HTTPRequestContentType; 50 | @property (readonly, nonatomic) NSData *requestData; 51 | @property (readonly, nonatomic) NSInputStream *requestInputStream; 52 | @property (readonly, nonatomic) NSUInteger requestInputStreamSize; 53 | @property (readonly, nonatomic) NSURL *requestURL; 54 | @property (readonly, nonatomic) BOOL usesPOSTRequest; 55 | 56 | // response 57 | @property (retain, nonatomic) NSDictionary *rawXMLMappedResponse; 58 | @property (retain, nonatomic) id processedResponse; 59 | @property (retain, nonatomic) NSError *error; 60 | @end 61 | -------------------------------------------------------------------------------- /Source/BKRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // BKRequest.m 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | // OTHER DEALINGS IN THE SOFTWARE. 27 | // 28 | 29 | #import "BKRequest.h" 30 | #import "BKError.h" 31 | #import "BKPrivateUtilities.h" 32 | #import "BKXMLMapper.h" 33 | 34 | @interface BKRequest (PrivateMethods) 35 | - (NSError *)errorFromXMLMappedResponse:(NSDictionary *)inXMLMappedResponse; 36 | - (NSString *)preparedParameterString; 37 | @end 38 | 39 | 40 | @implementation BKRequest 41 | - (void)dealloc 42 | { 43 | [APIContext release], APIContext = nil; 44 | [requestParameterDict release], requestParameterDict = nil; 45 | [rawXMLMappedResponse release], rawXMLMappedResponse = nil; 46 | [processedResponse release], processedResponse = nil; 47 | [error release], error = nil; 48 | [super dealloc]; 49 | } 50 | 51 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext 52 | { 53 | self = [super init]; 54 | if (self) { 55 | APIContext = [inAPIContext retain]; 56 | } 57 | 58 | return self; 59 | } 60 | 61 | #pragma mark NSObject methods 62 | 63 | - (NSString *)description 64 | { 65 | return [NSString stringWithFormat:@"<%@: %p> {APIContext: %p, req params: %@}", [self class], self, APIContext, requestParameterDict]; 66 | } 67 | 68 | #pragma mark Methods to be overriden 69 | 70 | - (void)postprocessError:(NSError *)inError 71 | { 72 | } 73 | 74 | - (id)postprocessResponse:(NSDictionary *)inXMLMappedResponse 75 | { 76 | return inXMLMappedResponse; 77 | } 78 | 79 | - (NSError *)validateResponse:(NSDictionary *)inXMLMappedResponse 80 | { 81 | return nil; 82 | } 83 | 84 | #pragma mark Dynamic properties 85 | 86 | - (NSString *)HTTPRequestContentType 87 | { 88 | return @"application/x-www-form-urlencoded"; 89 | } 90 | 91 | - (NSData *)requestData 92 | { 93 | if (self.usesPOSTRequest) { 94 | return [[self preparedParameterString] dataUsingEncoding:NSUTF8StringEncoding]; 95 | } 96 | 97 | return nil; 98 | } 99 | 100 | - (NSInputStream *)requestInputStream 101 | { 102 | return nil; 103 | } 104 | 105 | - (NSUInteger)requestInputStreamSize 106 | { 107 | return 0; 108 | } 109 | 110 | - (NSURL *)requestURL 111 | { 112 | if (!self.usesPOSTRequest) { 113 | NSString *paramsString = [self preparedParameterString]; 114 | 115 | return [paramsString length] ? [NSURL URLWithString:[@"?" stringByAppendingString:paramsString] relativeToURL:APIContext.endpoint] : APIContext.endpoint; 116 | } 117 | 118 | return APIContext.endpoint; 119 | } 120 | 121 | - (BOOL)usesPOSTRequest 122 | { 123 | return NO; 124 | } 125 | 126 | 127 | #pragma mark Dynamic setters 128 | 129 | - (void)setRawXMLMappedResponse:(NSDictionary *)inMappedXMLDictionary 130 | { 131 | NSDictionary *innerResponse = [inMappedXMLDictionary objectForKey:@"response"]; 132 | 133 | // TODO: Determine if we should handle, e.g. empty response, etc. 134 | 135 | NSError *responseError = [self errorFromXMLMappedResponse:innerResponse]; 136 | if (!responseError) { 137 | responseError = [self validateResponse:innerResponse]; 138 | } 139 | 140 | if (responseError) { 141 | BKReleaseClean(rawXMLMappedResponse); 142 | BKReleaseClean(processedResponse); 143 | BKRetainAssign(error, responseError); 144 | return; 145 | } 146 | 147 | BKReleaseClean(error); 148 | 149 | // TODO: Add a flag saying we don't need to do this--or altogether? 150 | BKRetainAssign(rawXMLMappedResponse, inMappedXMLDictionary); 151 | BKRetainAssign(processedResponse, [self postprocessResponse:innerResponse]); 152 | } 153 | 154 | - (void)setProcessedResponse:(id)inResponse 155 | { 156 | BKRetainAssign(processedResponse, inResponse); 157 | BKReleaseClean(error); 158 | BKReleaseClean(rawXMLMappedResponse); 159 | } 160 | 161 | - (void)setError:(NSError *)inError 162 | { 163 | BKRetainAssign(error, inError); 164 | BKReleaseClean(rawXMLMappedResponse); 165 | BKReleaseClean(processedResponse); 166 | } 167 | 168 | @synthesize rawXMLMappedResponse; 169 | @synthesize processedResponse; 170 | @synthesize error; 171 | @end 172 | 173 | 174 | @implementation BKRequest (PrivateMethods) 175 | - (NSError *)errorFromXMLMappedResponse:(NSDictionary *)inXMLMappedResponse 176 | { 177 | NSDictionary *errorDictionary = [inXMLMappedResponse objectForKey:@"error"]; 178 | if ([errorDictionary count]) { 179 | NSString *errorDomain = BKAPIErrorDomain; 180 | NSString *localizedMessage = NSLocalizedString(errorDictionary.textContent, nil); 181 | NSInteger errorCode = [[errorDictionary objectForKey:@"code"] integerValue]; 182 | 183 | return [NSError errorWithDomain:errorDomain code:errorCode userInfo:(!localizedMessage ? nil : [NSDictionary dictionaryWithObjectsAndKeys:localizedMessage, NSLocalizedDescriptionKey, nil])]; 184 | } 185 | 186 | return nil; 187 | } 188 | 189 | - (NSString *)preparedParameterString 190 | { 191 | NSDictionary *dict = requestParameterDict; 192 | NSMutableArray *params = [NSMutableArray array]; 193 | for (NSString *key in dict) { 194 | id value = [dict objectForKey:key]; 195 | 196 | if (value == [NSNull null]) { 197 | value = @""; 198 | } 199 | else if ([value isKindOfClass:[NSNumber class]]) { 200 | value = [value stringValue]; 201 | } 202 | else if ([value isKindOfClass:[NSDate class]]) { 203 | CFLocaleRef currentLocale = CFLocaleCopyCurrent(); 204 | CFTimeZoneRef timeZone = CFTimeZoneCreateWithName(NULL, (CFStringRef)@"GMT", NO); 205 | CFDateFormatterRef dateFormatter = CFDateFormatterCreate(NULL, currentLocale, kCFDateFormatterFullStyle, kCFDateFormatterFullStyle); 206 | CFDateFormatterSetProperty(dateFormatter, kCFDateFormatterTimeZone, timeZone); 207 | CFDateFormatterSetFormat(dateFormatter, (CFStringRef)@"yyyy-MM-dd'T'HH:mm:ss'Z'"); 208 | 209 | value = [NSMakeCollectable(CFDateFormatterCreateStringWithDate(NULL, dateFormatter, (CFDateRef)value)) autorelease]; 210 | 211 | CFRelease(dateFormatter); 212 | CFRelease(timeZone); 213 | CFRelease(currentLocale); 214 | } 215 | 216 | [params addObject:[NSString stringWithFormat:@"%@=%@", key, BKEscapedURLStringFromNSString(value)]]; 217 | } 218 | 219 | return [params count] ? [params componentsJoinedByString:@"&"] : nil; 220 | } 221 | @end 222 | -------------------------------------------------------------------------------- /Source/BKRequestOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKRequestOperation.h 3 | // 4 | // Copyright (c) 2009-2011 Lithoglyph Inc. All rights reserved. 5 | // 6 | 7 | #import "BKRequest.h" 8 | 9 | @interface BKRequestOperation : NSOperation 10 | { 11 | BKRequest *request; 12 | } 13 | - (id)initWithRequest:(BKRequest *)inRequest; 14 | 15 | // Override these (no need to call super) 16 | - (void)fetchMappedXMLData; 17 | - (void)cancelFetch; 18 | 19 | // The default behavior is to invoke the selector in the same thread; you might want to do otherwise (no need to call super if overriden) 20 | - (void)dispatchSelector:(SEL)inSelector; 21 | 22 | // Override these (no need to call super if overriden) 23 | - (void)handleRequestStarted; 24 | - (void)handleRequestCancelled; 25 | - (void)processRequestCompletion; // invoked in the same thread of the -main 26 | - (void)handleRequestCompleted; // dispatched, usually in the thread the operation is created 27 | - (void)handleRequestFailed; 28 | - (void)handleRequestOperationEnded; 29 | 30 | // Internal handler for dependency-caused cancellation, invoked by -main 31 | - (void)handleDependencyCancellation; 32 | 33 | @property (readonly) BKRequest *request; 34 | @end 35 | -------------------------------------------------------------------------------- /Source/BKRequestOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // BKRequestOperation.m 3 | // 4 | // Copyright (c) 2009-2011 Lithoglyph Inc. All rights reserved. 5 | // 6 | 7 | #import "BKRequestOperation.h" 8 | #import "BKPrivateUtilities.h" 9 | 10 | @implementation BKRequestOperation 11 | - (void)dealloc 12 | { 13 | BKReleaseClean(request); 14 | [super dealloc]; 15 | } 16 | 17 | - (id)initWithRequest:(BKRequest *)inRequest 18 | { 19 | self = [super init]; 20 | if (self) { 21 | request = [inRequest retain]; 22 | } 23 | 24 | return self; 25 | } 26 | 27 | - (void)fetchMappedXMLData; 28 | { 29 | } 30 | 31 | - (void)cancelFetch 32 | { 33 | } 34 | 35 | // The default behavior is to invoke the selector in the same thread; you might want to do otherwise (no need to call super if overriden) 36 | - (void)dispatchSelector:(SEL)inSelector 37 | { 38 | [self performSelector:inSelector]; 39 | } 40 | 41 | // Override these (no need to call super if overriden) 42 | - (void)handleRequestStarted 43 | { 44 | } 45 | 46 | - (void)handleRequestCancelled 47 | { 48 | } 49 | 50 | - (void)processRequestCompletion 51 | { 52 | } 53 | 54 | - (void)handleRequestCompleted 55 | { 56 | } 57 | 58 | - (void)handleRequestFailed 59 | { 60 | } 61 | 62 | - (void)handleRequestOperationEnded 63 | { 64 | } 65 | 66 | // Internal handler 67 | 68 | - (void)handleDependencyCancellation 69 | { 70 | [self cancel]; 71 | } 72 | 73 | #pragma mark Overriden NSOperationQueue methods 74 | 75 | - (void)cancel 76 | { 77 | BOOL alreadyCanceled = [self isCancelled]; 78 | BOOL alreadyFinished = [self isFinished]; 79 | 80 | [super cancel]; 81 | 82 | if (!alreadyCanceled && !alreadyFinished) { 83 | [self cancelFetch]; 84 | [self dispatchSelector:@selector(handleRequestCancelled)]; 85 | [self dispatchSelector:@selector(handleRequestOperationEnded)]; 86 | } 87 | } 88 | 89 | - (void)main 90 | { 91 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 92 | 93 | // see if any of the dependencies is cancelled or has error 94 | BOOL allDependenciesCompleted = YES; 95 | for (BKRequestOperation *dependency in [self dependencies]) { 96 | if ([dependency isCancelled] || ([dependency isKindOfClass:[BKRequestOperation class]] && dependency.request.error)) { 97 | allDependenciesCompleted = NO; 98 | break; 99 | } 100 | } 101 | 102 | if (allDependenciesCompleted) { 103 | [self dispatchSelector:@selector(handleRequestStarted)]; 104 | 105 | [self fetchMappedXMLData]; 106 | 107 | if (![self isCancelled]) { 108 | if (request.error || !request.rawXMLMappedResponse) { 109 | [self dispatchSelector:@selector(handleRequestFailed)]; 110 | } 111 | else { 112 | [self processRequestCompletion]; 113 | [self dispatchSelector:@selector(handleRequestCompleted)]; 114 | } 115 | 116 | [self dispatchSelector:@selector(handleRequestOperationEnded)]; 117 | } 118 | } 119 | else { 120 | [self handleDependencyCancellation]; 121 | } 122 | 123 | [pool drain]; 124 | } 125 | 126 | @synthesize request; 127 | @end 128 | -------------------------------------------------------------------------------- /Source/BKSetCurrentFilterRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKSetCurrentFilterRequest.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKRequest.h" 29 | 30 | @interface BKSetCurrentFilterRequest : BKRequest 31 | { 32 | NSString *filterName; 33 | } 34 | + (id)requestWithAPIContext:(BKAPIContext *)inAPIContext filterName:(NSString *)inFilterName DEPRECATED_ATTRIBUTE; 35 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext filterName:(NSString *)inFilterName; 36 | 37 | @property (readonly) NSString *filterName; 38 | @end 39 | -------------------------------------------------------------------------------- /Source/BKSetCurrentFilterRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // BKSetCurrentFilterRequest.m 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKSetCurrentFilterRequest.h" 29 | 30 | @implementation BKSetCurrentFilterRequest 31 | - (void)dealloc 32 | { 33 | [filterName release]; 34 | [super dealloc]; 35 | } 36 | 37 | + (id)requestWithAPIContext:(BKAPIContext *)inAPIContext filterName:(NSString *)inFilterName 38 | { 39 | return [[[self alloc] initWithAPIContext:inAPIContext filterName:inFilterName] autorelease]; 40 | } 41 | 42 | - (id)initWithAPIContext:(BKAPIContext *)inAPIContext filterName:(NSString *)inFilterName 43 | { 44 | self = [super initWithAPIContext:inAPIContext]; 45 | if (self) { 46 | filterName = [inFilterName copy]; 47 | 48 | // TODO: Check if API keeps the name 49 | // TODO: Ask if there's a way to set the sFilter to none 50 | requestParameterDict = [[NSDictionary dictionaryWithObjectsAndKeys:@"setCurrentFilter", @"cmd", inAPIContext.authToken, @"token", ([inFilterName length] ? inFilterName : @"inbox"), @"sFilter", nil] retain]; 51 | } 52 | 53 | return self; 54 | } 55 | 56 | - (BOOL)usesPOSTRequest 57 | { 58 | return YES; 59 | } 60 | 61 | @synthesize filterName; 62 | @end 63 | -------------------------------------------------------------------------------- /Source/BKXMLMapper.h: -------------------------------------------------------------------------------- 1 | // 2 | // BKXMLMapper.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import 29 | 30 | extern NSString *const BKXMLTextContentKey; 31 | 32 | #if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5 33 | @interface BKXMLMapper : NSObject 34 | #else 35 | @interface BKXMLMapper : NSObject 36 | #endif 37 | { 38 | NSMutableDictionary *resultantDictionary; 39 | 40 | NSMutableArray *elementStack; 41 | NSMutableDictionary *currentDictionary; 42 | NSString *currentElementName; 43 | } 44 | + (NSDictionary *)dictionaryMappedFromXMLData:(NSData *)inData; 45 | @end 46 | 47 | @interface NSDictionary (BKXMLMapperExtension) 48 | - (NSString *)textContent; 49 | - (NSString *)textContentForKey:(NSString *)inKey; 50 | - (NSString *)textContentForKeyPath:(NSString *)inKeyPath; 51 | 52 | #if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 53 | @property (nonatomic, readonly) NSString *textContent; 54 | #endif 55 | @end 56 | -------------------------------------------------------------------------------- /Source/BKXMLMapper.m: -------------------------------------------------------------------------------- 1 | // 2 | // BKXMLMapper.m 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKXMLMapper.h" 29 | 30 | #define BKXMLMAPPER_USER_NSXMLPARSER 31 | 32 | #ifndef BKXMLMAPPER_USER_NSXMLPARSER 33 | // this suppresses (a useless, anyway, on Clang) an annoying "cdecl attribute ignored" warning that we can't turn off 34 | #define XMLCALL 35 | #import 36 | #endif 37 | 38 | #import 39 | #import 40 | 41 | NSString *const BKXMLMapperExceptionName = @"BKXMLMapperException"; 42 | NSString *const BKXMLTextContentKey = @"_text"; 43 | 44 | #ifndef BKXMLMAPPER_USER_NSXMLPARSER 45 | static void BKXMExpatParserStart(void *inContext, const char *inElement, const char **attributes); 46 | static void BKXMExpatParserEnd(void *inContext, const char *inElement); 47 | static void BKXMExpatParserCharData(void *inContext, const XML_Char *inString, int inLength); 48 | #endif 49 | 50 | @interface BKXMLMapper (Flattener) 51 | - (NSArray *)flattenedArray:(NSArray *)inArray; 52 | - (id)flattenedDictionary:(NSDictionary *)inDictionary; 53 | - (id)transformValue:(id)inValue usingTypeInferredFromKey:(NSString *)inKey; 54 | @end 55 | 56 | @implementation BKXMLMapper 57 | - (void)dealloc 58 | { 59 | [resultantDictionary release]; 60 | [elementStack release]; 61 | [currentElementName release]; 62 | [super dealloc]; 63 | } 64 | 65 | - (id)init 66 | { 67 | self = [super init]; 68 | if (self) { 69 | resultantDictionary = [[NSMutableDictionary alloc] init]; 70 | elementStack = [[NSMutableArray alloc] init]; 71 | } 72 | 73 | return self; 74 | } 75 | 76 | - (void)runWithData:(NSData *)inData 77 | { 78 | currentDictionary = resultantDictionary; 79 | 80 | @synchronized([BKXMLMapper class]) { 81 | #ifdef BKXMLMAPPER_USER_NSXMLPARSER 82 | NSXMLParser *parser = [[NSXMLParser alloc] initWithData:inData]; 83 | [parser setDelegate:self]; 84 | [parser parse]; 85 | [parser release]; 86 | parser = nil; 87 | #else 88 | XML_Parser parser = XML_ParserCreate("UTF-8"); 89 | XML_SetElementHandler(parser, BKXMExpatParserStart, BKXMExpatParserEnd); 90 | XML_SetCharacterDataHandler(parser, BKXMExpatParserCharData); 91 | XML_SetUserData(parser, self); 92 | XML_Parse(parser, [inData bytes], [inData length], 1); 93 | XML_ParserFree(parser); 94 | #endif 95 | } 96 | } 97 | 98 | - (NSMutableDictionary *)resultantDictionary 99 | { 100 | return [[resultantDictionary retain] autorelease]; 101 | } 102 | 103 | - (id)transformValue:(id)inValue usingTypeInferredFromKey:(NSString *)inKey 104 | { 105 | // exceptions: s (returned directly), dt (date), hrs (NSTimeInterval), c (integer) 106 | // only two exceptions: s (returned directly), dt (date) 107 | 108 | NSUInteger length = [inKey length]; 109 | 110 | if (length < 2) { 111 | if ([inKey isEqualToString:@"c"]) { 112 | return [NSNumber numberWithUnsignedInteger:[inValue integerValue]]; 113 | } 114 | 115 | if ([inKey isEqualToString:@"s"] && [inValue isKindOfClass:[NSDictionary class]] && ![inValue count]) { 116 | // s cannot be an empty dictionary--must be a string 117 | inValue = @""; 118 | } 119 | 120 | return inValue; 121 | } 122 | 123 | UniChar firstChar = [inKey characterAtIndex:0]; 124 | UniChar secondChar = [inKey characterAtIndex:1]; 125 | UniChar thirdChar = length > 2 ? [inKey characterAtIndex:2] : 0; 126 | BOOL secondCharIsUpperCase = (secondChar >= 'A' && secondChar <= 'Z'); 127 | BOOL thirdCharIsUpperCase = [inKey isEqualToString:@"dt"] ? YES : (thirdChar >= 'A' && thirdChar <= 'Z'); 128 | 129 | // 's[A-Z][a-z]+ cannot be an empty dictionary 130 | if (firstChar == 's' && secondCharIsUpperCase && [inValue isKindOfClass:[NSDictionary class]] && ![inValue count]) { 131 | return @""; 132 | } 133 | 134 | // other than that, returns everything 135 | if (![inValue isKindOfClass:[NSString class]]) { 136 | return inValue; 137 | } 138 | 139 | 140 | // transform 'f' or 'b' 141 | if ((firstChar == 'f' || firstChar == 'b') && secondCharIsUpperCase) { 142 | return [inValue isEqualToString:@"true"] ? (id)kCFBooleanTrue : (id)kCFBooleanFalse; 143 | } 144 | 145 | // transform 'ix' 146 | if (firstChar == 'i' && secondChar == 'x' && thirdCharIsUpperCase) { 147 | 148 | // if it's ixBugChildren or ixRelatedBugs, don't translate it 149 | if (length == 13 && ([inKey isEqualToString:@"ixBugChildren"] || [inKey isEqualToString:@"ixRelatedBugs"])) { 150 | return inValue; 151 | } 152 | 153 | return [NSNumber numberWithUnsignedInteger:[inValue integerValue]]; 154 | } 155 | 156 | // transform 'i' or 'n' or 'c' 157 | if ((firstChar == 'i' || firstChar == 'n' || firstChar == 'c') && secondCharIsUpperCase) { 158 | return [NSNumber numberWithInteger:[inValue integerValue]]; 159 | } 160 | 161 | // transform 'dt' 162 | if (firstChar == 'd' && secondChar == 't' && thirdCharIsUpperCase) { 163 | NSAssert([inValue isKindOfClass:[NSString class]], @"must be string"); 164 | 165 | struct tm *t = (struct tm *)calloc(1, sizeof(struct tm)); 166 | time_t gmt = 0; 167 | 168 | // 12345678901234567890 169 | // 2011-01-04T10:06:24Z 170 | NSUInteger inValueLength = [inValue length]; 171 | 172 | if (inValueLength >= 10) { 173 | t->tm_year = (int)[[inValue substringWithRange:NSMakeRange(0, 4)] integerValue] - 1900; 174 | t->tm_mon = (int)[[inValue substringWithRange:NSMakeRange(5, 2)] integerValue] - 1; 175 | t->tm_mday = (int)[[inValue substringWithRange:NSMakeRange(8, 2)] integerValue]; 176 | } 177 | 178 | if (inValueLength >= 16) { 179 | t->tm_hour = (int)[[inValue substringWithRange:NSMakeRange(11, 2)] integerValue]; 180 | t->tm_min = (int)[[inValue substringWithRange:NSMakeRange(14, 2)] integerValue]; 181 | } 182 | 183 | if (inValueLength >= 20) { 184 | t->tm_sec = (int)[[inValue substringWithRange:NSMakeRange(17, 2)] integerValue]; 185 | } 186 | 187 | gmt = timegm(t); 188 | free (t); 189 | 190 | return [[[NSDate alloc] initWithTimeIntervalSince1970:(NSTimeInterval)gmt] autorelease]; 191 | } 192 | 193 | // transform 'hrs' 194 | if (firstChar == 'h' && secondChar == 'r' && thirdChar == 's') { 195 | return [NSNumber numberWithDouble:[inValue doubleValue]]; 196 | } 197 | 198 | return inValue; 199 | } 200 | 201 | - (NSArray *)flattenedArray:(NSArray *)inArray 202 | { 203 | NSMutableArray *flattenedArray = [NSMutableArray array]; 204 | 205 | for (id value in inArray) { 206 | if ([value isKindOfClass:[NSDictionary class]]) { 207 | [flattenedArray addObject:[self flattenedDictionary:value]]; 208 | } 209 | else { 210 | [flattenedArray addObject:value]; 211 | } 212 | } 213 | 214 | return flattenedArray; 215 | } 216 | 217 | - (id)flattenedDictionary:(NSDictionary *)inDictionary 218 | { 219 | if (![inDictionary count]) { 220 | return inDictionary; 221 | } 222 | 223 | NSString *textContent = [inDictionary objectForKey:BKXMLTextContentKey]; 224 | if (textContent && [inDictionary count] == 1) { 225 | return textContent; 226 | } 227 | 228 | NSMutableDictionary *flattenedDictionary = [NSMutableDictionary dictionary]; 229 | 230 | for (NSString *key in inDictionary) { 231 | id value = [inDictionary objectForKey:key]; 232 | 233 | if ([value isKindOfClass:[NSDictionary class]]) { 234 | if ([value count]) { 235 | value = [self flattenedDictionary:value]; 236 | } 237 | else { 238 | value = nil; 239 | } 240 | } 241 | else if ([value isKindOfClass:[NSArray class]]) { 242 | value = [self flattenedArray:value]; 243 | } 244 | else { 245 | } 246 | 247 | if (value) { 248 | value = [self transformValue:value usingTypeInferredFromKey:key]; 249 | [flattenedDictionary setObject:value forKey:key]; 250 | } 251 | } 252 | 253 | return flattenedDictionary; 254 | } 255 | 256 | + (NSDictionary *)dictionaryMappedFromXMLData:(NSData *)inData 257 | { 258 | BKXMLMapper *mapper = [[BKXMLMapper alloc] init]; 259 | [mapper runWithData:inData]; 260 | 261 | // flattens the text contents 262 | NSMutableDictionary *resultantDictionary = [mapper resultantDictionary]; 263 | NSDictionary *result = [mapper flattenedDictionary:resultantDictionary]; 264 | [mapper release]; 265 | mapper = nil; 266 | return result; 267 | } 268 | 269 | - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 270 | { 271 | NSMutableDictionary *mutableAttrDict = attributeDict ? [NSMutableDictionary dictionaryWithDictionary:attributeDict] : [NSMutableDictionary dictionary]; 272 | 273 | // see if it's duplicated 274 | id element; 275 | if ((element = [currentDictionary objectForKey:elementName])) { 276 | if (![element isKindOfClass:[NSMutableArray class]]) { 277 | // FogBugz 8.0 beta bug 278 | if ([elementName isEqualToString:@"c"]) { 279 | // let's overwrite the element 280 | } 281 | else if ([element isKindOfClass:[NSMutableDictionary class]]) { 282 | [element retain]; 283 | [currentDictionary removeObjectForKey:elementName]; 284 | 285 | NSMutableArray *newArray = [NSMutableArray arrayWithObject:element]; 286 | [currentDictionary setObject:newArray forKey:elementName]; 287 | [element release]; 288 | 289 | element = newArray; 290 | } 291 | else { 292 | // ignore, because we have things like and inside a duplicate 17 293 | } 294 | } 295 | 296 | if ([element isKindOfClass:[NSMutableArray class]]) { 297 | [element addObject:mutableAttrDict]; 298 | } 299 | } 300 | else { 301 | // plural tag rule: if the parent's tag is plural and the incoming is singular, we'll make it into an array (we only handles the -s case) 302 | 303 | if ([currentElementName length] > [elementName length] && [currentElementName hasPrefix:elementName] && [currentElementName hasSuffix:@"s"]) { 304 | [currentDictionary setObject:[NSMutableArray arrayWithObject:mutableAttrDict] forKey:elementName]; 305 | } 306 | else if ([currentElementName length] > [elementName length] && [elementName hasSuffix:@"s"] && [currentElementName hasSuffix:@"ses"]) { 307 | // status, statuses 308 | [currentDictionary setObject:[NSMutableArray arrayWithObject:mutableAttrDict] forKey:elementName]; 309 | } 310 | else if ([currentElementName length] > [elementName length] && [elementName hasSuffix:@"x"] && [currentElementName hasSuffix:@"xes"]) { 311 | // box, boxes 312 | [currentDictionary setObject:[NSMutableArray arrayWithObject:mutableAttrDict] forKey:elementName]; 313 | } 314 | else if ([currentElementName length] > [elementName length] && [elementName hasSuffix:@"y"] && [currentElementName hasSuffix:@"ies"]) { 315 | // category, categories 316 | // priority, priorities 317 | [currentDictionary setObject:[NSMutableArray arrayWithObject:mutableAttrDict] forKey:elementName]; 318 | } 319 | 320 | else if ([currentElementName isEqualToString:@"people"] && [elementName isEqualToString:@"person"]) { 321 | [currentDictionary setObject:[NSMutableArray arrayWithObject:mutableAttrDict] forKey:elementName]; 322 | } 323 | else { 324 | [currentDictionary setObject:mutableAttrDict forKey:elementName]; 325 | } 326 | } 327 | 328 | [elementStack insertObject:currentDictionary atIndex:0]; 329 | currentDictionary = mutableAttrDict; 330 | 331 | NSString *tmp = currentElementName; 332 | currentElementName = [elementName retain]; 333 | [tmp release]; 334 | } 335 | 336 | - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 337 | { 338 | if (![elementStack count]) { 339 | @throw [NSException exceptionWithName:BKXMLMapperExceptionName reason:@"Unbalanced XML element tag closing" userInfo:nil]; 340 | } 341 | 342 | currentDictionary = [elementStack objectAtIndex:0]; 343 | [elementStack removeObjectAtIndex:0]; 344 | } 345 | 346 | - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 347 | { 348 | NSString *existingContent = [currentDictionary objectForKey:BKXMLTextContentKey]; 349 | if (existingContent) { 350 | NSString *newContent = [existingContent stringByAppendingString:string]; 351 | [currentDictionary setObject:newContent forKey:BKXMLTextContentKey]; 352 | } 353 | else { 354 | [currentDictionary setObject:string forKey:BKXMLTextContentKey]; 355 | } 356 | } 357 | 358 | - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError 359 | { 360 | [resultantDictionary release]; 361 | resultantDictionary = nil; 362 | } 363 | @end 364 | 365 | @implementation NSDictionary (BKXMLMapperExtension) 366 | - (NSString *)textContent 367 | { 368 | return [self objectForKey:BKXMLTextContentKey]; 369 | } 370 | 371 | - (NSString *)textContentForKey:(NSString *)inKey 372 | { 373 | return [[self objectForKey:inKey] objectForKey:BKXMLTextContentKey]; 374 | } 375 | 376 | - (NSString *)textContentForKeyPath:(NSString *)inKeyPath 377 | { 378 | return [[self valueForKeyPath:inKeyPath] objectForKey:BKXMLTextContentKey]; 379 | } 380 | @end 381 | 382 | #ifndef BKXMLMAPPER_USER_NSXMLPARSER 383 | 384 | static void BKXMExpatParserStart(void *inContext, const char *inElement, const char **attributes) 385 | { 386 | BKXMLMapper *mapper = (BKXMLMapper *)inContext; 387 | NSString *elementName = [NSString stringWithUTF8String:inElement]; 388 | NSMutableDictionary *attrDict = [NSMutableDictionary dictionary]; 389 | 390 | const char **attr = attributes; 391 | while (*attr) { 392 | const char *key = *attr++; 393 | const char *value = *attr++; 394 | [attrDict setObject:[NSString stringWithUTF8String:value] forKey:[NSString stringWithUTF8String:key]]; 395 | } 396 | 397 | [mapper parser:nil didStartElement:elementName namespaceURI:nil qualifiedName:nil attributes:attrDict]; 398 | } 399 | 400 | static void BKXMExpatParserEnd(void *inContext, const char *inElement) 401 | { 402 | BKXMLMapper *mapper = (BKXMLMapper *)inContext; 403 | NSString *elementName = [NSString stringWithUTF8String:inElement]; 404 | [mapper parser:nil didEndElement:elementName namespaceURI:nil qualifiedName:nil]; 405 | } 406 | 407 | static void BKXMExpatParserCharData(void *inContext, const XML_Char *inString, int inLength) 408 | { 409 | BKXMLMapper *mapper = (BKXMLMapper *)inContext; 410 | 411 | NSString *s = [[[NSString alloc] initWithBytes:inString length:inLength encoding:NSUTF8StringEncoding] autorelease]; 412 | [mapper parser:nil foundCharacters:s]; 413 | } 414 | 415 | #endif 416 | -------------------------------------------------------------------------------- /Source/BugzKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // BugzKit.h 3 | // 4 | // Copyright (c) 2009-2011 Lukhnos D. Liu (http://lukhnos.org) 5 | // 6 | // Permission is hereby granted, free of charge, to any person 7 | // obtaining a copy of this software and associated documentation 8 | // files (the "Software"), to deal in the Software without 9 | // restriction, including without limitation the rights to use, 10 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the 12 | // Software is furnished to do so, subject to the following 13 | // conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be 16 | // included in all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | // OTHER DEALINGS IN THE SOFTWARE. 26 | // 27 | 28 | #import "BKAPIContext.h" 29 | #import "BKError.h" 30 | #import "BKRequest.h" 31 | #import "BKRequestOperation.h" 32 | #import "BKXMLMapper.h" 33 | 34 | // Request classes 35 | #import "BKAreaListRequest.h" 36 | #import "BKCheckVersionRequest.h" 37 | #import "BKEditCaseRequest.h" 38 | #import "BKListRequest.h" 39 | #import "BKListWorkingScheduleRequest.h" 40 | #import "BKLogOffRequest.h" 41 | #import "BKLogOnRequest.h" 42 | #import "BKMailRequest.h" 43 | #import "BKMarkAsViewedRequest.h" 44 | #import "BKQueryCaseRequest.h" 45 | #import "BKQueryEventRequest.h" 46 | #import "BKSetCurrentFilterRequest.h" 47 | --------------------------------------------------------------------------------