appjam 0.1.8.8 → 0.1.8.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. data/README.md +22 -62
  2. data/lib/appjam/generators/gist.yml +1 -1
  3. data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/project.pbxproj +1166 -482
  4. data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/project.xcworkspace/xcuserdata/eiffel.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  5. data/lib/appjam/generators/templates/blank/EiffelApplication/EiffelApplication-Prefix.pch.tt +26 -0
  6. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/AwesomeMenu.h +52 -0
  7. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/AwesomeMenu.m +412 -0
  8. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/AwesomeMenuItem.h +44 -0
  9. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/AwesomeMenuItem.m +97 -0
  10. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-addbutton-highlighted.png +0 -0
  11. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-addbutton-highlighted@2x.png +0 -0
  12. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-addbutton.png +0 -0
  13. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-addbutton@2x.png +0 -0
  14. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-menuitem-highlighted.png +0 -0
  15. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-menuitem-highlighted@2x.png +0 -0
  16. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-menuitem.png +0 -0
  17. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-menuitem@2x.png +0 -0
  18. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-plus-highlighted.png +0 -0
  19. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-plus-highlighted@2x.png +0 -0
  20. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-plus.png +0 -0
  21. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-plus@2x.png +0 -0
  22. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-star.png +0 -0
  23. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-star@2x.png +0 -0
  24. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/CMPopTipView/CMPopTipView.h +167 -0
  25. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/CMPopTipView/CMPopTipView.m +639 -0
  26. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/FXLabel/FXLabel.h +97 -0
  27. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/FXLabel/FXLabel.m +1080 -0
  28. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MBProgressHUD/MBProgressHUD.h +451 -0
  29. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MBProgressHUD/MBProgressHUD.m +865 -0
  30. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/FacingView.h +42 -0
  31. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/FacingView.m +56 -0
  32. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/FoldView.h +90 -0
  33. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/FoldView.m +316 -0
  34. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/MultiFoldView.h +104 -0
  35. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/MultiFoldView.m +516 -0
  36. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldConstants.h +49 -0
  37. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldNavigationController.h +18 -0
  38. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldNavigationController.m +88 -0
  39. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldResources.bundle/swipe_guide_left.png +0 -0
  40. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldResources.bundle/swipe_guide_left@2x.png +0 -0
  41. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldResources.bundle/swipe_guide_right.png +0 -0
  42. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldResources.bundle/swipe_guide_right@2x.png +0 -0
  43. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldSwipeHintView.h +25 -0
  44. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldSwipeHintView.m +76 -0
  45. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldView.h +131 -0
  46. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldView.m +941 -0
  47. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/Resources/swipe_guide.psd +0 -0
  48. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/Resources/swipe_guide2.psd +0 -0
  49. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/ShadowView.h +46 -0
  50. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/ShadowView.m +82 -0
  51. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/TouchThroughUIView.h +39 -0
  52. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/TouchThroughUIView.m +72 -0
  53. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/UIView+Screenshot.h +42 -0
  54. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/UIView+Screenshot.m +100 -0
  55. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/NSBubbleData.h +34 -0
  56. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/NSBubbleData.m +140 -0
  57. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleHeaderTableViewCell.h +17 -0
  58. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleHeaderTableViewCell.m +57 -0
  59. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableView.h +30 -0
  60. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableView.m +233 -0
  61. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableViewCell.h +19 -0
  62. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableViewCell.m +122 -0
  63. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableViewDataSource.h +24 -0
  64. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTypingTableViewCell.h +20 -0
  65. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTypingTableViewCell.m +56 -0
  66. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/bubbleMine.png +0 -0
  67. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/bubbleMine@2x.png +0 -0
  68. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/bubbleSomeone.png +0 -0
  69. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/bubbleSomeone@2x.png +0 -0
  70. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/missingAvatar.png +0 -0
  71. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/missingAvatar@2x.png +0 -0
  72. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/typingMine.png +0 -0
  73. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/typingMine@2x.png +0 -0
  74. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/typingSomeone.png +0 -0
  75. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/typingSomeone@2x.png +0 -0
  76. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIGlossyButton/UIGlossyButton.h +124 -0
  77. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIGlossyButton/UIGlossyButton.m +545 -0
  78. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIGlossyButton/UIView+LayerEffects.h +22 -0
  79. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIGlossyButton/UIView+LayerEffects.m +32 -0
  80. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFIncrementalStore/AFIncrementalStore.h +344 -0
  81. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFIncrementalStore/AFIncrementalStore.m +848 -0
  82. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFIncrementalStore/AFRESTClient.h +135 -0
  83. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFIncrementalStore/AFRESTClient.m +441 -0
  84. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/InflectorKit/NSString+InflectorKit.h +40 -0
  85. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/InflectorKit/NSString+InflectorKit.m +36 -0
  86. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/InflectorKit/TTTStringInflector.h +76 -0
  87. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/InflectorKit/TTTStringInflector.m +270 -0
  88. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/MKAnnotationView+WebCache.h +95 -0
  89. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/MKAnnotationView+WebCache.m +78 -0
  90. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDImageCache.h +144 -0
  91. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDImageCache.m +311 -0
  92. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageCompat.h +40 -0
  93. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageCompat.m +54 -0
  94. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDecoder.h +18 -0
  95. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDecoder.m +70 -0
  96. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDownloader.h +102 -0
  97. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDownloader.m +226 -0
  98. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDownloaderOperation.h +25 -0
  99. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDownloaderOperation.m +339 -0
  100. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageManager.h +167 -0
  101. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageManager.m +244 -0
  102. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageOperation.h +15 -0
  103. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImagePrefetcher.h +58 -0
  104. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImagePrefetcher.m +127 -0
  105. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/UIButton+WebCache.h +173 -0
  106. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/UIButton+WebCache.m +129 -0
  107. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/UIImageView+WebCache.h +140 -0
  108. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/UIImageView+WebCache.m +84 -0
  109. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/CPAnimationProgram.h +28 -0
  110. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/CPAnimationSequence.h +28 -0
  111. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/CPAnimationStep.h +49 -0
  112. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/private/CPAnimationProgram.m +100 -0
  113. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/private/CPAnimationSequence.m +85 -0
  114. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/private/CPAnimationStep.m +122 -0
  115. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaAsyncSocket/GCDAsyncSocket.h +1074 -0
  116. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaAsyncSocket/GCDAsyncSocket.m +7430 -0
  117. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDData.h +14 -0
  118. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDData.m +158 -0
  119. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDNumber.h +12 -0
  120. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDNumber.m +88 -0
  121. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDRange.h +56 -0
  122. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDRange.m +104 -0
  123. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPAuthenticationRequest.h +45 -0
  124. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPAuthenticationRequest.m +195 -0
  125. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPConnection.h +119 -0
  126. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPConnection.m +2708 -0
  127. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPLogging.h +136 -0
  128. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPMessage.h +48 -0
  129. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPMessage.m +113 -0
  130. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPResponse.h +149 -0
  131. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPServer.h +205 -0
  132. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPServer.m +772 -0
  133. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartFormDataParser.h +65 -0
  134. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartFormDataParser.m +529 -0
  135. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartMessageHeader.h +33 -0
  136. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartMessageHeader.m +86 -0
  137. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartMessageHeaderField.h +23 -0
  138. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartMessageHeaderField.m +211 -0
  139. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPAsyncFileResponse.h +75 -0
  140. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPAsyncFileResponse.m +405 -0
  141. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPDataResponse.h +13 -0
  142. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPDataResponse.m +79 -0
  143. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPDynamicFileResponse.h +52 -0
  144. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPDynamicFileResponse.m +292 -0
  145. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPErrorResponse.h +9 -0
  146. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPErrorResponse.m +38 -0
  147. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPFileResponse.h +25 -0
  148. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPFileResponse.m +237 -0
  149. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPRedirectResponse.h +12 -0
  150. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPRedirectResponse.m +73 -0
  151. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/WebSocket.h +105 -0
  152. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/WebSocket.m +791 -0
  153. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DAVConnection.h +7 -0
  154. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DAVConnection.m +160 -0
  155. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DAVResponse.h +11 -0
  156. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DAVResponse.m +372 -0
  157. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DELETEResponse.h +7 -0
  158. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DELETEResponse.m +49 -0
  159. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/PUTResponse.h +8 -0
  160. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/PUTResponse.m +69 -0
  161. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/TFHpple.h +54 -0
  162. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/TFHpple.m +102 -0
  163. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/TFHppleElement.h +103 -0
  164. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/TFHppleElement.m +200 -0
  165. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/XPathQuery.h +10 -0
  166. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/XPathQuery.m +197 -0
  167. data/lib/appjam/version.rb +1 -1
  168. metadata +164 -3
