Skip to content

Commit 7710a76

Browse files
authored
Merge 62e2308 into ea12acf
2 parents ea12acf + 62e2308 commit 7710a76

17 files changed

+209
-215
lines changed

Sources/Sentry/PrivateSentrySDKOnly.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ + (void)captureEnvelope:(SentryEnvelope *)envelope
5050

5151
+ (nullable SentryEnvelope *)envelopeWithData:(NSData *)data
5252
{
53-
return [SentrySerialization envelopeWithData:data];
53+
return [DataDeserialization envelopeWithData:data];
5454
}
5555

5656
#if !SDK_V9

Sources/Sentry/Public/SentryEnvelopeItemHeader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ SENTRY_NO_INIT
3131

3232
- (instancetype)initWithType:(NSString *)type
3333
length:(NSUInteger)length
34-
contentType:(NSString *)contentType
34+
contentType:(NSString *_Nullable)contentType
3535
itemCount:(NSNumber *)itemCount;
3636

3737
/**

Sources/Sentry/SentryAttachment.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ - (instancetype)initWithPath:(NSString *)path
8888
}
8989

9090
SentryAttachmentType
91-
typeForSentryAttachmentName(NSString *name)
91+
typeForSentryAttachmentName(NSString *_Nullable name)
9292
{
9393
if ([name isEqualToString:kSentryAttachmentTypeNameViewHierarchy]) {
9494
return kSentryAttachmentTypeViewHierarchy;

Sources/Sentry/SentryFileManager.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1073,7 +1073,7 @@ - (void)handleEnvelopesLimit
10731073
[envelopePathsCopy removeObjectAtIndex:i];
10741074

10751075
NSData *envelopeData = [[NSFileManager defaultManager] contentsAtPath:envelopeFilePath];
1076-
SentryEnvelope *envelope = [SentrySerialization envelopeWithData:envelopeData];
1076+
SentryEnvelope *envelope = [DataDeserialization envelopeWithData:envelopeData];
10771077

10781078
BOOL didMigrateSessionInit =
10791079
[SentryMigrateSessionInit migrateSessionInit:envelope

Sources/Sentry/SentryHttpTransport.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ - (void)sendAllCachedEnvelopes
339339

340340
envelopeFilePath = envelopeFileContents.path;
341341

342-
envelope = [SentrySerialization envelopeWithData:envelopeFileContents.contents];
342+
envelope = [DataDeserialization envelopeWithData:envelopeFileContents.contents];
343343
if (nil == envelope) {
344344
SENTRY_LOG_DEBUG(@"Envelope contained no deserializable data.");
345345
[self deleteEnvelopeAndSendNext:envelopeFilePath];

Sources/Sentry/SentryMigrateSessionInit.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ + (BOOL)setInitFlagOnNextEnvelopeWithSameSessionId:(SentrySession *)session
5656
continue;
5757
}
5858

59-
SentryEnvelope *envelope = [SentrySerialization envelopeWithData:envelopeData];
59+
SentryEnvelope *envelope = [DataDeserialization envelopeWithData:envelopeData];
6060

6161
if (nil != envelope) {
6262
BOOL didSetInitFlag = [self setInitFlagIfContainsSameSessionId:session.sessionId

Sources/Sentry/SentrySerialization.m

Lines changed: 0 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -76,165 +76,6 @@ + (NSData *_Nullable)dataWithEnvelope:(SentryEnvelope *)envelope
7676
return envelopeData;
7777
}
7878

79-
+ (SentryEnvelope *_Nullable)envelopeWithData:(NSData *)data
80-
{
81-
SentryEnvelopeHeader *envelopeHeader = nil;
82-
const unsigned char *bytes = [data bytes];
83-
NSUInteger envelopeHeaderIndex = 0;
84-
85-
for (NSUInteger i = 0; i < data.length; ++i) {
86-
if (bytes[i] == '\n') {
87-
envelopeHeaderIndex = i;
88-
// Envelope header end
89-
NSData *headerData = [NSData dataWithBytes:bytes length:i];
90-
#ifdef DEBUG
91-
NSString *headerString = [[NSString alloc] initWithData:headerData
92-
encoding:NSUTF8StringEncoding];
93-
SENTRY_LOG_DEBUG(@"Header %@", headerString);
94-
#endif
95-
NSError *error = nil;
96-
NSDictionary *headerDictionary = [NSJSONSerialization JSONObjectWithData:headerData
97-
options:0
98-
error:&error];
99-
if (nil != error) {
100-
SENTRY_LOG_ERROR(@"Failed to parse envelope header %@", error);
101-
break;
102-
}
103-
104-
SentryId *eventId = nil;
105-
NSString *eventIdAsString = headerDictionary[@"event_id"];
106-
if (nil != eventIdAsString) {
107-
eventId = [[SentryId alloc] initWithUUIDString:eventIdAsString];
108-
}
109-
110-
SentrySdkInfo *sdkInfo = nil;
111-
if (nil != headerDictionary[@"sdk"] &&
112-
[headerDictionary[@"sdk"] isKindOfClass:[NSDictionary class]]) {
113-
sdkInfo = [[SentrySdkInfo alloc]
114-
initWithDict:SENTRY_UNWRAP_NULLABLE(NSDictionary, headerDictionary[@"sdk"])];
115-
}
116-
117-
SentryTraceContext *traceContext = nil;
118-
if (nil != headerDictionary[@"trace"] &&
119-
[headerDictionary[@"trace"] isKindOfClass:[NSDictionary class]]) {
120-
traceContext = [[SentryTraceContext alloc]
121-
initWithDict:SENTRY_UNWRAP_NULLABLE(NSDictionary, headerDictionary[@"trace"])];
122-
}
123-
124-
envelopeHeader = [[SentryEnvelopeHeader alloc] initWithId:eventId
125-
sdkInfo:sdkInfo
126-
traceContext:traceContext];
127-
128-
if (headerDictionary[@"sent_at"] != nil &&
129-
[headerDictionary[@"sent_at"] isKindOfClass:[NSString class]]) {
130-
envelopeHeader.sentAt = sentry_fromIso8601String(
131-
SENTRY_UNWRAP_NULLABLE(NSString, headerDictionary[@"sent_at"]));
132-
}
133-
134-
break;
135-
}
136-
}
137-
138-
if (nil == envelopeHeader) {
139-
SENTRY_LOG_ERROR(@"Invalid envelope. No header found.");
140-
return nil;
141-
}
142-
143-
if (envelopeHeaderIndex == 0) {
144-
SENTRY_LOG_ERROR(@"EnvelopeHeader was parsed, its index is expected.");
145-
return nil;
146-
}
147-
148-
// Parse items
149-
NSUInteger itemHeaderStart = envelopeHeaderIndex + 1;
150-
151-
NSMutableArray<SentryEnvelopeItem *> *items = [NSMutableArray new];
152-
NSUInteger endOfEnvelope = data.length - 1;
153-
154-
for (NSUInteger i = itemHeaderStart; i <= endOfEnvelope; ++i) {
155-
if (bytes[i] == '\n' || i == endOfEnvelope) {
156-
157-
NSData *itemHeaderData =
158-
[data subdataWithRange:NSMakeRange(itemHeaderStart, i - itemHeaderStart)];
159-
#ifdef DEBUG
160-
NSString *itemHeaderString = [[NSString alloc] initWithData:itemHeaderData
161-
encoding:NSUTF8StringEncoding];
162-
SENTRY_LOG_DEBUG(@"Item Header %@", itemHeaderString);
163-
#endif
164-
NSError *error = nil;
165-
NSDictionary *headerDictionary = [NSJSONSerialization JSONObjectWithData:itemHeaderData
166-
options:0
167-
error:&error];
168-
if (nil != error) {
169-
SENTRY_LOG_ERROR(@"Failed to parse envelope item header %@", error);
170-
return nil;
171-
}
172-
NSString *_Nullable nullableType = [headerDictionary valueForKey:@"type"];
173-
if (nil == nullableType) {
174-
SENTRY_LOG_ERROR(@"Envelope item type is required.");
175-
break;
176-
}
177-
NSString *_Nonnull type = SENTRY_UNWRAP_NULLABLE(NSString, nullableType);
178-
179-
NSNumber *bodyLengthNumber = [headerDictionary valueForKey:@"length"];
180-
NSUInteger bodyLength = [bodyLengthNumber unsignedIntegerValue];
181-
if (endOfEnvelope == i && bodyLength != 0) {
182-
SENTRY_LOG_ERROR(
183-
@"Envelope item has no data but header indicates it's length is %d.",
184-
(int)bodyLength);
185-
break;
186-
}
187-
188-
NSString *filename = [headerDictionary valueForKey:@"filename"];
189-
NSString *contentType = [headerDictionary valueForKey:@"content_type"];
190-
NSString *attachmentType = [headerDictionary valueForKey:@"attachment_type"];
191-
NSNumber *itemCount = [headerDictionary valueForKey:@"item_count"];
192-
193-
SentryEnvelopeItemHeader *itemHeader;
194-
if (nil != filename) {
195-
itemHeader = [[SentryEnvelopeAttachmentHeader alloc]
196-
initWithType:type
197-
length:bodyLength
198-
filename:filename
199-
contentType:contentType
200-
attachmentType:typeForSentryAttachmentName(attachmentType)];
201-
} else if (nil != itemCount) {
202-
itemHeader = [[SentryEnvelopeItemHeader alloc] initWithType:type
203-
length:bodyLength
204-
contentType:contentType
205-
itemCount:itemCount];
206-
} else {
207-
itemHeader = [[SentryEnvelopeItemHeader alloc] initWithType:type length:bodyLength];
208-
}
209-
210-
if (endOfEnvelope == i) {
211-
i++; // 0 byte attachment
212-
}
213-
214-
if (bodyLength > 0 && data.length < (i + 1 + bodyLength)) {
215-
SENTRY_LOG_ERROR(@"Envelope is corrupted or has invalid data. Trying to read %li "
216-
@"bytes by skipping %li from a buffer of %li bytes.",
217-
(unsigned long)data.length, (unsigned long)bodyLength, (long)(i + 1));
218-
return nil;
219-
}
220-
221-
NSData *itemBody = [data subdataWithRange:NSMakeRange(i + 1, bodyLength)];
222-
SentryEnvelopeItem *envelopeItem = [[SentryEnvelopeItem alloc] initWithHeader:itemHeader
223-
data:itemBody];
224-
[items addObject:envelopeItem];
225-
i = itemHeaderStart = i + 1 + [bodyLengthNumber integerValue];
226-
}
227-
}
228-
229-
if (items.count == 0) {
230-
SENTRY_LOG_ERROR(@"Envelope has no items.");
231-
return nil;
232-
}
233-
234-
SentryEnvelope *envelope = [[SentryEnvelope alloc] initWithHeader:envelopeHeader items:items];
235-
return envelope;
236-
}
237-
23879
+ (NSData *_Nullable)dataWithSession:(SentrySession *)session
23980
{
24081
return [self dataWithJSONObject:[session serialize]];

Sources/Sentry/include/SentryAttachment+Private.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ typedef NS_ENUM(NSInteger, SentryAttachmentType) {
1616

1717
NSString *nameForSentryAttachmentType(SentryAttachmentType attachmentType);
1818

19-
SentryAttachmentType typeForSentryAttachmentName(NSString *name);
19+
SentryAttachmentType typeForSentryAttachmentName(NSString *_Nullable name);
2020

2121
@interface SentryAttachment ()
2222
SENTRY_NO_INIT

Sources/Sentry/include/SentrySerialization.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ NS_ASSUME_NONNULL_BEGIN
1515

1616
+ (NSData *_Nullable)dataWithEnvelope:(SentryEnvelope *)envelope;
1717

18-
+ (SentryEnvelope *_Nullable)envelopeWithData:(NSData *)data;
19-
2018
/**
2119
* Retrieves the json object from an event envelope item data.
2220
*/

