iCuke 0.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. data/.gitignore +13 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +69 -0
  4. data/Rakefile +80 -0
  5. data/VERSION +1 -0
  6. data/app/iCuke/.gitignore +1 -0
  7. data/app/iCuke/Classes/FlipsideView.h +13 -0
  8. data/app/iCuke/Classes/FlipsideView.m +32 -0
  9. data/app/iCuke/Classes/FlipsideViewController.h +25 -0
  10. data/app/iCuke/Classes/FlipsideViewController.m +54 -0
  11. data/app/iCuke/Classes/MainView.h +15 -0
  12. data/app/iCuke/Classes/MainView.m +32 -0
  13. data/app/iCuke/Classes/MainViewController.h +16 -0
  14. data/app/iCuke/Classes/MainViewController.m +86 -0
  15. data/app/iCuke/Classes/iCukeAppDelegate.h +20 -0
  16. data/app/iCuke/Classes/iCukeAppDelegate.m +33 -0
  17. data/app/iCuke/FlipsideView.xib +444 -0
  18. data/app/iCuke/MainView.xib +520 -0
  19. data/app/iCuke/MainWindow.xib +355 -0
  20. data/app/iCuke/SniffingView.h +20 -0
  21. data/app/iCuke/SniffingView.m +191 -0
  22. data/app/iCuke/iCuke-Info.plist +30 -0
  23. data/app/iCuke/iCuke.xcodeproj/project.pbxproj +313 -0
  24. data/app/iCuke/iCuke_Prefix.pch +14 -0
  25. data/app/iCuke/main.m +16 -0
  26. data/ext/iCuke/.gitignore +2 -0
  27. data/ext/iCuke/DefaultsResponse.h +5 -0
  28. data/ext/iCuke/DefaultsResponse.m +67 -0
  29. data/ext/iCuke/EventResponse.h +5 -0
  30. data/ext/iCuke/EventResponse.m +122 -0
  31. data/ext/iCuke/Rakefile +22 -0
  32. data/ext/iCuke/Recorder.h +15 -0
  33. data/ext/iCuke/Recorder.m +85 -0
  34. data/ext/iCuke/RecorderResponse.h +5 -0
  35. data/ext/iCuke/RecorderResponse.m +59 -0
  36. data/ext/iCuke/SynthesizeSingleton.h +68 -0
  37. data/ext/iCuke/ViewResponse.h +5 -0
  38. data/ext/iCuke/ViewResponse.m +84 -0
  39. data/ext/iCuke/Viewer.h +8 -0
  40. data/ext/iCuke/Viewer.m +153 -0
  41. data/ext/iCuke/iCukeHTTPResponseHandler.h +50 -0
  42. data/ext/iCuke/iCukeHTTPResponseHandler.m +381 -0
  43. data/ext/iCuke/iCukeHTTPServer.h +53 -0
  44. data/ext/iCuke/iCukeHTTPServer.m +365 -0
  45. data/ext/iCuke/iCukeServer.h +16 -0
  46. data/ext/iCuke/iCukeServer.m +46 -0
  47. data/ext/iCuke/json/JSON.h +50 -0
  48. data/ext/iCuke/json/NSObject+SBJSON.h +68 -0
  49. data/ext/iCuke/json/NSObject+SBJSON.m +53 -0
  50. data/ext/iCuke/json/NSString+SBJSON.h +58 -0
  51. data/ext/iCuke/json/NSString+SBJSON.m +55 -0
  52. data/ext/iCuke/json/SBJSON.h +75 -0
  53. data/ext/iCuke/json/SBJSON.m +212 -0
  54. data/ext/iCuke/json/SBJsonBase.h +86 -0
  55. data/ext/iCuke/json/SBJsonBase.m +78 -0
  56. data/ext/iCuke/json/SBJsonParser.h +87 -0
  57. data/ext/iCuke/json/SBJsonParser.m +475 -0
  58. data/ext/iCuke/json/SBJsonWriter.h +129 -0
  59. data/ext/iCuke/json/SBJsonWriter.m +228 -0
  60. data/features/icuke.feature +17 -0
  61. data/features/support/env.rb +3 -0
  62. data/iCuke.gemspec +113 -0
  63. data/lib/icuke/cucumber.rb +211 -0
  64. data/lib/icuke/simulate.rb +132 -0
  65. data/lib/icuke/simulator.rb +107 -0
  66. data/lib/icuke.rb +1 -0
  67. metadata +163 -0
