adium-1.4 3271:46c3f8883b98: Back out the earlier backout of AIX...
commits at adium.im
commits at adium.im
Tue Nov 16 10:08:04 UTC 2010
details: http://hg.adium.im/adium-1.4/rev/46c3f8883b98
revision: 3271:46c3f8883b98
author: Colin Barrett <colin at springsandstruts.com>
date: Tue Nov 16 02:00:34 2010 -0800
Back out the earlier backout of AIXMLChatlogConverter NSXMLDocument that was done for 1.4.1
Subject: adium-1.4 3272:3c3f46b4f59b: Fix build
details: http://hg.adium.im/adium-1.4/rev/3c3f46b4f59b
revision: 3272:3c3f46b4f59b
author: Colin Barrett <colin at springsandstruts.com>
date: Tue Nov 16 02:07:30 2010 -0800
Fix build
diffs (681 lines):
diff -r f3540daa81d8 -r 3c3f46b4f59b Plists/Info.plist
--- a/Plists/Info.plist Tue Nov 16 01:52:41 2010 -0800
+++ b/Plists/Info.plist Tue Nov 16 02:07:30 2010 -0800
@@ -469,11 +469,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
-<<<<<<< local
<string>1.4.2hg</string>
-=======
- <string>1.4.1</string>
->>>>>>> other
<key>LSMinimumSystemVersion</key>
<string>10.5.8</string>
<key>LSRequiresNativeExecution</key>
diff -r f3540daa81d8 -r 3c3f46b4f59b Source/AIXMLChatlogConverter.h
--- a/Source/AIXMLChatlogConverter.h Tue Nov 16 01:52:41 2010 -0800
+++ b/Source/AIXMLChatlogConverter.h Tue Nov 16 02:07:30 2010 -0800
@@ -14,15 +14,6 @@
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-
-typedef enum{
- XML_STATE_NONE,
- XML_STATE_CHAT,
- XML_STATE_MESSAGE,
- XML_STATE_EVENT_MESSAGE,
- XML_STATE_STATUS_MESSAGE
-} chatLogState;
-
/*!
* @brief Different ways of formatting display names
*/
@@ -37,34 +28,12 @@
@class AIHTMLDecoder;
@interface AIXMLChatlogConverter : NSObject {
- CFXMLParserRef parser;
- NSString *inputFileString;
- NSDictionary *eventTranslate;
-
- NSDateFormatter *dateFormatter;
-
- chatLogState state;
- NSString *sender;
- NSString *senderAlias;
- NSString *mySN;
- NSString *service;
- NSString *myDisplayName;
- NSCalendarDate *date;
- NSInteger messageStart;
- BOOL autoResponse;
- BOOL showTimestamps;
- BOOL showEmoticons;
- NSString *status;
-
- NSMutableAttributedString *output;
- NSAttributedString *newlineAttributedString;
+ NSDateFormatter *dateFormatter;
NSDictionary *statusLookup;
+ NSAttributedString *newlineAttributedString;
AIHTMLDecoder *htmlDecoder;
-
- AINameFormat nameFormat;
}
+ (NSAttributedString *)readFile:(NSString *)filePath withOptions:(NSDictionary *)options;
-- (NSAttributedString *)readFile:(NSString *)filePath withOptions:(NSDictionary *)options;
@end
diff -r f3540daa81d8 -r 3c3f46b4f59b Source/AIXMLChatlogConverter.m
--- a/Source/AIXMLChatlogConverter.m Tue Nov 16 01:52:41 2010 -0800
+++ b/Source/AIXMLChatlogConverter.m Tue Nov 16 02:07:30 2010 -0800
@@ -31,37 +31,98 @@
#define KEY_WEBKIT_USE_NAME_FORMAT @"Use Custom Name Format"
#define KEY_WEBKIT_NAME_FORMAT @"Name Format"
-static void *createStructure(CFXMLParserRef parser, CFXMLNodeRef node, void *context);
-static void addChild(CFXMLParserRef parser, void *parent, void *child, void *context);
-static void endStructure(CFXMLParserRef parser, void *xmlType, void *context);
+ at interface NSMutableString (XMLMethods)
+- (void)stripInvalidCharacters;
+ at end
+
+ at implementation NSMutableString (XMLMethods)
+
+//Strip invalid XML characters
+- (void)stripInvalidCharacters
+{
+ static NSCharacterSet *invalidXMLCharacterSet;
+
+ if (invalidXMLCharacterSet == nil)
+ {
+ // First, create a character set containing all valid UTF8 characters.
+ NSMutableCharacterSet *xmlCharacterSet = [[NSMutableCharacterSet alloc] init];
+ [xmlCharacterSet addCharactersInRange:NSMakeRange(0x9, 1)];
+ [xmlCharacterSet addCharactersInRange:NSMakeRange(0xA, 1)];
+ [xmlCharacterSet addCharactersInRange:NSMakeRange(0xD, 1)];
+ [xmlCharacterSet addCharactersInRange:NSMakeRange(0x20, 0xD7FF - 0x20)];
+ [xmlCharacterSet addCharactersInRange:NSMakeRange(0xE000, 0xFFFD - 0xE000)];
+ [xmlCharacterSet addCharactersInRange:NSMakeRange(0x10000, 0x10FFFF - 0x10000)];
+ // Then create and retain an inverted set, which will thus contain all invalid XML characters.
+ invalidXMLCharacterSet = [[xmlCharacterSet invertedSet] retain];
+ [xmlCharacterSet release];
+ }
+
+ // Are there any invalid characters in this string?
+ NSRange range = [self rangeOfCharacterFromSet:invalidXMLCharacterSet];
+
+ // Otherwise go through and remove any illegal XML characters from a copy of the string.
+ while (range.length > 0)
+ {
+ [self deleteCharactersInRange:range];
+ range = [self rangeOfCharacterFromSet:invalidXMLCharacterSet
+ options:0
+ range:NSMakeRange(range.location,[self length]-range.location)];
+ }
+}
+
+ at end
+
+ at interface NSXMLElement (AIAttributeDict)
+- (NSDictionary *)AIAttributesAsDictionary;
+ at end
+
+ at implementation NSXMLElement (AIAttributeDict)
+
+- (NSDictionary *)AIAttributesAsDictionary
+{
+ NSArray *attrArray = [self attributes];
+ NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
+ for (NSXMLNode *attr in attrArray) {
+ [attributes setObject:attr forKey:[attr name]];
+ }
+ return attributes;
+}
+
+ at end
+
+ at interface AIXMLChatlogConverter()
+- (NSAttributedString *)readData:(NSData *)xmlData withOptions:(NSDictionary *)options retrying:(BOOL)reentrancyFlag;
+ at end
@implementation AIXMLChatlogConverter
+ (NSAttributedString *)readFile:(NSString *)filePath withOptions:(NSDictionary *)options
{
- AIXMLChatlogConverter *converter = [[AIXMLChatlogConverter alloc] init];
- NSAttributedString *ret = [[converter readFile:filePath withOptions:options] retain];
- [converter release];
- return [ret autorelease];
+ static AIXMLChatlogConverter *converter;
+ if (!converter) {
+ converter = [[AIXMLChatlogConverter alloc] init];
+ }
+ NSData *xmlData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:filePath]];
+ [converter->htmlDecoder setBaseURL:[filePath stringByDeletingLastPathComponent]];
+ NSAttributedString *result = nil;
+ @try {
+ result = [converter readData:xmlData withOptions:options retrying:NO];
+ } @catch (NSException *e) {
+ NSLog(@"Error \"%@\" parsing log file at %@.", e, filePath);
+ return [[[NSAttributedString alloc] initWithString:@"Sorry, there was an error parsing this transcript. It may be corrupt."] autorelease];
+ }
+ return result;
}
- (id)init
{
if ((self = [super init])) {
-
- state = XML_STATE_NONE;
-
- inputFileString = nil;
- sender = nil;
- mySN = nil;
- myDisplayName = nil;
- date = nil;
- parser = NULL;
- status = nil;
-
+ if (!newlineAttributedString) {
+ newlineAttributedString = [[NSAttributedString alloc] initWithString:@"\n" attributes:nil];
+ }
+
+ htmlDecoder = [[AIHTMLDecoder alloc] init];
dateFormatter = [[NSDateFormatter localizedDateFormatterShowingSeconds:YES showingAMorPM:YES] retain];
-
- newlineAttributedString = [[NSAttributedString alloc] initWithString:@"\n" attributes:nil];
statusLookup = [[NSDictionary alloc] initWithObjectsAndKeys:
AILocalizedString(@"Online", nil), @"online",
@@ -81,14 +142,6 @@
[adium.statusController localizedDescriptionForCoreStatusName:STATUS_NAME_NOT_IN_OFFICE], @"notInTheOffice",
[adium.statusController localizedDescriptionForCoreStatusName:STATUS_NAME_STEPPED_OUT], @"steppedOut",
nil];
-
- if ([[adium.preferenceController preferenceForKey:KEY_WEBKIT_USE_NAME_FORMAT
- group:PREF_GROUP_WEBKIT_MESSAGE_DISPLAY] boolValue]) {
- nameFormat = [[adium.preferenceController preferenceForKey:KEY_WEBKIT_NAME_FORMAT
- group:PREF_GROUP_WEBKIT_MESSAGE_DISPLAY] integerValue];
- } else {
- nameFormat = AIDefaultName;
- }
}
return self;
@@ -97,317 +150,173 @@
- (void)dealloc
{
[dateFormatter release];
- [newlineAttributedString release];
- [inputFileString release];
- [eventTranslate release];
- [sender release];
- [senderAlias release];
- [mySN release];
- [myDisplayName release];
- [service release];
- [date release];
- [status release];
- [output release];
[statusLookup release];
[htmlDecoder release];
[super dealloc];
}
-- (NSAttributedString *)readFile:(NSString *)filePath withOptions:(NSDictionary *)options
+- (NSAttributedString *)readData:(NSData *)xmlData withOptions:(NSDictionary *)options retrying:(BOOL)reentrancyFlag
{
- NSData *inputData = [NSData dataWithContentsOfFile:filePath];
- inputFileString = [[NSString alloc] initWithData:inputData encoding:NSUTF8StringEncoding];
- NSURL *url = [[NSURL alloc] initFileURLWithPath:filePath];
- output = [[NSMutableAttributedString alloc] init];
+ if (!xmlData) {
+ return [[[NSAttributedString alloc] initWithString:@""] autorelease];
+ }
+ AINameFormat nameFormat;
+ if ([[adium.preferenceController preferenceForKey:KEY_WEBKIT_USE_NAME_FORMAT
+ group:PREF_GROUP_WEBKIT_MESSAGE_DISPLAY] boolValue]) {
+ nameFormat = [[adium.preferenceController preferenceForKey:KEY_WEBKIT_NAME_FORMAT
+ group:PREF_GROUP_WEBKIT_MESSAGE_DISPLAY] integerValue];
+ } else {
+ nameFormat = AIDefaultName;
+ }
+ NSMutableAttributedString *output = [[[NSMutableAttributedString alloc] init] autorelease];
+
+ NSError *err=nil;
+ NSXMLDocument *xmlDoc = [[[NSXMLDocument alloc] initWithData:xmlData
+ options:NSXMLNodePreserveCDATA
+ error:&err] autorelease];
- htmlDecoder = [[AIHTMLDecoder alloc] init];
- [htmlDecoder setBaseURL:[filePath stringByDeletingLastPathComponent]];
-
- showTimestamps = [[options objectForKey:@"showTimestamps"] boolValue];
- showEmoticons = [[options objectForKey:@"showEmoticons"] boolValue];
+ if (!xmlDoc)
+ {
+ goto ohno;
+ }
+
+ BOOL showTimestamps = [[options objectForKey:@"showTimestamps"] boolValue];
+ BOOL showEmoticons = [[options objectForKey:@"showEmoticons"] boolValue];
+
+ NSXMLElement *chatElement = [[xmlDoc nodesForXPath:@"//chat" error:&err] lastObject];
+
+ NSDictionary *chatAttributes = [chatElement AIAttributesAsDictionary];
+ NSString *mySN = [[chatAttributes objectForKey:@"account"] stringValue];
+ NSString *service = [[chatAttributes objectForKey:@"service"] stringValue];
+
+ NSString *myDisplayName = nil;
+
+ for (AIAccount *account in adium.accountController.accounts) {
+ if ([[account.UID compactedString] isEqualToString:[mySN compactedString]] &&
+ [account.service.serviceID isEqualToString:service]) {
+ myDisplayName = [account.displayName retain];
+ break;
+ }
+ }
+
+ NSArray *elements = [xmlDoc nodesForXPath:@"//message | //status" error:&err];
+ if (!elements) {
+ goto ohno;
+ }
+
+ for (NSXMLElement *element in elements) {
+ NSString *type = [element name];
+
+ NSDictionary *attributes = [element AIAttributesAsDictionary];
+
+ if ([type isEqualToString:@"message"]) {
+ NSString *senderAlias = [[attributes objectForKey:@"alias"] stringValue];
+ NSString *dateStr = [[attributes objectForKey:@"time"] stringValue];
+ NSDate *date = dateStr ? [NSCalendarDate calendarDateWithString:dateStr] : nil;
+ NSString *sender = [[attributes objectForKey:@"sender"] stringValue];
+ NSString *shownSender = (senderAlias ? senderAlias : sender);
+ BOOL autoResponse = [[[attributes objectForKey:@"auto"] stringValue] isEqualToString:@"true"];
- CFXMLParserCallBacks callbacks = {
- 0,
- createStructure,
- addChild,
- endStructure,
- NULL,
- NULL
- };
- CFXMLParserContext context = {
- 0,
- self,
- CFRetain,
- CFRelease,
- NULL
- };
- parser = CFXMLParserCreate(NULL, (CFDataRef)inputData, NULL, kCFXMLParserSkipMetaData | kCFXMLParserSkipWhitespace, kCFXMLNodeCurrentVersion, &callbacks, &context);
- if (!CFXMLParserParse(parser)) {
- NSLog(@"%@: Parser %@ for inputFileString %@ returned false.",
- [self class], parser, inputFileString);
- [output release];
- output = nil;
- }
- CFRelease(parser);
- parser = nil;
- [url release];
- return output;
-}
+ NSMutableString *messageXML = [NSMutableString string];
+ for (NSXMLNode *node in [element children]) {
+ [messageXML appendString:[node XMLString]];
+ }
+
+ NSString *displayName = nil, *longDisplayName = nil;
+
+ BOOL sentMessage = [mySN isEqualToString:sender];
-- (void)startedElement:(NSString *)name info:(const CFXMLElementInfo *)info
-{
- NSDictionary *attributes = (NSDictionary *)info->attributes;
-
- switch(state){
- case XML_STATE_NONE:
- if([name isEqualToString:@"chat"])
- {
- [mySN release];
- mySN = [[attributes objectForKey:@"account"] retain];
+
+ if (sentMessage) {
+ //Find an account if one exists, and use its name
+ displayName = (myDisplayName ? myDisplayName : sender);
+ } else {
+ AIListObject *listObject = [adium.contactController existingListObjectWithUniqueID:[AIListObject internalObjectIDForServiceID:service UID:sender]];
+
+ displayName = listObject.displayName;
+ longDisplayName = [listObject longDisplayName];
+ }
+
+ if (displayName && !sentMessage) {
+ switch (nameFormat) {
+ case AIDefaultName:
+ shownSender = (longDisplayName ? longDisplayName : displayName);
+ break;
+
+ case AIDisplayName:
+ shownSender = displayName;
+ break;
+
+ case AIDisplayName_ScreenName:
+ shownSender = [NSString stringWithFormat:@"%@ (%@)",displayName,sender];
+ break;
+
+ case AIScreenName_DisplayName:
+ shownSender = [NSString stringWithFormat:@"%@ (%@)",sender,displayName];
+ break;
+
+ case AIScreenName:
+ shownSender = sender;
+ break;
+ }
+ }
- [service release];
- service = [[attributes objectForKey:@"service"] retain];
+ NSString *timestampStr = [dateFormatter stringFromDate:date];
- [myDisplayName release];
- myDisplayName = nil;
+ [output appendAttributedString:[htmlDecoder decodeHTML:[NSString stringWithFormat:
+ @"<div class=\"%@\">%@<span class=\"sender\">%@%@:</span></div> ",
+ (sentMessage ? @"send" : @"receive"),
+ (showTimestamps ? [NSString stringWithFormat:@"<span class=\"timestamp\">%@</span> ", timestampStr] : @""),
+ shownSender, (autoResponse ? AILocalizedString(@" (Autoreply)", nil) : @"")]]];
- for (AIAccount *account in adium.accountController.accounts) {
- if ([[account.UID compactedString] isEqualToString:[mySN compactedString]] &&
- [account.service.serviceID isEqualToString:service]) {
- myDisplayName = [account.displayName retain];
- break;
- }
- }
-
- state = XML_STATE_CHAT;
- }
- break;
- case XML_STATE_CHAT:
- if([name isEqualToString:@"message"])
- {
- [sender release];
- [senderAlias release];
- [date release];
-
- NSString *dateStr = [attributes objectForKey:@"time"];
- if(dateStr != nil)
- date = [[NSCalendarDate calendarDateWithString:dateStr] retain];
- else
- date = nil;
- sender = [[attributes objectForKey:@"sender"] retain];
- senderAlias = [[attributes objectForKey:@"alias"] retain];
- autoResponse = [[attributes objectForKey:@"auto"] isEqualToString:@"true"];
-
- //Mark the location of the message... We can copy it directly. Anyone know why it is off by 1?
- messageStart = CFXMLParserGetLocation(parser) - 1;
-
- state = XML_STATE_MESSAGE;
- }
- else if([name isEqualToString:@"event"])
- {
- //Mark the location of the message... We can copy it directly. Anyone know why it is off by 1?
- messageStart = CFXMLParserGetLocation(parser) - 1;
-
- state = XML_STATE_EVENT_MESSAGE;
- }
- else if([name isEqualToString:@"status"])
- {
- [status release];
- [date release];
-
- NSString *dateStr = [attributes objectForKey:@"time"];
- if(dateStr != nil)
- date = [[NSCalendarDate calendarDateWithString:dateStr] retain];
- else
- date = nil;
-
- status = [[attributes objectForKey:@"type"] retain];
-
- //Mark the location of the message... We can copy it directly. Anyone know why it is off by 1?
- messageStart = CFXMLParserGetLocation(parser) - 1;
-
- state = XML_STATE_STATUS_MESSAGE;
- }
- break;
- case XML_STATE_MESSAGE:
- case XML_STATE_EVENT_MESSAGE:
- case XML_STATE_STATUS_MESSAGE:
- break;
- }
-}
-
-- (void)endedElement:(NSString *)name empty:(BOOL)empty
-{
- switch(state)
- {
- case XML_STATE_EVENT_MESSAGE:
- state = XML_STATE_CHAT;
- break;
-
- case XML_STATE_MESSAGE:
- if([name isEqualToString:@"message"])
- {
- CFIndex end = CFXMLParserGetLocation(parser);
- NSString *message = nil;
- if (!empty) {
- // 11 = 10 for </message> and 1 for the index being off
- message = [inputFileString substringWithRange:NSMakeRange(messageStart, end - messageStart - 11)];
- }
- NSString *shownSender = (senderAlias ? senderAlias : sender);
- NSString *cssClass;
- NSString *displayName = nil, *longDisplayName = nil;
-
- if ([mySN isEqualToString:sender]) {
- //Find an account if one exists, and use its name
- displayName = (myDisplayName ? myDisplayName : sender);
- cssClass = @"send";
- } else {
- AIListObject *listObject = [adium.contactController existingListObjectWithUniqueID:[AIListObject internalObjectIDForServiceID:service UID:sender]];
-
- cssClass = @"receive";
- displayName = listObject.displayName;
- longDisplayName = [listObject longDisplayName];
- }
-
- if (displayName && ![displayName isEqualToString:sender]) {
- switch (nameFormat) {
- case AIDefaultName:
- shownSender = (longDisplayName ? longDisplayName : displayName);
- break;
-
- case AIDisplayName:
- shownSender = displayName;
- break;
-
- case AIDisplayName_ScreenName:
- shownSender = [NSString stringWithFormat:@"%@ (%@)",displayName,sender];
- break;
-
- case AIScreenName_DisplayName:
- shownSender = [NSString stringWithFormat:@"%@ (%@)",sender,displayName];
- break;
-
- case AIScreenName:
- shownSender = sender;
- break;
- }
- }
-
- NSString *timestampStr = [dateFormatter stringFromDate:date];
-
- BOOL sentMessage = [mySN isEqualToString:sender];
- [output appendAttributedString:[htmlDecoder decodeHTML:[NSString stringWithFormat:
- @"<div class=\"%@\">%@<span class=\"sender\">%@%@:</span></div> ",
- (sentMessage ? @"send" : @"receive"),
- (showTimestamps ? [NSString stringWithFormat:@"<span class=\"timestamp\">%@</span> ", timestampStr] : @""),
- shownSender, (autoResponse ? AILocalizedString(@" (Autoreply)", nil) : @"")]]];
-
- NSAttributedString *attributedMessage = [htmlDecoder decodeHTML:message];
- if (showEmoticons) {
- attributedMessage = [adium.contentController filterAttributedString:attributedMessage
- usingFilterType:AIFilterMessageDisplay
- direction:(sentMessage ? AIFilterOutgoing : AIFilterIncoming)
- context:nil];
- }
- [output appendAttributedString:attributedMessage];
- [output appendAttributedString:newlineAttributedString];
-
- state = XML_STATE_CHAT;
- }
- break;
- case XML_STATE_STATUS_MESSAGE:
- if([name isEqualToString:@"status"])
- {
- CFIndex end = CFXMLParserGetLocation(parser);
- NSString *message = nil;
- if(!empty)
- message = [inputFileString substringWithRange:NSMakeRange(messageStart, end - messageStart - 10)]; // 9 for </status> and 1 for the index being off
-
- NSString *displayMessage = nil;
- //Note: I am diverging from what the AILoggerPlugin logs in this case. It can't handle every case we can have here
- if([message length])
- {
- if([statusLookup objectForKey:status])
- displayMessage = [NSString stringWithFormat:AILocalizedString(@"Changed status to %@: %@", nil), [statusLookup objectForKey:status], message];
- else
- displayMessage = [NSString stringWithFormat:AILocalizedString(@"%@", nil), message];
- }
- else if([status length] && [statusLookup objectForKey:status])
- displayMessage = [NSString stringWithFormat:AILocalizedString(@"Changed status to %@", nil), [statusLookup objectForKey:status]];
-
- if([displayMessage length])
- [output appendAttributedString:[htmlDecoder decodeHTML:[NSString stringWithFormat:@"<div class=\"status\">%@ (%@)</div>\n",
- displayMessage,
- [dateFormatter stringFromDate:date]]]];
- state = XML_STATE_CHAT;
- }
- case XML_STATE_CHAT:
- if([name isEqualToString:@"chat"])
- state = XML_STATE_NONE;
- break;
- case XML_STATE_NONE:
- break;
- }
-}
-
-typedef struct{
- NSString *name;
- BOOL empty;
-} element;
-
-void *createStructure(CFXMLParserRef parser, CFXMLNodeRef node, void *context)
-{
- element *ret = NULL;
-
- // Use the dataTypeID to determine what to print.
- switch (CFXMLNodeGetTypeCode(node)) {
- case kCFXMLNodeTypeDocument:
- break;
- case kCFXMLNodeTypeElement:
- {
- NSString *name = [NSString stringWithString:(NSString *)CFXMLNodeGetString(node)];
- const CFXMLElementInfo *info = CFXMLNodeGetInfoPtr(node);
- [(AIXMLChatlogConverter *)context startedElement:name info:info];
- ret = (element *)malloc(sizeof(element));
- ret->name = [name retain];
- ret->empty = info->isEmpty;
- break;
- }
- case kCFXMLNodeTypeProcessingInstruction:
- case kCFXMLNodeTypeComment:
- case kCFXMLNodeTypeText:
- case kCFXMLNodeTypeCDATASection:
- case kCFXMLNodeTypeEntityReference:
- case kCFXMLNodeTypeDocumentType:
- case kCFXMLNodeTypeWhitespace:
- default:
- break;
- }
-
- // Return the data string for use by the addChild and
- // endStructure callbacks.
- return (void *) ret;
-}
-
-void addChild(CFXMLParserRef parser, void *parent, void *child, void *context)
-{
-}
-
-void endStructure(CFXMLParserRef parser, void *xmlType, void *context)
-{
- NSString *name = nil;
- BOOL empty = NO;
- if(xmlType != NULL)
- {
- name = [NSString stringWithString:((element *)xmlType)->name];
- empty = ((element *)xmlType)->empty;
- }
- [(AIXMLChatlogConverter *)context endedElement:name empty:empty];
- if(xmlType != NULL)
- {
- [((element *)xmlType)->name release];
- free(xmlType);
- }
+ NSAttributedString *attributedMessage = [htmlDecoder decodeHTML:messageXML];
+ if (showEmoticons) {
+ attributedMessage = [adium.contentController filterAttributedString:attributedMessage
+ usingFilterType:AIFilterMessageDisplay
+ direction:(sentMessage ? AIFilterOutgoing : AIFilterIncoming)
+ context:nil];
+ }
+ [output appendAttributedString:attributedMessage];
+ [output appendAttributedString:newlineAttributedString];
+ } else if ([type isEqualToString:@"status"]) {
+ NSString *dateStr = [[attributes objectForKey:@"time"] stringValue];
+ NSDate *date = dateStr ? [NSCalendarDate calendarDateWithString:dateStr] : nil;
+ NSString *status = [[attributes objectForKey:@"type"] stringValue];
+
+ NSMutableString *messageXML = [NSMutableString string];
+ for (NSXMLNode *node in [element children]) {
+ [messageXML appendString:[node XMLString]];
+ }
+
+ NSString *displayMessage = nil;
+ //Note: I am diverging from what the AILoggerPlugin logs in this case. It can't handle every case we can have here
+ if([messageXML length]) {
+ if([statusLookup objectForKey:status]) {
+ displayMessage = [NSString stringWithFormat:AILocalizedString(@"Changed status to %@: %@", nil), [statusLookup objectForKey:status], messageXML];
+ } else {
+ displayMessage = [NSString stringWithFormat:AILocalizedString(@"%@", nil), messageXML];
+ }
+ } else if([status length] && [statusLookup objectForKey:status]) {
+ displayMessage = [NSString stringWithFormat:AILocalizedString(@"Changed status to %@", nil), [statusLookup objectForKey:status]];
+ }
+
+ if([displayMessage length]) {
+ [output appendAttributedString:[htmlDecoder decodeHTML:[NSString stringWithFormat:@"<div class=\"status\">%@ (%@)</div>\n",
+ displayMessage,
+ [dateFormatter stringFromDate:date]]]];
+ }
+ }
+ }
+
+ return output;
+
+ohno:
+ if (!reentrancyFlag) {
+ NSMutableString *xmlString = [NSMutableString stringWithUTF8String:[xmlData bytes]];
+ [xmlString stripInvalidCharacters];
+ return [self readData:[xmlString dataUsingEncoding:NSUTF8StringEncoding] withOptions:options retrying:YES];
+ }
+ @throw [NSException exceptionWithName:@"Log File Parsing Error" reason:[err description] userInfo:nil];
}
@end
More information about the commits
mailing list