@@ -0,0 +1,7 @@
1
+ #import "HTTPConnection.h"
2
+
3
+ @interface DAVConnection : HTTPConnection {
4
+ id requestContentBody;
5
+ NSOutputStream* requestContentStream;
6
+ }
7
+ @end
@@ -0,0 +1,160 @@
1
+ #import "DAVConnection.h"
2
+ #import "HTTPMessage.h"
3
+ #import "HTTPFileResponse.h"
4
+ #import "HTTPAsyncFileResponse.h"
5
+ #import "PUTResponse.h"
6
+ #import "DELETEResponse.h"
7
+ #import "DAVResponse.h"
8
+ #import "HTTPLogging.h"
9
+
10
+ #define HTTP_BODY_MAX_MEMORY_SIZE (1024 * 1024)
11
+ #define HTTP_ASYNC_FILE_RESPONSE_THRESHOLD (16 * 1024 * 1024)
12
+
13
+ static const int httpLogLevel = HTTP_LOG_LEVEL_WARN;
14
+
15
+ @implementation DAVConnection
16
+
17
+ - (void) dealloc {
18
+ [requestContentStream close];
19
+
20
+ }
21
+
22
+ - (BOOL) supportsMethod:(NSString*)method atPath:(NSString*)path {
23
+ // HTTPFileResponse & HTTPAsyncFileResponse
24
+ if ([method isEqualToString:@"GET"]) return YES;
25
+ if ([method isEqualToString:@"HEAD"]) return YES;
26
+
27
+ // PUTResponse
28
+ if ([method isEqualToString:@"PUT"]) return YES;
29
+
30
+ // DELETEResponse
31
+ if ([method isEqualToString:@"DELETE"]) return YES;
32
+
33
+ // DAVResponse
34
+ if ([method isEqualToString:@"OPTIONS"]) return YES;
35
+ if ([method isEqualToString:@"PROPFIND"]) return YES;
36
+ if ([method isEqualToString:@"MKCOL"]) return YES;
37
+ if ([method isEqualToString:@"MOVE"]) return YES;
38
+ if ([method isEqualToString:@"COPY"]) return YES;
39
+ if ([method isEqualToString:@"LOCK"]) return YES;
40
+ if ([method isEqualToString:@"UNLOCK"]) return YES;
41
+
42
+ return NO;
43
+ }
44
+
45
+ - (BOOL) expectsRequestBodyFromMethod:(NSString*)method atPath:(NSString*)path {
46
+ // PUTResponse
47
+ if ([method isEqualToString:@"PUT"]) {
48
+ return YES;
49
+ }
50
+
51
+ // DAVResponse
52
+ if ([method isEqual:@"PROPFIND"] || [method isEqual:@"MKCOL"]) {
53
+ return [request headerField:@"Content-Length"] ? YES : NO;
54
+ }
55
+ if ([method isEqual:@"LOCK"]) {
56
+ return YES;
57
+ }
58
+
59
+ return NO;
60
+ }
61
+
62
+ - (void) prepareForBodyWithSize:(UInt64)contentLength {
63
+ NSAssert(requestContentStream == nil, @"requestContentStream should be nil");
64
+ NSAssert(requestContentBody == nil, @"requestContentBody should be nil");
65
+
66
+ if (contentLength > HTTP_BODY_MAX_MEMORY_SIZE) {
67
+ requestContentBody = [[NSTemporaryDirectory() stringByAppendingString:[[NSProcessInfo processInfo] globallyUniqueString]] copy];
68
+ requestContentStream = [[NSOutputStream alloc] initToFileAtPath:requestContentBody append:NO];
69
+ [requestContentStream open];
70
+ } else {
71
+ requestContentBody = [[NSMutableData alloc] initWithCapacity:(NSUInteger)contentLength];
72
+ requestContentStream = nil;
73
+ }
74
+ }
75
+
76
+ - (void) processBodyData:(NSData*)postDataChunk {
77
+ NSAssert(requestContentBody != nil, @"requestContentBody should not be nil");
78
+ if (requestContentStream) {
79
+ [requestContentStream write:[postDataChunk bytes] maxLength:[postDataChunk length]];
80
+ } else {
81
+ [(NSMutableData*)requestContentBody appendData:postDataChunk];
82
+ }
83
+ }
84
+
85
+ - (void) finishBody {
86
+ NSAssert(requestContentBody != nil, @"requestContentBody should not be nil");
87
+ if (requestContentStream) {
88
+ [requestContentStream close];
89
+ requestContentStream = nil;
90
+ }
91
+ }
92
+
93
+ - (void)finishResponse {
94
+ NSAssert(requestContentStream == nil, @"requestContentStream should be nil");
95
+ requestContentBody = nil;
96
+
97
+ [super finishResponse];
98
+ }
99
+
100
+ - (NSObject<HTTPResponse>*) httpResponseForMethod:(NSString*)method URI:(NSString*)path {
101
+ if ([method isEqualToString:@"HEAD"] || [method isEqualToString:@"GET"]) {
102
+ NSString* filePath = [self filePathForURI:path allowDirectory:NO];
103
+ if (filePath) {
104
+ NSDictionary* fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:NULL];
105
+ if (fileAttributes) {
106
+ if ([[fileAttributes objectForKey:NSFileSize] unsignedLongLongValue] > HTTP_ASYNC_FILE_RESPONSE_THRESHOLD) {
107
+ return [[HTTPAsyncFileResponse alloc] initWithFilePath:filePath forConnection:self];
108
+ } else {
109
+ return [[HTTPFileResponse alloc] initWithFilePath:filePath forConnection:self];
110
+ }
111
+ }
112
+ }
113
+ }
114
+
115
+ if ([method isEqualToString:@"PUT"]) {
116
+ NSString* filePath = [self filePathForURI:path allowDirectory:YES];
117
+ if (filePath) {
118
+ if ([requestContentBody isKindOfClass:[NSString class]]) {
119
+ return [[PUTResponse alloc] initWithFilePath:filePath headers:[request allHeaderFields] bodyFile:requestContentBody];
120
+ } else if ([requestContentBody isKindOfClass:[NSData class]]) {
121
+ return [[PUTResponse alloc] initWithFilePath:filePath headers:[request allHeaderFields] bodyData:requestContentBody];
122
+ } else {
123
+ HTTPLogError(@"Internal error");
124
+ }
125
+ }
126
+ }
127
+
128
+ if ([method isEqualToString:@"DELETE"]) {
129
+ NSString* filePath = [self filePathForURI:path allowDirectory:YES];
130
+ if (filePath) {
131
+ return [[DELETEResponse alloc] initWithFilePath:filePath];
132
+ }
133
+ }
134
+
135
+ if ([method isEqualToString:@"OPTIONS"] || [method isEqualToString:@"PROPFIND"] || [method isEqualToString:@"MKCOL"] ||
136
+ [method isEqualToString:@"MOVE"] || [method isEqualToString:@"COPY"] || [method isEqualToString:@"LOCK"] || [method isEqualToString:@"UNLOCK"]) {
137
+ NSString* filePath = [self filePathForURI:path allowDirectory:YES];
138
+ if (filePath) {
139
+ NSString* rootPath = [config documentRoot];
140
+ NSString* resourcePath = [filePath substringFromIndex:([rootPath length] + 1)];
141
+ if (requestContentBody) {
142
+ if ([requestContentBody isKindOfClass:[NSString class]]) {
143
+ requestContentBody = [NSData dataWithContentsOfFile:requestContentBody];
144
+ } else if (![requestContentBody isKindOfClass:[NSData class]]) {
145
+ HTTPLogError(@"Internal error");
146
+ return nil;
147
+ }
148
+ }
149
+ return [[DAVResponse alloc] initWithMethod:method
150
+ headers:[request allHeaderFields]
151
+ bodyData:requestContentBody
152
+ resourcePath:resourcePath
153
+ rootPath:rootPath];
154
+ }
155
+ }
156
+
157
+ return nil;
158
+ }
159
+
160
+ @end
@@ -0,0 +1,11 @@
1
+ #import "HTTPResponse.h"
2
+
3
+ @interface DAVResponse : NSObject <HTTPResponse> {
4
+ @private
5
+ UInt64 _offset;
6
+ NSMutableDictionary* _headers;
7
+ NSData* _data;
8
+ NSInteger _status;
9
+ }
10
+ - (id) initWithMethod:(NSString*)method headers:(NSDictionary*)headers bodyData:(NSData*)body resourcePath:(NSString*)resourcePath rootPath:(NSString*)rootPath;
11
+ @end
@@ -0,0 +1,372 @@
1
+ #import <libxml/parser.h>
2
+
3
+ #import "DAVResponse.h"
4
+ #import "HTTPLogging.h"
5
+
6
+ // WebDAV specifications: http://webdav.org/specs/rfc4918.html
7
+
8
+ typedef enum {
9
+ kDAVProperty_ResourceType = (1 << 0),
10
+ kDAVProperty_CreationDate = (1 << 1),
11
+ kDAVProperty_LastModified = (1 << 2),
12
+ kDAVProperty_ContentLength = (1 << 3),
13
+ kDAVAllProperties = kDAVProperty_ResourceType | kDAVProperty_CreationDate | kDAVProperty_LastModified | kDAVProperty_ContentLength
14
+ } DAVProperties;
15
+
16
+ #define kXMLParseOptions (XML_PARSE_NONET | XML_PARSE_RECOVER | XML_PARSE_NOBLANKS | XML_PARSE_COMPACT | XML_PARSE_NOWARNING | XML_PARSE_NOERROR)
17
+
18
+ static const int httpLogLevel = HTTP_LOG_LEVEL_WARN;
19
+
20
+ @implementation DAVResponse
21
+
22
+ static void _AddPropertyResponse(NSString* itemPath, NSString* resourcePath, DAVProperties properties, NSMutableString* xmlString) {
23
+ CFStringRef escapedPath = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)resourcePath, NULL,
24
+ CFSTR("<&>?+"), kCFStringEncodingUTF8);
25
+ if (escapedPath) {
26
+ NSDictionary* attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:itemPath error:NULL];
27
+ BOOL isDirectory = [[attributes fileType] isEqualToString:NSFileTypeDirectory];
28
+ [xmlString appendString:@"<D:response>"];
29
+ [xmlString appendFormat:@"<D:href>%@</D:href>", escapedPath];
30
+ [xmlString appendString:@"<D:propstat>"];
31
+ [xmlString appendString:@"<D:prop>"];
32
+
33
+ if (properties & kDAVProperty_ResourceType) {
34
+ if (isDirectory) {
35
+ [xmlString appendString:@"<D:resourcetype><D:collection/></D:resourcetype>"];
36
+ } else {
37
+ [xmlString appendString:@"<D:resourcetype/>"];
38
+ }
39
+ }
40
+
41
+ if ((properties & kDAVProperty_CreationDate) && [attributes objectForKey:NSFileCreationDate]) {
42
+ NSDateFormatter* formatter = [[NSDateFormatter alloc] init];
43
+ formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
44
+ formatter.timeZone = [NSTimeZone timeZoneWithName:@"GMT"];
45
+ formatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss'+00:00'";
46
+ [xmlString appendFormat:@"<D:creationdate>%@</D:creationdate>", [formatter stringFromDate:[attributes fileCreationDate]]];
47
+ }
48
+
49
+ if ((properties & kDAVProperty_LastModified) && [attributes objectForKey:NSFileModificationDate]) {
50
+ NSDateFormatter* formatter = [[NSDateFormatter alloc] init];
51
+ formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
52
+ formatter.timeZone = [NSTimeZone timeZoneWithName:@"GMT"];
53
+ formatter.dateFormat = @"EEE', 'd' 'MMM' 'yyyy' 'HH:mm:ss' GMT'";
54
+ [xmlString appendFormat:@"<D:getlastmodified>%@</D:getlastmodified>", [formatter stringFromDate:[attributes fileModificationDate]]];
55
+ }
56
+
57
+ if ((properties & kDAVProperty_ContentLength) && !isDirectory && [attributes objectForKey:NSFileSize]) {
58
+ [xmlString appendFormat:@"<D:getcontentlength>%qu</D:getcontentlength>", [attributes fileSize]];
59
+ }
60
+
61
+ [xmlString appendString:@"</D:prop>"];
62
+ [xmlString appendString:@"<D:status>HTTP/1.1 200 OK</D:status>"];
63
+ [xmlString appendString:@"</D:propstat>"];
64
+ [xmlString appendString:@"</D:response>\n"];
65
+ CFRelease(escapedPath);
66
+ }
67
+ }
68
+
69
+ static xmlNodePtr _XMLChildWithName(xmlNodePtr child, const xmlChar* name) {
70
+ while (child) {
71
+ if ((child->type == XML_ELEMENT_NODE) && !xmlStrcmp(child->name, name)) {
72
+ return child;
73
+ }
74
+ child = child->next;
75
+ }
76
+ return NULL;
77
+ }
78
+
79
+ - (id) initWithMethod:(NSString*)method headers:(NSDictionary*)headers bodyData:(NSData*)body resourcePath:(NSString*)resourcePath rootPath:(NSString*)rootPath {
80
+ if ((self = [super init])) {
81
+ _status = 200;
82
+ _headers = [[NSMutableDictionary alloc] init];
83
+
84
+ // 10.1 DAV Header
85
+ if ([method isEqualToString:@"OPTIONS"]) {
86
+ if ([[headers objectForKey:@"User-Agent"] hasPrefix:@"WebDAVFS/"]) { // Mac OS X WebDAV support
87
+ [_headers setObject:@"1, 2" forKey:@"DAV"];
88
+ } else {
89
+ [_headers setObject:@"1" forKey:@"DAV"];
90
+ }
91
+ }
92
+
93
+ // 9.1 PROPFIND Method
94
+ if ([method isEqualToString:@"PROPFIND"]) {
95
+ NSInteger depth;
96
+ NSString* depthHeader = [headers objectForKey:@"Depth"];
97
+ if ([depthHeader isEqualToString:@"0"]) {
98
+ depth = 0;
99
+ } else if ([depthHeader isEqualToString:@"1"]) {
100
+ depth = 1;
101
+ } else {
102
+ HTTPLogError(@"Unsupported DAV depth \"%@\"", depthHeader);
103
+ return nil;
104
+ }
105
+
106
+ DAVProperties properties = 0;
107
+ xmlDocPtr document = xmlReadMemory(body.bytes, (int)body.length, NULL, NULL, kXMLParseOptions);
108
+ if (document) {
109
+ xmlNodePtr node = _XMLChildWithName(document->children, (const xmlChar*)"propfind");
110
+ if (node) {
111
+ node = _XMLChildWithName(node->children, (const xmlChar*)"prop");
112
+ }
113
+ if (node) {
114
+ node = node->children;
115
+ while (node) {
116
+ if (!xmlStrcmp(node->name, (const xmlChar*)"resourcetype")) {
117
+ properties |= kDAVProperty_ResourceType;
118
+ } else if (!xmlStrcmp(node->name, (const xmlChar*)"creationdate")) {
119
+ properties |= kDAVProperty_CreationDate;
120
+ } else if (!xmlStrcmp(node->name, (const xmlChar*)"getlastmodified")) {
121
+ properties |= kDAVProperty_LastModified;
122
+ } else if (!xmlStrcmp(node->name, (const xmlChar*)"getcontentlength")) {
123
+ properties |= kDAVProperty_ContentLength;
124
+ } else {
125
+ HTTPLogWarn(@"Unknown DAV property requested \"%s\"", node->name);
126
+ }
127
+ node = node->next;
128
+ }
129
+ } else {
130
+ HTTPLogWarn(@"HTTP Server: Invalid DAV properties\n%@", [[NSString alloc] initWithData:body encoding:NSUTF8StringEncoding]);
131
+ }
132
+ xmlFreeDoc(document);
133
+ }
134
+ if (!properties) {
135
+ properties = kDAVAllProperties;
136
+ }
137
+
138
+ NSString* basePath = [rootPath stringByAppendingPathComponent:resourcePath];
139
+ if (![basePath hasPrefix:rootPath] || ![[NSFileManager defaultManager] fileExistsAtPath:basePath]) {
140
+ return nil;
141
+ }
142
+
143
+ NSMutableString* xmlString = [NSMutableString stringWithString:@"<?xml version=\"1.0\" encoding=\"utf-8\" ?>"];
144
+ [xmlString appendString:@"<D:multistatus xmlns:D=\"DAV:\">\n"];
145
+ if (![resourcePath hasPrefix:@"/"]) {
146
+ resourcePath = [@"/" stringByAppendingString:resourcePath];
147
+ }
148
+ _AddPropertyResponse(basePath, resourcePath, properties, xmlString);
149
+ if (depth == 1) {
150
+ if (![resourcePath hasSuffix:@"/"]) {
151
+ resourcePath = [resourcePath stringByAppendingString:@"/"];
152
+ }
153
+ NSDirectoryEnumerator* enumerator = [[NSFileManager defaultManager] enumeratorAtPath:basePath];
154
+ NSString* path;
155
+ while ((path = [enumerator nextObject])) {
156
+ _AddPropertyResponse([basePath stringByAppendingPathComponent:path], [resourcePath stringByAppendingString:path], properties, xmlString);
157
+ [enumerator skipDescendents];
158
+ }
159
+ }
160
+ [xmlString appendString:@"</D:multistatus>"];
161
+
162
+ [_headers setObject:@"application/xml; charset=\"utf-8\"" forKey:@"Content-Type"];
163
+ _data = [xmlString dataUsingEncoding:NSUTF8StringEncoding];
164
+ _status = 207;
165
+ }
166
+
167
+ // 9.3 MKCOL Method
168
+ if ([method isEqualToString:@"MKCOL"]) {
169
+ NSString* path = [rootPath stringByAppendingPathComponent:resourcePath];
170
+ if (![path hasPrefix:rootPath]) {
171
+ return nil;
172
+ }
173
+
174
+ if (![[NSFileManager defaultManager] fileExistsAtPath:[path stringByDeletingLastPathComponent]]) {
175
+ HTTPLogError(@"Missing intermediate collection(s) at \"%@\"", path);
176
+ _status = 409;
177
+ } else if (![[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:NO attributes:nil error:NULL]) {
178
+ HTTPLogError(@"Failed creating collection at \"%@\"", path);
179
+ _status = 405;
180
+ }
181
+ }
182
+
183
+ // 9.8 COPY Method
184
+ // 9.9 MOVE Method
185
+ if ([method isEqualToString:@"MOVE"] || [method isEqualToString:@"COPY"]) {
186
+ if ([method isEqualToString:@"COPY"] && ![[headers objectForKey:@"Depth"] isEqualToString:@"infinity"]) {
187
+ HTTPLogError(@"Unsupported DAV depth \"%@\"", [headers objectForKey:@"Depth"]);
188
+ return nil;
189
+ }
190
+
191
+ NSString* sourcePath = [rootPath stringByAppendingPathComponent:resourcePath];
192
+ if (![sourcePath hasPrefix:rootPath] || ![[NSFileManager defaultManager] fileExistsAtPath:sourcePath]) {
193
+ return nil;
194
+ }
195
+
196
+ NSString* destination = [headers objectForKey:@"Destination"];
197
+ NSRange range = [destination rangeOfString:[headers objectForKey:@"Host"]];
198
+ if (range.location == NSNotFound) {
199
+ return nil;
200
+ }
201
+ NSString* destinationPath = [rootPath stringByAppendingPathComponent:
202
+ [[destination substringFromIndex:(range.location + range.length)] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
203
+ if (![destinationPath hasPrefix:rootPath] || [[NSFileManager defaultManager] fileExistsAtPath:destinationPath]) {
204
+ return nil;
205
+ }
206
+
207
+ BOOL isDirectory;
208
+ if (![[NSFileManager defaultManager] fileExistsAtPath:[destinationPath stringByDeletingLastPathComponent] isDirectory:&isDirectory] || !isDirectory) {
209
+ HTTPLogError(@"Invalid destination path \"%@\"", destinationPath);
210
+ _status = 409;
211
+ } else {
212
+ BOOL existing = [[NSFileManager defaultManager] fileExistsAtPath:destinationPath];
213
+ if (existing && [[headers objectForKey:@"Overwrite"] isEqualToString:@"F"]) {
214
+ HTTPLogError(@"Pre-existing destination path \"%@\"", destinationPath);
215
+ _status = 412;
216
+ } else {
217
+ if ([method isEqualToString:@"COPY"]) {
218
+ if ([[NSFileManager defaultManager] copyItemAtPath:sourcePath toPath:destinationPath error:NULL]) {
219
+ _status = existing ? 204 : 201;
220
+ } else {
221
+ HTTPLogError(@"Failed copying \"%@\" to \"%@\"", sourcePath, destinationPath);
222
+ _status = 403;
223
+ }
224
+ } else {
225
+ if ([[NSFileManager defaultManager] moveItemAtPath:sourcePath toPath:destinationPath error:NULL]) {
226
+ _status = existing ? 204 : 201;
227
+ } else {
228
+ HTTPLogError(@"Failed moving \"%@\" to \"%@\"", sourcePath, destinationPath);
229
+ _status = 403;
230
+ }
231
+ }
232
+ }
233
+ }
234
+ }
235
+
236
+ // 9.10 LOCK Method - TODO: Actually lock the resource
237
+ if ([method isEqualToString:@"LOCK"]) {
238
+ NSString* path = [rootPath stringByAppendingPathComponent:resourcePath];
239
+ if (![path hasPrefix:rootPath]) {
240
+ return nil;
241
+ }
242
+
243
+ NSString* depth = [headers objectForKey:@"Depth"];
244
+ NSString* scope = nil;
245
+ NSString* type = nil;
246
+ NSString* owner = nil;
247
+ NSString* token = nil;
248
+ xmlDocPtr document = xmlReadMemory(body.bytes, (int)body.length, NULL, NULL, kXMLParseOptions);
249
+ if (document) {
250
+ xmlNodePtr node = _XMLChildWithName(document->children, (const xmlChar*)"lockinfo");
251
+ if (node) {
252
+ xmlNodePtr scopeNode = _XMLChildWithName(node->children, (const xmlChar*)"lockscope");
253
+ if (scopeNode && scopeNode->children && scopeNode->children->name) {
254
+ scope = [NSString stringWithUTF8String:(const char*)scopeNode->children->name];
255
+ }
256
+ xmlNodePtr typeNode = _XMLChildWithName(node->children, (const xmlChar*)"locktype");
257
+ if (typeNode && typeNode->children && typeNode->children->name) {
258
+ type = [NSString stringWithUTF8String:(const char*)typeNode->children->name];
259
+ }
260
+ xmlNodePtr ownerNode = _XMLChildWithName(node->children, (const xmlChar*)"owner");
261
+ if (ownerNode) {
262
+ ownerNode = _XMLChildWithName(ownerNode->children, (const xmlChar*)"href");
263
+ if (ownerNode && ownerNode->children && ownerNode->children->content) {
264
+ owner = [NSString stringWithUTF8String:(const char*)ownerNode->children->content];
265
+ }
266
+ }
267
+ } else {
268
+ HTTPLogWarn(@"HTTP Server: Invalid DAV properties\n%@", [[NSString alloc] initWithData:body encoding:NSUTF8StringEncoding]);
269
+ }
270
+ xmlFreeDoc(document);
271
+ } else {
272
+ // No body, see if they're trying to refresh an existing lock. If so, then just fake up the scope, type and depth so we fall
273
+ // into the lock create case.
274
+ NSString* lockToken;
275
+ if ((lockToken = [headers objectForKey:@"If"]) != nil) {
276
+ scope = @"exclusive";
277
+ type = @"write";
278
+ depth = @"0";
279
+ token = [lockToken stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"(<>)"]];
280
+ }
281
+ }
282
+ if ([scope isEqualToString:@"exclusive"] && [type isEqualToString:@"write"] && [depth isEqualToString:@"0"] &&
283
+ ([[NSFileManager defaultManager] fileExistsAtPath:path] || [[NSData data] writeToFile:path atomically:YES])) {
284
+ NSString* timeout = [headers objectForKey:@"Timeout"];
285
+ if (!token) {
286
+ CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
287
+ NSString *uuidStr = (__bridge_transfer NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuid);
288
+ token = [NSString stringWithFormat:@"urn:uuid:%@", uuidStr];
289
+ CFRelease(uuid);
290
+ }
291
+
292
+ NSMutableString* xmlString = [NSMutableString stringWithString:@"<?xml version=\"1.0\" encoding=\"utf-8\" ?>"];
293
+ [xmlString appendString:@"<D:prop xmlns:D=\"DAV:\">\n"];
294
+ [xmlString appendString:@"<D:lockdiscovery>\n<D:activelock>\n"];
295
+ [xmlString appendFormat:@"<D:locktype><D:%@/></D:locktype>\n", type];
296
+ [xmlString appendFormat:@"<D:lockscope><D:%@/></D:lockscope>\n", scope];
297
+ [xmlString appendFormat:@"<D:depth>%@</D:depth>\n", depth];
298
+ if (owner) {
299
+ [xmlString appendFormat:@"<D:owner><D:href>%@</D:href></D:owner>\n", owner];
300
+ }
301
+ if (timeout) {
302
+ [xmlString appendFormat:@"<D:timeout>%@</D:timeout>\n", timeout];
303
+ }
304
+ [xmlString appendFormat:@"<D:locktoken><D:href>%@</D:href></D:locktoken>\n", token];
305
+ NSString* lockroot = [@"http://" stringByAppendingString:[[headers objectForKey:@"Host"] stringByAppendingString:[@"/" stringByAppendingString:resourcePath]]];
306
+ [xmlString appendFormat:@"<D:lockroot><D:href>%@</D:href></D:lockroot>\n", lockroot];
307
+ [xmlString appendString:@"</D:activelock>\n</D:lockdiscovery>\n"];
308
+ [xmlString appendString:@"</D:prop>"];
309
+
310
+ [_headers setObject:@"application/xml; charset=\"utf-8\"" forKey:@"Content-Type"];
311
+ _data = [xmlString dataUsingEncoding:NSUTF8StringEncoding];
312
+ _status = 200;
313
+ HTTPLogVerbose(@"Pretending to lock \"%@\"", resourcePath);
314
+ } else {
315
+ HTTPLogError(@"Locking request \"%@/%@/%@\" for \"%@\" is not allowed", scope, type, depth, resourcePath);
316
+ _status = 403;
317
+ }
318
+ }
319
+
320
+ // 9.11 UNLOCK Method - TODO: Actually unlock the resource
321
+ if ([method isEqualToString:@"UNLOCK"]) {
322
+ NSString* path = [rootPath stringByAppendingPathComponent:resourcePath];
323
+ if (![path hasPrefix:rootPath] || ![[NSFileManager defaultManager] fileExistsAtPath:path]) {
324
+ return nil;
325
+ }
326
+
327
+ NSString* token = [headers objectForKey:@"Lock-Token"];
328
+ _status = token ? 204 : 400;
329
+ HTTPLogVerbose(@"Pretending to unlock \"%@\"", resourcePath);
330
+ }
331
+
332
+ }
333
+ return self;
334
+ }
335
+
336
+
337
+ - (UInt64) contentLength {
338
+ return _data ? _data.length : 0;
339
+ }
340
+
341
+ - (UInt64) offset {
342
+ return _offset;
343
+ }
344
+
345
+ - (void) setOffset:(UInt64)offset {
346
+ _offset = offset;
347
+ }
348
+
349
+ - (NSData*) readDataOfLength:(NSUInteger)lengthParameter {
350
+ if (_data) {
351
+ NSUInteger remaining = _data.length - (NSUInteger)_offset;
352
+ NSUInteger length = lengthParameter < remaining ? lengthParameter : remaining;
353
+ void* bytes = (void*)(_data.bytes + _offset);
354
+ _offset += length;
355
+ return [NSData dataWithBytesNoCopy:bytes length:length freeWhenDone:NO];
356
+ }
357
+ return nil;
358
+ }
359
+
360
+ - (BOOL) isDone {
361
+ return _data ? _offset == _data.length : YES;
362
+ }
363
+
364
+ - (NSInteger) status {
365
+ return _status;
366
+ }
367
+
368
+ - (NSDictionary*) httpHeaders {
369
+ return _headers;
370
+ }
371
+
372
+ @end