@@ -0,0 +1,381 @@
1
+ //
2
+ // HTTPResponseHandler.m
3
+ // TextTransfer
4
+ //
5
+ // Created by Matt Gallagher on 2009/07/13.
6
+ // Copyright 2009 Matt Gallagher. All rights reserved.
7
+ //
8
+ // Permission is given to use this source code file, free of charge, in any
9
+ // project, commercial or otherwise, entirely at your risk, with the condition
10
+ // that any redistribution (in part or whole) of source code must retain
11
+ // this copyright and permission notice. Attribution in compiled projects is
12
+ // appreciated but not required.
13
+ //
14
+
15
+ #import "iCukeHTTPResponseHandler.h"
16
+ #import "iCukeHTTPServer.h"
17
+ #import "ViewResponse.h"
18
+
19
+ @implementation iCukeHTTPResponseHandler
20
+
21
+ static NSMutableArray *registeredHandlers = nil;
22
+
23
+ //
24
+ // priority
25
+ //
26
+ // The priority determines which request handlers are given the option to
27
+ // handle a request first. The highest number goes first, with the base class
28
+ // (HTTPResponseHandler) implementing a 501 error response at priority 0
29
+ // (the lowest priorty).
30
+ //
31
+ // Even if subclasses have a 0 priority, they will always receive precedence
32
+ // over the base class, since the base class' implementation is intended as
33
+ // an error condition only.
34
+ //
35
+ // returns the priority.
36
+ //
37
+ + (NSUInteger)priority
38
+ {
39
+ return 0;
40
+ }
41
+
42
+ //
43
+ // load
44
+ //
45
+ // Implementing the load method and invoking
46
+ // [HTTPResponseHandler registerHandler:self] causes HTTPResponseHandler
47
+ // to register this class in the list of registered HTTP response handlers.
48
+ //
49
+ + (void)load
50
+ {
51
+ [iCukeHTTPResponseHandler registerHandler:self];
52
+ }
53
+
54
+ //
55
+ // registerHandler:
56
+ //
57
+ // Inserts the HTTPResponseHandler class into the priority list.
58
+ //
59
+ + (void)registerHandler:(Class)handlerClass
60
+ {
61
+ if (registeredHandlers == nil)
62
+ {
63
+ registeredHandlers = [[NSMutableArray alloc] init];
64
+ }
65
+
66
+ NSUInteger i;
67
+ NSUInteger count = [registeredHandlers count];
68
+ for (i = 0; i < count; i++)
69
+ {
70
+ if ([handlerClass priority] >= [[registeredHandlers objectAtIndex:i] priority])
71
+ {
72
+ break;
73
+ }
74
+ }
75
+ [registeredHandlers insertObject:handlerClass atIndex:i];
76
+ }
77
+
78
+ //
79
+ // canHandleRequest:method:url:headerFields:
80
+ //
81
+ // Class method to determine if the response handler class can handle
82
+ // a given request.
83
+ //
84
+ // Parameters:
85
+ // aRequest - the request
86
+ // requestMethod - the request method
87
+ // requestURL - the request URL
88
+ // requestHeaderFields - the request headers
89
+ //
90
+ // returns YES (if the handler can handle the request), NO (otherwise)
91
+ //
92
+ + (BOOL)canHandleRequest:(CFHTTPMessageRef)aRequest
93
+ method:(NSString *)requestMethod
94
+ url:(NSURL *)requestURL
95
+ headerFields:(NSDictionary *)requestHeaderFields
96
+ {
97
+ return YES;
98
+ }
99
+
100
+ //
101
+ // handlerClassForRequest:method:url:headerFields:
102
+ //
103
+ // Important method to edit for your application.
104
+ //
105
+ // This method determines (from the HTTP request message, URL and headers)
106
+ // which
107
+ //
108
+ // Parameters:
109
+ // aRequest - the CFHTTPMessageRef, with data at least as far as the end
110
+ // of the headers
111
+ // requestMethod - the request method (GET, POST, PUT, DELETE etc)
112
+ // requestURL - the URL (likely only contains a path)
113
+ // requestHeaderFields - the parsed header fields
114
+ //
115
+ // returns the class to handle the request, or nil if no handler exists.
116
+ //
117
+ + (Class)handlerClassForRequest:(CFHTTPMessageRef)aRequest
118
+ method:(NSString *)requestMethod
119
+ url:(NSURL *)requestURL
120
+ headerFields:(NSDictionary *)requestHeaderFields
121
+ {
122
+ for (Class handlerClass in registeredHandlers)
123
+ {
124
+ if ([handlerClass canHandleRequest:aRequest
125
+ method:requestMethod
126
+ url:requestURL
127
+ headerFields:requestHeaderFields])
128
+ {
129
+ return handlerClass;
130
+ }
131
+ }
132
+
133
+ return nil;
134
+ }
135
+
136
+ //
137
+ // handleRequest:fileHandle:server:
138
+ //
139
+ // This method parses the request method and header components, invokes
140
+ // +[handlerClassForRequest:method:url:headerFields:] to determine a handler
141
+ // class (if any) and creates the handler.
142
+ //
143
+ // Parameters:
144
+ // aRequest - the CFHTTPMessageRef request requiring a response
145
+ // requestFileHandle - the file handle for the incoming request (still
146
+ // open and possibly receiving data) and for the outgoing response
147
+ // aServer - the server that is invoking us
148
+ //
149
+ // returns the initialized handler (if one can handle the request) or nil
150
+ // (if no valid handler exists).
151
+ //
152
+ + (iCukeHTTPResponseHandler *)handlerForRequest:(CFHTTPMessageRef)aRequest
153
+ fileHandle:(NSFileHandle *)requestFileHandle
154
+ server:(iCukeHTTPServer *)aServer
155
+ {
156
+ NSDictionary *requestHeaderFields =
157
+ [(NSDictionary *)CFHTTPMessageCopyAllHeaderFields(aRequest)
158
+ autorelease];
159
+ NSURL *requestURL =
160
+ [(NSURL *)CFHTTPMessageCopyRequestURL(aRequest) autorelease];
161
+ NSString *method =
162
+ [(NSString *)CFHTTPMessageCopyRequestMethod(aRequest)
163
+ autorelease];
164
+
165
+ Class classForRequest =
166
+ [self handlerClassForRequest:aRequest
167
+ method:method
168
+ url:requestURL
169
+ headerFields:requestHeaderFields];
170
+
171
+ iCukeHTTPResponseHandler *handler =
172
+ [[[classForRequest alloc]
173
+ initWithRequest:aRequest
174
+ method:method
175
+ url:requestURL
176
+ headerFields:requestHeaderFields
177
+ fileHandle:requestFileHandle
178
+ server:aServer]
179
+ autorelease];
180
+
181
+ return handler;
182
+ }
183
+
184
+ //
185
+ // initWithRequest:method:url:headerFields:fileHandle:server:
186
+ //
187
+ // Init method for the handler. This method is mostly just a value copy operation
188
+ // so that the parts of the request don't need to be reparsed.
189
+ //
190
+ // Parameters:
191
+ // aRequest - the CFHTTPMessageRef
192
+ // method - the request method
193
+ // requestURL - the URL
194
+ // requestHeaderFields - the CFHTTPMessageRef header fields
195
+ // requestFileHandle - the incoming request file handle, also used for
196
+ // the outgoing response.
197
+ // aServer - the server that spawned us
198
+ //
199
+ // returns the initialized object
200
+ //
201
+ - (id)initWithRequest:(CFHTTPMessageRef)aRequest
202
+ method:(NSString *)method
203
+ url:(NSURL *)requestURL
204
+ headerFields:(NSDictionary *)requestHeaderFields
205
+ fileHandle:(NSFileHandle *)requestFileHandle
206
+ server:(iCukeHTTPServer *)aServer
207
+ {
208
+ self = [super init];
209
+ if (self != nil)
210
+ {
211
+ request = (CFHTTPMessageRef)[(id)aRequest retain];
212
+ requestMethod = [method retain];
213
+ url = [requestURL retain];
214
+ headerFields = [requestHeaderFields retain];
215
+ fileHandle = [requestFileHandle retain];
216
+ server = [aServer retain];
217
+
218
+ [[NSNotificationCenter defaultCenter]
219
+ addObserver:self
220
+ selector:@selector(receiveIncomingDataNotification:)
221
+ name:NSFileHandleDataAvailableNotification
222
+ object:fileHandle];
223
+
224
+ [fileHandle waitForDataInBackgroundAndNotify];
225
+ }
226
+ return self;
227
+ }
228
+
229
+ //
230
+ // startResponse
231
+ //
232
+ // Begin sending a response over the fileHandle. Trivial cases can
233
+ // synchronously return a response but everything else should spawn a thread
234
+ // or otherwise asynchronously start returning the response data.
235
+ //
236
+ // THIS IS THE PRIMARY METHOD FOR SUBCLASSES TO OVERRIDE. YOU DO NOT NEED
237
+ // TO INVOKE SUPER FOR THIS METHOD.
238
+ //
239
+ // This method should only be invoked from HTTPServer (it needs to add the
240
+ // object to its responseHandlers before this method is invoked).
241
+ //
242
+ // [server closeHandler:self] should be invoked when done sending data.
243
+ //
244
+ - (void)startResponse
245
+ {
246
+ CFHTTPMessageRef response =
247
+ CFHTTPMessageCreateResponse(
248
+ kCFAllocatorDefault, 501, NULL, kCFHTTPVersion1_1);
249
+ CFHTTPMessageSetHeaderFieldValue(
250
+ response, (CFStringRef)@"Content-Type", (CFStringRef)@"text/plain");
251
+ CFHTTPMessageSetHeaderFieldValue(
252
+ response, (CFStringRef)@"Connection", (CFStringRef)@"close");
253
+ CFHTTPMessageSetBody(
254
+ response,
255
+ (CFDataRef)[[NSString stringWithFormat:
256
+ @"No handler exists to handle %@.",
257
+ [url absoluteString]]
258
+ dataUsingEncoding:NSUTF8StringEncoding]);
259
+ CFDataRef headerData = CFHTTPMessageCopySerializedMessage(response);
260
+ @try
261
+ {
262
+ [fileHandle writeData:(NSData *)headerData];
263
+ }
264
+ @catch (NSException *exception)
265
+ {
266
+ // Ignore the exception, it normally just means the client
267
+ // closed the connection from the other end.
268
+ }
269
+ @finally
270
+ {
271
+ CFRelease(headerData);
272
+ CFRelease(response);
273
+ [server closeHandler:self];
274
+ }
275
+ }
276
+
277
+ //
278
+ // endResponse
279
+ //
280
+ // Closes the outgoing file handle.
281
+ //
282
+ // You should not invoke this method directly. It should only be invoked from
283
+ // HTTPServer (it needs to remove the object from its responseHandlers before
284
+ // this method is invoked). To close a reponse handler, use
285
+ // [server closeHandler:responseHandler].
286
+ //
287
+ // Subclasses should stop any other activity when this method is invoked and
288
+ // invoke super to close the file handle.
289
+ //
290
+ // If the connection is persistent, you must set fileHandle to nil (without
291
+ // closing the file) to prevent the connection getting closed by this method.
292
+ //
293
+ - (void)endResponse
294
+ {
295
+ if (fileHandle)
296
+ {
297
+ [[NSNotificationCenter defaultCenter]
298
+ removeObserver:self
299
+ name:NSFileHandleDataAvailableNotification
300
+ object:fileHandle];
301
+ [fileHandle closeFile];
302
+ [fileHandle release];
303
+ fileHandle = nil;
304
+ }
305
+
306
+ [server release];
307
+ server = nil;
308
+ }
309
+
310
+ //
311
+ // receiveIncomingDataNotification:
312
+ //
313
+ // Continues to receive incoming data for the connection. Remember that the
314
+ // first data past the end of the headers may already have been read into
315
+ // the request.
316
+ //
317
+ // Override this method to read the complete HTTP Request Body. This is a
318
+ // complicated process if you want to handle both Content-Length and all common
319
+ // Transfer-Encodings, so I haven't implemented it.
320
+ //
321
+ // If you want to handle persistent connections, you would need careful handling
322
+ // to determine the end of the request, seek the fileHandle so it points
323
+ // to the byte immediately after then end of this request, and then send an
324
+ // NSFileHandleConnectionAcceptedNotification notification with the fileHandle
325
+ // as the NSFileHandleNotificationFileHandleItem in the userInfo dictionary
326
+ // back to the server to handle the fileHandle as a new incoming request again
327
+ // (before setting fileHandle to nil so the connection won't get closed when this
328
+ // handler ends).
329
+ //
330
+ // Parameters:
331
+ // notification - notification that more data is available
332
+ //
333
+ - (void)receiveIncomingDataNotification:(NSNotification *)notification
334
+ {
335
+ NSFileHandle *incomingFileHandle = [notification object];
336
+ NSData *data = [incomingFileHandle availableData];
337
+
338
+ if ([data length] == 0)
339
+ {
340
+ [server closeHandler:self];
341
+ }
342
+
343
+ //
344
+ // This is a default implementation and simply ignores all data.
345
+ // If you need the HTTP body, you need to override this method to continue
346
+ // accumulating data. Don't forget that new data may need to be combined
347
+ // with any HTTP body data that may have already been received in the
348
+ // "request" body.
349
+ //
350
+
351
+ [incomingFileHandle waitForDataInBackgroundAndNotify];
352
+ }
353
+
354
+ //
355
+ // dealloc
356
+ //
357
+ // Stops the response if still running.
358
+ //
359
+ - (void)dealloc
360
+ {
361
+ if (server)
362
+ {
363
+ [self endResponse];
364
+ }
365
+
366
+ [(id)request release];
367
+ request = nil;
368
+
369
+ [requestMethod release];
370
+ requestMethod = nil;
371
+
372
+ [url release];
373
+ url = nil;
374
+
375
+ [headerFields release];
376
+ headerFields = nil;
377
+
378
+ [super dealloc];
379
+ }
380
+
381
+ @end
@@ -0,0 +1,53 @@
1
+ //
2
+ // HTTPServer.h
3
+ // TextTransfer
4
+ //
5
+ // Created by Matt Gallagher on 2009/07/13.
6
+ // Copyright 2009 Matt Gallagher. All rights reserved.
7
+ //
8
+ // Permission is given to use this source code file, free of charge, in any
9
+ // project, commercial or otherwise, entirely at your risk, with the condition
10
+ // that any redistribution (in part or whole) of source code must retain
11
+ // this copyright and permission notice. Attribution in compiled projects is
12
+ // appreciated but not required.
13
+ //
14
+
15
+ #if TARGET_OS_IPHONE
16
+ #import <UIKit/UIKit.h>
17
+ #else
18
+ #import <Cocoa/Cocoa.h>
19
+ #endif
20
+
21
+ typedef enum
22
+ {
23
+ SERVER_STATE_IDLE,
24
+ SERVER_STATE_STARTING,
25
+ SERVER_STATE_RUNNING,
26
+ SERVER_STATE_STOPPING
27
+ } iCukeHTTPServerState;
28
+
29
+ @class iCukeHTTPResponseHandler;
30
+
31
+ @interface iCukeHTTPServer : NSObject
32
+ {
33
+ NSError *lastError;
34
+ NSFileHandle *listeningHandle;
35
+ CFSocketRef socket;
36
+ iCukeHTTPServerState state;
37
+ CFMutableDictionaryRef incomingRequests;
38
+ NSMutableSet *responseHandlers;
39
+ }
40
+
41
+ @property (nonatomic, readonly, retain) NSError *lastError;
42
+ @property (readonly, assign) iCukeHTTPServerState state;
43
+
44
+ + (iCukeHTTPServer *)sharediCukeHTTPServer;
45
+
46
+ - (void)start;
47
+ - (void)stop;
48
+
49
+ - (void)closeHandler:(iCukeHTTPResponseHandler *)aHandler;
50
+
51
+ @end
52
+
53
+ extern NSString * const iCukeHTTPServerNotificationStateChanged;