2 * Adium is the legal property of its developers, whose names are listed in the copyright file included
3 * with this source distribution.
5 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * General Public License as published by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11 * Public License for more details.
13 * You should have received a copy of the GNU General Public License along with this program; if not,
14 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 #import "BGICLogImportController.h"
18 #import "AIXMLAppender.h"
19 #import "AILoggerPlugin.h"
20 #import "AICoreComponentLoader.h"
21 #import <Adium/AIHTMLDecoder.h>
22 #import <Adium/AILoginControllerProtocol.h>
23 #import <AIUtilities/NSCalendarDate+ISO8601Unparsing.h>
24 #import <AIUtilities/AIFileManagerAdditions.h>
26 // InstantMessage and other iChat transcript classes are from Spiny Software's Logorrhea, used with permission.
27 #import "InstantMessage.h"
28 #import "Presentity.h"
31 #define TEST_LOGGING_LOCATION [@"~/Desktop/testLog" stringByExpandingTildeInPath]
33 @implementation BGICLogImportController
35 /* an iChat log importer needs to be set up with a destination pair, specified as @"service.account" to match current representation(s) in PATH_LOGS */
36 -(id)initWithDestination:(NSString *)newSAPair
40 importServiceAccountPair = [newSAPair copy];
46 [importServiceAccountPair release];
50 -(BOOL)createNewLogForPath:(NSString *)fullPath
52 AIHTMLDecoder *xhtmlDecoder = [[AIHTMLDecoder alloc] initWithHeaders:NO
60 onlyIncludeOutgoingImages:NO
63 allowJavascriptURLs:YES];
64 [xhtmlDecoder setGeneratesStrictXHTML:YES];
65 [xhtmlDecoder setUsesAttachmentTextEquivalents:YES];
67 // read the raw file into an array for working against, two different formats have been employed by iChat, based on available classes
68 fullPath = [[NSFileManager defaultManager] pathByResolvingAlias:fullPath];
74 rawChat = ([[fullPath pathExtension] isEqual:@"ichat"] ?
75 [NSKeyedUnarchiver unarchiveObjectWithFile:fullPath] :
76 [NSUnarchiver unarchiveObjectWithFile:fullPath]);
78 @catch (NSException *releaseException)
80 NSLog(@"Could not open iChat log at %@: %@", fullPath, releaseException);
84 if (!rawChat) return NO;
86 NSString *preceedingPath = nil;
89 preceedingPath = [[[[adium loginController] userDirectory] stringByAppendingPathComponent:PATH_LOGS] stringByExpandingTildeInPath];
91 preceedingPath = TEST_LOGGING_LOCATION;
95 [rawChat objectAtIndex:0],
96 TEST_ACCOUNT, // this has to be matched somehow, I can't see a way offhand through as iChat stores the originating party
98 NSString *parentPath = [preceedingPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@/%@",
99 importServiceAccountPair, // see commented code above for a brittle methodology
100 [[[rawChat objectAtIndex:3] objectAtIndex:0] senderID] // this is improperly brittle and imprecise
103 // create a new xml parser for logs
104 NSString *documentPath = [parentPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@ (%@).chatlog", [[[rawChat objectAtIndex:3] objectAtIndex:0] senderID], [[[[rawChat objectAtIndex:2] objectAtIndex:0] date] dateWithCalendarFormat:@"%Y-%m-%dT%H.%M.%S%z" timeZone:nil]]];
105 AIXMLAppender *appender = [AIXMLAppender documentWithPath:documentPath];
106 [appender setFullSyncAfterEachAppend:NO];
108 // set up the initial layout of the xml log
109 [appender initializeDocumentWithRootElementName:@"chat"
110 attributeKeys:[NSArray arrayWithObjects:@"xmlns", @"account", @"service", nil]
111 attributeValues:[NSArray arrayWithObjects:
112 XML_LOGGING_NAMESPACE,
113 [[[rawChat objectAtIndex:3] objectAtIndex:0] senderID],
114 [rawChat objectAtIndex:0],
115 // [[chat account] UID], // pulled from iChat transcript
116 // [[chat account] serviceID], // pulled from iChat transcript
119 // sequentially add the messages from the iChat transcript sans attributed text features
120 for(int i = 0; i < [[rawChat objectAtIndex:2] count]; i++)
122 NSMutableArray *attributeKeys = [NSMutableArray arrayWithObjects:@"sender", @"time", nil];
123 NSMutableArray *attributeValues = [NSMutableArray arrayWithObjects:
124 ([[(InstantMessage *)[[rawChat objectAtIndex:2] objectAtIndex:i] sender] senderID] != nil ? [[(InstantMessage *)[[rawChat objectAtIndex:2] objectAtIndex:i] sender] senderID] : @""),
125 [[[(InstantMessage *)[[rawChat objectAtIndex:2] objectAtIndex:i] date] dateWithCalendarFormat:nil timeZone:nil] ISO8601DateString],
128 NSMutableString *chatContents = [[[xhtmlDecoder encodeHTML:[[[rawChat objectAtIndex:2] objectAtIndex:i] text] imagesPath:nil] mutableCopy] autorelease];
130 [appender addElementWithName:(![[[(InstantMessage *)[[rawChat objectAtIndex:2] objectAtIndex:i] sender] senderID] isEqual:@""] ? @"message" : @"event")
131 escapedContent:chatContents
132 attributeKeys:([attributeValues count] == 2 ? attributeKeys : nil)
133 attributeValues:([attributeValues count] == 2 ? attributeValues : nil)];
136 //Force this log to disk immediately
137 [appender performFullSync];
139 if ([[NSFileManager defaultManager] fileExistsAtPath:documentPath]) {
140 [(AILoggerPlugin *)[[adium componentLoader] pluginWithClassName:@"AILoggerPlugin"] markLogDirtyAtPath:documentPath];