appium-webdriveragent 10.2.7 → 10.3.0
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.
- package/CHANGELOG.md +6 -0
- package/WebDriverAgentLib/Info.plist +2 -2
- package/WebDriverAgentLib/Utilities/FBConfiguration.m +1 -0
- package/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m +1605 -1595
- package/WebDriverAgentLib/Vendor/CocoaAsyncSocket/GCDAsyncUdpSocket.m +994 -990
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPMessage.h +14 -9
- package/WebDriverAgentLib/Vendor/CocoaHTTPServer/HTTPMessage.m +273 -30
- package/package.json +1 -1
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The HTTPMessage class is a simple Objective-C wrapper
|
|
2
|
+
* The HTTPMessage class is a simple Objective-C wrapper for HTTP message parsing.
|
|
3
|
+
* Migrated from CFHTTPMessage to use Foundation and Network framework.
|
|
3
4
|
**/
|
|
4
5
|
|
|
5
6
|
#import <Foundation/Foundation.h>
|
|
6
7
|
|
|
7
|
-
#
|
|
8
|
-
|
|
9
|
-
#import <CFNetwork/CFNetwork.h>
|
|
10
|
-
#endif
|
|
11
|
-
|
|
12
|
-
#define HTTPVersion1_0 ((NSString *)kCFHTTPVersion1_0)
|
|
13
|
-
#define HTTPVersion1_1 ((NSString *)kCFHTTPVersion1_1)
|
|
8
|
+
#define HTTPVersion1_0 @"HTTP/1.0"
|
|
9
|
+
#define HTTPVersion1_1 @"HTTP/1.1"
|
|
14
10
|
|
|
15
11
|
|
|
16
12
|
@interface HTTPMessage : NSObject
|
|
17
13
|
{
|
|
18
|
-
|
|
14
|
+
NSMutableDictionary *_headers;
|
|
15
|
+
NSMutableData *_body;
|
|
16
|
+
NSString *_version;
|
|
17
|
+
NSString *_method;
|
|
18
|
+
NSURL *_url;
|
|
19
|
+
NSInteger _statusCode;
|
|
20
|
+
NSString *_statusDescription;
|
|
21
|
+
BOOL _isRequest;
|
|
22
|
+
BOOL _headerComplete;
|
|
23
|
+
NSMutableData *_rawData;
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
- (id)initEmptyRequest;
|
|
@@ -8,107 +8,350 @@
|
|
|
8
8
|
|
|
9
9
|
@implementation HTTPMessage
|
|
10
10
|
|
|
11
|
-
- (id)
|
|
11
|
+
- (id)init
|
|
12
12
|
{
|
|
13
13
|
if ((self = [super init]))
|
|
14
14
|
{
|
|
15
|
-
|
|
15
|
+
_headers = [[NSMutableDictionary alloc] init];
|
|
16
|
+
_body = [[NSMutableData alloc] init];
|
|
17
|
+
_rawData = [[NSMutableData alloc] init];
|
|
18
|
+
_version = HTTPVersion1_1;
|
|
19
|
+
_headerComplete = NO;
|
|
20
|
+
_isRequest = YES;
|
|
21
|
+
}
|
|
22
|
+
return self;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
- (id)initEmptyRequest
|
|
26
|
+
{
|
|
27
|
+
if ((self = [self init]))
|
|
28
|
+
{
|
|
29
|
+
_isRequest = YES;
|
|
16
30
|
}
|
|
17
31
|
return self;
|
|
18
32
|
}
|
|
19
33
|
|
|
20
34
|
- (id)initRequestWithMethod:(NSString *)method URL:(NSURL *)url version:(NSString *)version
|
|
21
35
|
{
|
|
22
|
-
if ((self = [
|
|
36
|
+
if ((self = [self init]))
|
|
23
37
|
{
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
38
|
+
_isRequest = YES;
|
|
39
|
+
_method = [method copy];
|
|
40
|
+
_url = [url copy];
|
|
41
|
+
_version = version ? [version copy] : HTTPVersion1_1;
|
|
28
42
|
}
|
|
29
43
|
return self;
|
|
30
44
|
}
|
|
31
45
|
|
|
32
46
|
- (id)initResponseWithStatusCode:(NSInteger)code description:(NSString *)description version:(NSString *)version
|
|
33
47
|
{
|
|
34
|
-
if ((self = [
|
|
48
|
+
if ((self = [self init]))
|
|
35
49
|
{
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
50
|
+
_isRequest = NO;
|
|
51
|
+
_statusCode = code;
|
|
52
|
+
_statusDescription = [description copy];
|
|
53
|
+
_version = version ? [version copy] : HTTPVersion1_1;
|
|
40
54
|
}
|
|
41
55
|
return self;
|
|
42
56
|
}
|
|
43
57
|
|
|
44
|
-
- (
|
|
58
|
+
- (BOOL)appendData:(NSData *)data
|
|
45
59
|
{
|
|
46
|
-
if (
|
|
60
|
+
if (!data || [data length] == 0)
|
|
47
61
|
{
|
|
48
|
-
|
|
62
|
+
return NO;
|
|
49
63
|
}
|
|
64
|
+
|
|
65
|
+
[_rawData appendData:data];
|
|
66
|
+
|
|
67
|
+
if (!_headerComplete)
|
|
68
|
+
{
|
|
69
|
+
// Look for the end of headers (CRLF CRLF or LF LF)
|
|
70
|
+
NSData *headerEndMarker = [@"\r\n\r\n" dataUsingEncoding:NSASCIIStringEncoding];
|
|
71
|
+
NSRange headerEndRange = [_rawData rangeOfData:headerEndMarker options:0 range:NSMakeRange(0, [_rawData length])];
|
|
72
|
+
|
|
73
|
+
if (headerEndRange.location == NSNotFound)
|
|
74
|
+
{
|
|
75
|
+
// Also check for LF LF (some clients use this)
|
|
76
|
+
NSData *lfMarker = [@"\n\n" dataUsingEncoding:NSASCIIStringEncoding];
|
|
77
|
+
headerEndRange = [_rawData rangeOfData:lfMarker options:0 range:NSMakeRange(0, [_rawData length])];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (headerEndRange.location != NSNotFound)
|
|
81
|
+
{
|
|
82
|
+
_headerComplete = YES;
|
|
83
|
+
|
|
84
|
+
// Parse the header data
|
|
85
|
+
NSData *headerData = [_rawData subdataWithRange:NSMakeRange(0, headerEndRange.location + headerEndRange.length)];
|
|
86
|
+
NSString *headerString = [[NSString alloc] initWithData:headerData encoding:NSASCIIStringEncoding];
|
|
87
|
+
|
|
88
|
+
if (headerString)
|
|
89
|
+
{
|
|
90
|
+
[self parseHeaders:headerString];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Extract body data if any
|
|
94
|
+
NSUInteger bodyStart = headerEndRange.location + headerEndRange.length;
|
|
95
|
+
if ([_rawData length] > bodyStart)
|
|
96
|
+
{
|
|
97
|
+
NSData *bodyData = [_rawData subdataWithRange:NSMakeRange(bodyStart, [_rawData length] - bodyStart)];
|
|
98
|
+
[_body appendData:bodyData];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
[_rawData setLength:0];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
else
|
|
105
|
+
{
|
|
106
|
+
// Headers are complete, append to body
|
|
107
|
+
[_body appendData:data];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return YES;
|
|
50
111
|
}
|
|
51
112
|
|
|
52
|
-
- (
|
|
113
|
+
- (void)parseHeaders:(NSString *)headerString
|
|
53
114
|
{
|
|
54
|
-
|
|
115
|
+
NSArray *lines;
|
|
116
|
+
|
|
117
|
+
// Try splitting by "\r\n" first (standard HTTP line ending)
|
|
118
|
+
// Check if the string actually contains "\r\n" delimiter
|
|
119
|
+
if ([headerString rangeOfString:@"\r\n"].location != NSNotFound)
|
|
120
|
+
{
|
|
121
|
+
// Found "\r\n" delimiter, use this split
|
|
122
|
+
lines = [headerString componentsSeparatedByString:@"\r\n"];
|
|
123
|
+
}
|
|
124
|
+
else
|
|
125
|
+
{
|
|
126
|
+
// No "\r\n" found, try "\n" (some clients use just LF)
|
|
127
|
+
lines = [headerString componentsSeparatedByString:@"\n"];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// componentsSeparatedByString: always returns at least one element,
|
|
131
|
+
// so check if we have meaningful content (non-empty first line)
|
|
132
|
+
if ([lines count] == 0 || [[lines objectAtIndex:0] length] == 0)
|
|
133
|
+
{
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Parse first line (request line or status line)
|
|
138
|
+
NSString *firstLine = [lines objectAtIndex:0];
|
|
139
|
+
NSArray *firstLineParts = [firstLine componentsSeparatedByString:@" "];
|
|
140
|
+
|
|
141
|
+
if (_isRequest && [firstLineParts count] >= 3)
|
|
142
|
+
{
|
|
143
|
+
// Request line: METHOD URL VERSION
|
|
144
|
+
_method = [[firstLineParts objectAtIndex:0] copy];
|
|
145
|
+
NSString *urlString = [firstLineParts objectAtIndex:1];
|
|
146
|
+
|
|
147
|
+
// Handle both absolute URLs and relative paths
|
|
148
|
+
// Try absolute URL first
|
|
149
|
+
NSURL *parsedURL = [NSURL URLWithString:urlString];
|
|
150
|
+
|
|
151
|
+
// If that fails (nil), it's likely a relative path like "/endpoint"
|
|
152
|
+
// Create a URL with a base URL to handle relative paths
|
|
153
|
+
if (!parsedURL)
|
|
154
|
+
{
|
|
155
|
+
// Use a dummy base URL to allow relative path parsing
|
|
156
|
+
NSURL *baseURL = [NSURL URLWithString:@"http://localhost"];
|
|
157
|
+
parsedURL = [NSURL URLWithString:urlString relativeToURL:baseURL];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
_url = [parsedURL copy];
|
|
161
|
+
if ([firstLineParts count] >= 3)
|
|
162
|
+
{
|
|
163
|
+
_version = [[firstLineParts objectAtIndex:2] copy];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
else if (!_isRequest && [firstLineParts count] >= 3)
|
|
167
|
+
{
|
|
168
|
+
// Status line: VERSION CODE DESCRIPTION
|
|
169
|
+
_version = [[firstLineParts objectAtIndex:0] copy];
|
|
170
|
+
_statusCode = [[firstLineParts objectAtIndex:1] integerValue];
|
|
171
|
+
NSMutableArray *descParts = [NSMutableArray arrayWithArray:firstLineParts];
|
|
172
|
+
[descParts removeObjectAtIndex:0];
|
|
173
|
+
[descParts removeObjectAtIndex:0];
|
|
174
|
+
_statusDescription = [[descParts componentsJoinedByString:@" "] copy];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Parse header fields
|
|
178
|
+
for (NSUInteger i = 1; i < [lines count]; i++)
|
|
179
|
+
{
|
|
180
|
+
NSString *line = [lines objectAtIndex:i];
|
|
181
|
+
if ([line length] == 0)
|
|
182
|
+
{
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
NSRange colonRange = [line rangeOfString:@":"];
|
|
187
|
+
if (colonRange.location != NSNotFound)
|
|
188
|
+
{
|
|
189
|
+
NSString *headerName = [[line substringToIndex:colonRange.location] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
|
190
|
+
NSString *headerValue = [[line substringFromIndex:colonRange.location + 1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
|
191
|
+
|
|
192
|
+
if ([headerName length] > 0)
|
|
193
|
+
{
|
|
194
|
+
// HTTP headers are case-insensitive, but we'll store them with their original case
|
|
195
|
+
// For lookup, we'll use case-insensitive comparison
|
|
196
|
+
[_headers setObject:headerValue forKey:headerName];
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
55
200
|
}
|
|
56
201
|
|
|
57
202
|
- (BOOL)isHeaderComplete
|
|
58
203
|
{
|
|
59
|
-
return
|
|
204
|
+
return _headerComplete;
|
|
60
205
|
}
|
|
61
206
|
|
|
62
207
|
- (NSString *)version
|
|
63
208
|
{
|
|
64
|
-
return
|
|
209
|
+
return _version;
|
|
65
210
|
}
|
|
66
211
|
|
|
67
212
|
- (NSString *)method
|
|
68
213
|
{
|
|
69
|
-
return
|
|
214
|
+
return _method;
|
|
70
215
|
}
|
|
71
216
|
|
|
72
217
|
- (NSURL *)url
|
|
73
218
|
{
|
|
74
|
-
return
|
|
219
|
+
return _url;
|
|
75
220
|
}
|
|
76
221
|
|
|
77
222
|
- (NSInteger)statusCode
|
|
78
223
|
{
|
|
79
|
-
return
|
|
224
|
+
return _statusCode;
|
|
80
225
|
}
|
|
81
226
|
|
|
82
227
|
- (NSDictionary *)allHeaderFields
|
|
83
228
|
{
|
|
84
|
-
return
|
|
229
|
+
return [_headers copy];
|
|
85
230
|
}
|
|
86
231
|
|
|
87
232
|
- (NSString *)headerField:(NSString *)headerField
|
|
88
233
|
{
|
|
89
|
-
|
|
234
|
+
// Case-insensitive lookup
|
|
235
|
+
for (NSString *key in [_headers allKeys])
|
|
236
|
+
{
|
|
237
|
+
if ([key caseInsensitiveCompare:headerField] == NSOrderedSame)
|
|
238
|
+
{
|
|
239
|
+
return [_headers objectForKey:key];
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return nil;
|
|
90
243
|
}
|
|
91
244
|
|
|
92
245
|
- (void)setHeaderField:(NSString *)headerField value:(NSString *)headerFieldValue
|
|
93
246
|
{
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
247
|
+
if (headerField && headerFieldValue)
|
|
248
|
+
{
|
|
249
|
+
// Remove existing header with same name (case-insensitive)
|
|
250
|
+
NSMutableArray *keysToRemove = [NSMutableArray array];
|
|
251
|
+
for (NSString *key in [_headers allKeys])
|
|
252
|
+
{
|
|
253
|
+
if ([key caseInsensitiveCompare:headerField] == NSOrderedSame)
|
|
254
|
+
{
|
|
255
|
+
[keysToRemove addObject:key];
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
[_headers removeObjectsForKeys:keysToRemove];
|
|
259
|
+
|
|
260
|
+
// Add new header
|
|
261
|
+
[_headers setObject:headerFieldValue forKey:headerField];
|
|
262
|
+
}
|
|
97
263
|
}
|
|
98
264
|
|
|
99
265
|
- (NSData *)messageData
|
|
100
266
|
{
|
|
101
|
-
|
|
267
|
+
NSMutableString *messageString = [NSMutableString string];
|
|
268
|
+
|
|
269
|
+
if (_isRequest)
|
|
270
|
+
{
|
|
271
|
+
// Request line
|
|
272
|
+
// For relative URLs, use the path component; for absolute URLs, use absoluteString
|
|
273
|
+
NSString *urlString = nil;
|
|
274
|
+
if (_url)
|
|
275
|
+
{
|
|
276
|
+
// If it's a relative URL (has a base), use the relative path
|
|
277
|
+
// Otherwise use absoluteString or path
|
|
278
|
+
if ([_url baseURL])
|
|
279
|
+
{
|
|
280
|
+
// Relative URL - use the relative portion
|
|
281
|
+
urlString = [_url relativeString];
|
|
282
|
+
}
|
|
283
|
+
else
|
|
284
|
+
{
|
|
285
|
+
// Absolute URL
|
|
286
|
+
urlString = [_url absoluteString];
|
|
287
|
+
if (!urlString)
|
|
288
|
+
{
|
|
289
|
+
urlString = [_url path];
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
[messageString appendFormat:@"%@ %@ %@\r\n", _method ?: @"GET", urlString ?: @"/", _version ?: HTTPVersion1_1];
|
|
294
|
+
}
|
|
295
|
+
else
|
|
296
|
+
{
|
|
297
|
+
// Status line
|
|
298
|
+
[messageString appendFormat:@"%@ %ld %@\r\n", _version ?: HTTPVersion1_1, (long)_statusCode, _statusDescription ?: @""];
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Headers
|
|
302
|
+
for (NSString *key in [_headers allKeys])
|
|
303
|
+
{
|
|
304
|
+
NSString *value = [_headers objectForKey:key];
|
|
305
|
+
[messageString appendFormat:@"%@: %@\r\n", key, value];
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Empty line to separate headers from body
|
|
309
|
+
[messageString appendString:@"\r\n"];
|
|
310
|
+
|
|
311
|
+
NSMutableData *data = [NSMutableData dataWithData:(id)[messageString dataUsingEncoding:NSASCIIStringEncoding]];
|
|
312
|
+
|
|
313
|
+
// Append body if present
|
|
314
|
+
if ([_body length] > 0)
|
|
315
|
+
{
|
|
316
|
+
[data appendData:_body];
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
return data;
|
|
102
320
|
}
|
|
103
321
|
|
|
104
322
|
- (NSData *)body
|
|
105
323
|
{
|
|
106
|
-
return
|
|
324
|
+
return [_body copy];
|
|
107
325
|
}
|
|
108
326
|
|
|
109
327
|
- (void)setBody:(NSData *)body
|
|
110
328
|
{
|
|
111
|
-
|
|
329
|
+
if (body)
|
|
330
|
+
{
|
|
331
|
+
_body = [body mutableCopy];
|
|
332
|
+
}
|
|
333
|
+
else
|
|
334
|
+
{
|
|
335
|
+
_body = [[NSMutableData alloc] init];
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
- (void)dealloc
|
|
340
|
+
{
|
|
341
|
+
// ARC automatically releases all instance variables, but we include this
|
|
342
|
+
// for clarity and to match the pattern of the original CFNetwork implementation.
|
|
343
|
+
// All Objective-C objects (_headers, _body, _rawData, _version, _method, _url, _statusDescription)
|
|
344
|
+
// will be automatically released by ARC when this object is deallocated.
|
|
345
|
+
#if ! __has_feature(objc_arc)
|
|
346
|
+
[_headers release];
|
|
347
|
+
[_body release];
|
|
348
|
+
[_rawData release];
|
|
349
|
+
[_version release];
|
|
350
|
+
[_method release];
|
|
351
|
+
[_url release];
|
|
352
|
+
[_statusDescription release];
|
|
353
|
+
[super dealloc];
|
|
354
|
+
#endif
|
|
112
355
|
}
|
|
113
356
|
|
|
114
357
|
@end
|