Sources/Swift/Helper/DataDeserialization.swift

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
@_implementationOnly import _SentryPrivate
2+
13
@_spi(Private) @objc public final class DataDeserialization: NSObject {
24
@objc(sessionWithData:) public static func session(with data: Data) -> SentrySession? {
35
do {
@@ -29,4 +31,155 @@
2931
return nil
3032
}
3133
}
34+
35+
//swiftlint:disable cyclomatic_complexity function_body_length
36+
@objc(envelopeWithData:) public static func envelope(with data: Data) -> SentryEnvelope? {
37+
var envelopeHeader: SentryEnvelopeHeader?
38+
let bytes = [UInt8](data)
39+
var envelopeHeaderIndex: Int = 0
40+
41+
for i in 0..<data.count {
42+
if bytes[i] == UInt8(ascii: "\n") {
43+
envelopeHeaderIndex = i
44+
// Envelope header end
45+
let headerData = data.subdata(in: 0..<i)
46+
#if DEBUG
47+
if let headerString = String(data: headerData, encoding: .utf8) {
48+
SentrySDKLog.debug("Header \(headerString)")
49+
}
50+
#endif
51+
do {
52+
let headerDictionary = try JSONSerialization.jsonObject(with: headerData) as? [String: Any]
53+
var eventId: SentryId?
54+
if let eventIdAsString = headerDictionary?["event_id"] as? String {
55+
eventId = SentryId(uuidString: eventIdAsString)
56+
}
57+
58+
var sdkInfo: SentrySdkInfo?
59+
if let sdkDict = headerDictionary?["sdk"] as? [String: Any] {
60+
sdkInfo = SentrySdkInfo(dict: sdkDict)
61+
}
62+
63+
var traceContext: TraceContext?
64+
if let traceDict = headerDictionary?["trace"] as? [String: Any] {
65+
traceContext = TraceContext(dict: traceDict)
66+
}
67+
68+
let header = SentryEnvelopeHeader(id: eventId,
69+
sdkInfo: sdkInfo,
70+
traceContext: traceContext)
71+
72+
if let sentAtStr = headerDictionary?["sent_at"] as? String {
73+
header.sentAt = sentry_fromIso8601String(sentAtStr)
74+
}
75+
76+
envelopeHeader = header
77+
} catch {
78+
SentrySDKLog.error("Failed to parse envelope header \(error)")
79+
break
80+
}
81+
82+
}
83+
}
84+
85+
guard let envelopeHeaderUnwrapped = envelopeHeader else {
86+
SentrySDKLog.error("Invalid envelope. No header found.")
87+
return nil
88+
}
89+
90+
if envelopeHeaderIndex == 0 {
91+
SentrySDKLog.error("EnvelopeHeader was parsed, its index is expected.")
92+
return nil
93+
}
94+
95+
// Parse items
96+
var itemHeaderStart = envelopeHeaderIndex + 1
97+
var items: [SentryEnvelopeItem] = []
98+
let endOfEnvelope = data.count - 1
99+
100+
var i = itemHeaderStart
101+
while i <= endOfEnvelope {
102+
if bytes[i] == UInt8(ascii: "\n") || i == endOfEnvelope {
103+
let itemHeaderData = data.subdata(in: itemHeaderStart..<i)
104+
105+
#if DEBUG
106+
if let itemHeaderString = String(data: itemHeaderData, encoding: .utf8) {
107+
SentrySDKLog.debug("Item Header \(itemHeaderString)")
108+
}
109+
#endif
110+
111+
do {
112+
let headerDictionary = try JSONSerialization.jsonObject(with: itemHeaderData) as? [String: Any]
113+
114+
guard let type = headerDictionary?["type"] as? String else {
115+
SentrySDKLog.error("Envelope item type is required.")
116+
break
117+
}
118+
119+
let bodyLength = (headerDictionary?["length"] as? NSNumber)?.uintValue ?? 0
120+
121+
if i == endOfEnvelope && bodyLength != 0 {
122+
SentrySDKLog.error("Envelope item has no data but header indicates its length is \(bodyLength).")
123+
break
124+
}
125+
126+
let filename = headerDictionary?["filename"] as? String
127+
let contentType = headerDictionary?["content_type"] as? String
128+
let attachmentType = headerDictionary?["attachment_type"] as? String
129+
let itemCount = headerDictionary?["item_count"] as? NSNumber
130+
131+
let itemHeader: SentryEnvelopeItemHeader
132+
if let filename = filename {
133+
itemHeader = SentryEnvelopeAttachmentHeader(
134+
type: type,
135+
length: bodyLength,
136+
filename: filename,
137+
contentType: contentType,
138+
attachmentType: typeForSentryAttachmentName(attachmentType)
139+
)
140+
} else if let itemCount = itemCount {
141+
itemHeader = SentryEnvelopeItemHeader(
142+
type: type,
143+
length: bodyLength,
144+
contentType: contentType,
145+
itemCount: itemCount
146+
)
147+
} else {
148+
itemHeader = SentryEnvelopeItemHeader(type: type, length: bodyLength)
149+
}
150+
151+
if i == endOfEnvelope {
152+
i += 1 // 0-byte attachment
153+
}
154+
155+
if bodyLength > 0 && data.count < (i + 1 + Int(bodyLength)) {
156+
SentrySDKLog.error(
157+
"Envelope is corrupted or has invalid data. Trying to read \(bodyLength) bytes by skipping \(i + 1) from a buffer of \(data.count) bytes."
158+
)
159+
return nil
160+
}
161+
162+
let itemBody = data.subdata(in: (i + 1)..<(i + 1 + Int(bodyLength)))
163+
let envelopeItem = SentryEnvelopeItem(header: itemHeader, data: itemBody)
164+
items.append(envelopeItem)
165+
166+
i = itemHeaderStart + 1 + Int(bodyLength)
167+
itemHeaderStart = i
168+
} catch {
169+
SentrySDKLog.error("Failed to parse envelope item header \(error)")
170+
return nil
171+
}
172+
} else {
173+
i += 1
174+
}
175+
}
176+
177+
if items.isEmpty {
178+
SentrySDKLog.error("Envelope has no items.")
179+
return nil
180+
}
181+
182+
return SentryEnvelope(header: envelopeHeaderUnwrapped, items: items)
183+
}
184+
//swiftlint:enable cyclomatic_complexity function_body_length
32185
}

0 commit comments

Comments
 (0)