Skip to content
Browse files

- Improvements when parsing multipart, still has bugs

- Added README.md
  • Loading branch information...
1 parent ebfa960 commit 7e0b0a11648a4e3b3230d35b23ea53fa5971a2df @akempgen committed Feb 20, 2012
Showing with 148 additions and 13 deletions.
  1. +1 −1 ALEXLog.h
  2. +41 −11 ALEXMIMEMessage/ALEXMIMEMessage.m
  3. +77 −0 README.md
  4. +1 −0 TestApp/ALEXAppDelegate.m
  5. +28 −1 TestApp/en.lproj/MainMenu.xib
View
2 ALEXLog.h
@@ -13,6 +13,6 @@
#define ALEXLog(format,...) fprintf(stderr, "%s %s\n", __PRETTY_FUNCTION__, [[NSString stringWithFormat:format, ## __VA_ARGS__] UTF8String])
#define ALEXLogObject(NSObject) ALEXLog(@"" #NSObject ": '%@'", NSObject)
-//#define ALEXLogDataAsASCIIString(NSData) ALEXLog(@"Data " #NSData " as ASCII string: '%@'", [[NSString alloc] initWithData:NSData encoding:NSASCIIStringEncoding])
+#define ALEXLogDataAsASCIIString(NSData) ALEXLog(@"Data " #NSData " as ASCII string: '%@'", [[NSString alloc] initWithData:NSData encoding:NSASCIIStringEncoding])
#endif
View
52 ALEXMIMEMessage/ALEXMIMEMessage.m
@@ -14,7 +14,6 @@
-
NSString *const ALEXMIMEHeaderNameMIMEVersion = @"MIME-Version";
NSString *const ALEXMIMEHeaderNameContentType = @"Content-Type";
NSString *const ALEXMIMEHeaderNameContentTransferEncoding = @"Content-Type-Encoding";
@@ -112,8 +111,7 @@ - (id) initWithData:(NSData *)messageData
- (id) initWithData:(NSData *)messageData messageRange:(NSRange)messageRange
{
- //ALEXLogDataAsASCIIString(messageData);
- //ALEXLogDataAsASCIIString([messageData subdataWithRange:messageRange]);
+ ALEXLogDataAsASCIIString([messageData subdataWithRange:messageRange]);
NSCharacterSet *wsCS = [NSCharacterSet whitespaceCharacterSet];
@@ -151,7 +149,7 @@ - (id) initWithData:(NSData *)messageData messageRange:(NSRange)messageRange
NSUInteger lineLength = crlfRange.location-lineBeginning;
-#warning this can change for subparts? use data instead?
+//#warning this can change for subparts? use data instead?
NSStringEncoding stringEncoding = NSUTF8StringEncoding;
NSString *line = [[NSString alloc] initWithData:[messageData subdataWithRange:NSMakeRange(lineBeginning, lineLength)] encoding:stringEncoding];
@@ -203,9 +201,12 @@ - (id) initWithData:(NSData *)messageData messageRange:(NSRange)messageRange
- (id) initWithHeaderFields:(NSDictionary*)headerFields data:(NSData *)messageData bodyRange:(NSRange)bodyRange
{
+ NSParameterAssert(headerFields != nil);
+ NSParameterAssert(messageData != nil);
+
id objectValue = nil;
- //ALEXLogDataAsASCIIString([messageData subdataWithRange:bodyRange]);
+ ALEXLogDataAsASCIIString([messageData subdataWithRange:bodyRange]);
NSString *contentType = [headerFields objectForKey:ALEXMIMEHeaderNameContentType];
//ALEXLogObject(contentType);
@@ -225,26 +226,55 @@ - (id) initWithHeaderFields:(NSDictionary*)headerFields data:(NSData *)messageDa
NSData *boundaryData = [[ALEXMIMEMessage_CRLF ALEXMIMEMessage_DoubleHyphen stringByAppendingString:boundary] dataUsingEncoding:NSASCIIStringEncoding];
- //ALEXLogDataAsASCIIString([messageData subdataWithRange:bodyRange]);
+ ALEXLogDataAsASCIIString([messageData subdataWithRange:bodyRange]);
- while ( NO )
+ NSUInteger location = bodyRange.location;
+ NSUInteger bodyLength = bodyRange.length;
+ while ( bodyLength > 0 )
{
ALEXLog(@"bodyRange.location: %u .length %u", bodyRange.location, bodyRange.length);
- NSRange boundaryRange = [messageData rangeOfData:boundaryData options:0 range:bodyRange];
+ NSRange boundaryRange = [messageData rangeOfData:boundaryData options:0 range:NSMakeRange(location, bodyLength)];
ALEXLog(@"boundaryRange.location: %u .length %u", boundaryRange.location, boundaryRange.length);
+ /*
+ NSData *partData = [messageData subdataWithRange:NSMakeRange(location, boundaryRange.location-location)];
+
+
+ ALEXLogDataAsASCIIString(partData);
+ */
- //NSData *partData = [messageData subdataWithRange:partRange];
- //ALEXLogObject(partData);
+
+ ALEXMIMEMessage *subpart = [[ALEXMIMEMessage alloc] initWithData:messageData messageRange:NSMakeRange(location, boundaryRange.location-location)];
+ if (subpart) {
+ [subparts addObject:subpart];
+ }
+ bodyLength -= (boundaryRange.location + boundaryRange.length -location);
+ location = boundaryRange.location + boundaryRange.length;
+#warning whitespace +crlf überspringen
+
+ NSRange doubleHyphenRange = [messageData rangeOfData:[ALEXMIMEMessage_DoubleHyphen dataUsingEncoding:NSASCIIStringEncoding] options:0 range:NSMakeRange(location, 2)];
+ if ( doubleHyphenRange.location != NSNotFound )
+ break;
+
+ NSRange crlfRange = [messageData rangeOfData:[ALEXMIMEMessage_CRLF dataUsingEncoding:NSASCIIStringEncoding] options:0 range:NSMakeRange(location, bodyLength)];
+
+ bodyLength -= (crlfRange.location + crlfRange.length -location);
+ location = crlfRange.location + crlfRange.length;
+
}
objectValue = subparts;
}
-
+ else
+ {
+ //objectValue = [messageData subdataWithRange:bodyRange];
+ NSString *string = [[NSString alloc] initWithData:[messageData subdataWithRange:bodyRange] encoding:NSUTF8StringEncoding];
+ objectValue = [string stringByReplacingOccurrencesOfString:ALEXMIMEMessage_CRLF withString:@" » "];
+ }
// do other parsing here, like creating nsimages
View
77 README.md
@@ -0,0 +1,77 @@
+ALEXMIMEMessage
+===============
+
+A class to parse received MIME (Multipurpose Internet Mail Extensions) messages into objects and to construct MIME messages from objects for sending.
+
+Supports Multipart.
+
+Usage
+-----
+
+One example of using ALEXMIMEMessage to parse the response of a NSURLConnection (also see included Test App):
+
+ [NSURLConnection sendAsynchronousRequest:URLRequest
+ queue:queue
+ completionHandler:^(NSURLResponse *urlResponse, NSData *data, NSError *error)
+ {
+ self.mimeMessage = [[ALEXMIMEMessage alloc] initWithHTTPURLResponse:urlResponse bodyData:data];
+ [self.outlineView reloadData];
+ }];
+
+API
+---
+
+Creation
+
+ - (id) initWithHeaderFields:(NSDictionary*)headerFields objectValue:(id)objectValue;
+
+ @property (nonatomic, copy, readonly) NSDictionary *headerFields;
+ @property (nonatomic, copy, readonly) id objectValue;
+
+ @property (nonatomic, assign, readonly) BOOL isMultipart;
+
+Deserialization
+
+ - (id) initWithHTTPURLResponse:(NSHTTPURLResponse*)HTTPURLResponse bodyData:(NSData*)bodyData;
+ - (id) initWithHeaderFields:(NSDictionary*)headerFields bodyData:(NSData *)data;
+
+ - (id) initWithData:(NSData *)messageData;
+ - (id) initWithData:(NSData *)messageData messageRange:(NSRange)messageRange;
+ - (id) initWithHeaderFields:(NSDictionary*)headerFields data:(NSData *)messageData bodyRange:(NSRange)bodyRange;
+
+Serialization
+
+ - (NSMutableURLRequest*) mutableURLRequestWithURL:(NSURL*)URL;
+
+ - (NSData*) MIMEData;
+ - (NSData*) MIMEDataWithOptions:(ALEXMIMESerializationOptions)options;
+ - (NSData*) MIMEDataWithOptions:(ALEXMIMESerializationOptions)options headerFields:(NSDictionary**)headerFields;
+
+
+Status
+------
+
+**Note:** This code is work in progress and should not be used for anything yet, that would be crazy. While the following RFCs have been considered while writing this code, it is far from being compliant.
+
+Relevant RFCs:
+
+* [RFC 5322: Internet Message Format](http://tools.ietf.org/html/rfc5322)
+* [RFC 2045: MIME Part One: Format of Internet Message Bodies](http://tools.ietf.org/html/rfc2045)
+* [RFC 2046: MIME Part Two: Media Types](http://tools.ietf.org/html/rfc2046)
+* [RFC 2047: MIME Part Three: Message Header Extensions for Non-ASCII Text](http://tools.ietf.org/html/rfc2047)
+* [RFC 4288: Media Type Specifications and Registration Procedures](http://tools.ietf.org/html/rfc4288)
+* [RFC 4289: MIME Part Four: Registration Procedures](http://tools.ietf.org/html/rfc4289)
+* [RFC 4289: MIME Part Five: Conformance Criteria and Examples](http://tools.ietf.org/html/rfc2049)
+
+
+License
+-------
+
+Not licensed (yet).
+
+For two reasons: I simply haven't picked one and I *really* don't want you to use it yet
+
+
+Version History
+---------------
+No releases.
View
1 TestApp/ALEXAppDelegate.m
@@ -62,6 +62,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
NSString *source = [[NSString alloc] initWithData:message encoding:NSASCIIStringEncoding];
[self.sourceTextField setStringValue:source];
+
ALEXMIMEMessage *MIMEMessage = [[ALEXMIMEMessage alloc] initWithData:message];
ALEXLogObject(MIMEMessage);
View
29 TestApp/en.lproj/MainMenu.xib
@@ -1326,6 +1326,7 @@
<int key="NSvFlags">274</int>
<string key="NSFrameSize">{396, 672}</string>
<reference key="NSSuperview" ref="179773046"/>
+ <reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="356634609"/>
<string key="NSReuseIdentifierKey">_NS:354</string>
<string key="NSAntiCompressionPriority">{250, 750}</string>
@@ -1365,6 +1366,7 @@
</array>
<string key="NSFrameSize">{396, 672}</string>
<reference key="NSSuperview" ref="551452395"/>
+ <reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="552487036"/>
<string key="NSReuseIdentifierKey">_NS:404</string>
</object>
@@ -1385,6 +1387,7 @@
<int key="NSvFlags">256</int>
<string key="NSFrameSize">{396, 670}</string>
<reference key="NSSuperview" ref="35035542"/>
+ <reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="125486177"/>
<string key="NSReuseIdentifierKey">_NS:1703</string>
<bool key="NSEnabled">YES</bool>
@@ -1473,6 +1476,7 @@
</array>
<string key="NSFrame">{{1, 1}, {396, 670}}</string>
<reference key="NSSuperview" ref="515509394"/>
+ <reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="896951442"/>
<string key="NSReuseIdentifierKey">_NS:1701</string>
<reference key="NSDocView" ref="896951442"/>
@@ -1484,6 +1488,7 @@
<int key="NSvFlags">-2147483392</int>
<string key="NSFrame">{{224, 17}, {15, 102}}</string>
<reference key="NSSuperview" ref="515509394"/>
+ <reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="514185039"/>
<string key="NSReuseIdentifierKey">_NS:1726</string>
<reference key="NSTarget" ref="515509394"/>
@@ -1495,6 +1500,8 @@
<int key="NSvFlags">-2147483392</int>
<string key="NSFrame">{{1, 656}, {396, 15}}</string>
<reference key="NSSuperview" ref="515509394"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:1728</string>
<int key="NSsFlags">1</int>
<reference key="NSTarget" ref="515509394"/>
@@ -1504,6 +1511,7 @@
</array>
<string key="NSFrameSize">{398, 672}</string>
<reference key="NSSuperview" ref="356634609"/>
+ <reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="35035542"/>
<string key="NSReuseIdentifierKey">_NS:1699</string>
<int key="NSsFlags">133682</int>
@@ -1515,13 +1523,15 @@
</array>
<string key="NSFrame">{{406, 0}, {398, 672}}</string>
<reference key="NSSuperview" ref="551452395"/>
+ <reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="515509394"/>
<string key="NSReuseIdentifierKey">_NS:1167</string>
<string key="NSClassName">NSView</string>
</object>
</array>
<string key="NSFrameSize">{804, 672}</string>
<reference key="NSSuperview" ref="439893737"/>
+ <reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="179773046"/>
<string key="NSReuseIdentifierKey">_NS:1163</string>
<bool key="NSIsVertical">YES</bool>
@@ -1530,6 +1540,7 @@
</array>
<string key="NSFrameSize">{804, 672}</string>
<reference key="NSSuperview"/>
+ <reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="551452395"/>
</object>
<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
@@ -2336,6 +2347,22 @@
</object>
<int key="connectionID">582</int>
</object>
+ <object class="IBConnectionRecord">
+ <object class="IBBindingConnection" key="connection">
+ <string key="label">value: objectValue.objectValue</string>
+ <reference key="source" ref="505737748"/>
+ <reference key="destination" ref="125486177"/>
+ <object class="NSNibBindingConnector" key="connector">
+ <reference key="NSSource" ref="505737748"/>
+ <reference key="NSDestination" ref="125486177"/>
+ <string key="NSLabel">value: objectValue.objectValue</string>
+ <string key="NSBinding">value</string>
+ <string key="NSKeyPath">objectValue.objectValue</string>
+ <int key="NSNibBindingConnectorVersion">2</int>
+ </object>
+ </object>
+ <int key="connectionID">612</int>
+ </object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
@@ -3638,7 +3665,7 @@
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
- <int key="maxID">610</int>
+ <int key="maxID">612</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">

0 comments on commit 7e0b0a1

Please sign in to comment.
Something went wrong with that request. Please try again.