* Adium is the legal property of its developers, whose names are listed in the copyright file included * with this source distribution. * This program is free software; you can redistribute it and/or modify it under the terms of the GNU * General Public License as published by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * You should have received a copy of the GNU General Public License along with this program; if not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #import "AILoginController.h" #import "AILogViewerWindowController.h" #import "AILoggerPlugin.h" #import "AICalendarDate.h" #import <AIUtilities/NSCalendarDate+ISO8601Parsing.h> @implementation AIChatLog static NSCalendarDate * dateFromFileName ( NSString * fileName ); - ( id ) initWithPath: ( NSString * ) inPath from: ( NSString * ) inFrom to: ( NSString * ) inTo serviceClass: ( NSString * ) inServiceClass if (( self = [ super init ])) { relativePath = [ inPath retain ]; serviceClass = [ inServiceClass retain ]; - ( id ) initWithPath: ( NSString * ) inPath NSString * parentPath = [ inPath stringByDeletingLastPathComponent ]; NSString * toUID = [ parentPath lastPathComponent ]; NSString * serviceAndFromUID = [[ parentPath stringByDeletingLastPathComponent ] lastPathComponent ]; NSString * myServiceClass , * fromUID ; //Determine the service and fromUID - should be SERVICE.ACCOUNT_NAME //Check against count to guard in case of old, malformed or otherwise odd folders & whatnot sitting in log base NSArray * serviceAndFromUIDArray = [ serviceAndFromUID componentsSeparatedByString : @"." ]; if ([ serviceAndFromUIDArray count ] >= 2 ) { myServiceClass = handleSpecialCasesForUIDAndServiceClass ( toUID , [ serviceAndFromUIDArray objectAtIndex : 0 ]); //Use substringFromIndex so we include the rest of the string in the case of a UID with a . in it fromUID = [ serviceAndFromUID substringFromIndex : ([ serviceClass length ] + 1 )]; //One off for the '.' //Fallback: blank non-nil serviceClass; folderName as the fromUID fromUID = serviceAndFromUID ; return [ self initWithPath : inPath serviceClass : myServiceClass ]; - ( NSString * ) relativePath { - ( NSString * ) serviceClass { - ( NSCalendarDate * ) date { //Determine the date of this log lazily date = [ dateFromFileName ([ relativePath lastPathComponent ]) retain ]; //Sometimes the filename doesn't have a date (e.g., “jdoe ((null)).chatlog”). In such cases, if it's a chatlog, parse it and get the date from the first element that has one. //We don't do this first because NSXMLParser uses +[NSData dataWithContentsOfURL:], which is painful for large log files. if ([[ relativePath pathExtension ] isEqualToString : @"chatlog" ]) { NSXMLParser * parser = [[ NSXMLParser alloc ] initWithContentsOfURL : [ NSURL fileURLWithPath : [[ AILoggerPlugin logBasePath ] stringByAppendingPathComponent : relativePath ]]]; [ parser setDelegate : self ]; - ( void ) parser: ( NSXMLParser * ) parser didStartElement: ( NSString * ) elementName namespaceURI: ( NSString * ) namespaceURI qualifiedName: ( NSString * ) qualifiedName attributes: ( NSDictionary * ) attributeDict { //Stop at the first element with a date. NSString * dateString = nil ; if (( dateString = [ attributeDict objectForKey : @"time" ])) { date = [[ NSCalendarDate calendarDateWithString : dateString strictly : YES ] retain ]; - ( CGFloat ) rankingPercentage return rankingPercentage ; - ( void ) setRankingPercentage: ( CGFloat ) inRankingPercentage rankingPercentage = inRankingPercentage ; - ( void ) setRankingValueOnArbitraryScale: ( CGFloat ) inRankingValue rankingValue = inRankingValue ; - ( CGFloat ) rankingValueOnArbitraryScale - ( BOOL ) isFromSameDayAsDate: ( NSCalendarDate * ) inDate return [[ self date ] dayOfCommonEra ] == [ inDate dayOfCommonEra ]; #pragma mark Sort Selectors - ( NSComparisonResult ) compareTo: ( AIChatLog * ) inLog NSComparisonResult result = [ to caseInsensitiveCompare : [ inLog to ]]; if ( result == NSOrderedSame ) { NSTimeInterval interval = [ date timeIntervalSinceDate : [ inLog date ]]; result = NSOrderedAscending ; } else if ( interval > 0 ) { result = NSOrderedDescending ; - ( NSComparisonResult ) compareToReverse: ( AIChatLog * ) inLog NSComparisonResult result = [[ inLog to ] caseInsensitiveCompare : to ]; if ( result == NSOrderedSame ) { NSTimeInterval interval = [ date timeIntervalSinceDate : [ inLog date ]]; result = NSOrderedAscending ; } else if ( interval > 0 ) { result = NSOrderedDescending ; //Sort by From, then Date - ( NSComparisonResult ) compareFrom: ( AIChatLog * ) inLog NSComparisonResult result = [ from caseInsensitiveCompare : [ inLog from ]]; if ( result == NSOrderedSame ) { NSTimeInterval interval = [ date timeIntervalSinceDate : [ inLog date ]]; result = NSOrderedAscending ; } else if ( interval > 0 ) { result = NSOrderedDescending ; - ( NSComparisonResult ) compareFromReverse: ( AIChatLog * ) inLog NSComparisonResult result = [[ inLog from ] caseInsensitiveCompare : from ]; if ( result == NSOrderedSame ) { NSTimeInterval interval = [ date timeIntervalSinceDate : [ inLog date ]]; result = NSOrderedAscending ; } else if ( interval > 0 ) { result = NSOrderedDescending ; //Sort by From, then Date - ( NSComparisonResult ) compareService: ( AIChatLog * ) inLog NSComparisonResult result = [ serviceClass caseInsensitiveCompare : inLog . serviceClass ]; if ( result == NSOrderedSame ) { NSTimeInterval interval = [ date timeIntervalSinceDate : inLog . date ]; result = NSOrderedAscending ; } else if ( interval > 0 ) { result = NSOrderedDescending ; - ( NSComparisonResult ) compareServiceReverse: ( AIChatLog * ) inLog NSComparisonResult result = [ inLog . serviceClass caseInsensitiveCompare : serviceClass ]; if ( result == NSOrderedSame ) { NSTimeInterval interval = [ date timeIntervalSinceDate : inLog . date ]; result = NSOrderedAscending ; } else if ( interval > 0 ) { result = NSOrderedDescending ; - ( NSComparisonResult ) compareDate: ( AIChatLog * ) inLog NSComparisonResult result ; NSTimeInterval interval = [[ self date ] timeIntervalSinceDate : [ inLog date ]]; result = NSOrderedAscending ; } else if ( interval > 0 ) { result = NSOrderedDescending ; result = [ to caseInsensitiveCompare : [ inLog to ]]; - ( NSComparisonResult ) compareDateReverse: ( AIChatLog * ) inLog NSComparisonResult result ; NSTimeInterval interval = [[ inLog date ] timeIntervalSinceDate : [ self date ]]; result = NSOrderedAscending ; } else if ( interval > 0 ) { result = NSOrderedDescending ; result = [[ inLog to ] caseInsensitiveCompare : to ]; -( NSComparisonResult ) compareRank: ( AIChatLog * ) inLog NSComparisonResult result ; CGFloat otherRankingPercentage = [ inLog rankingPercentage ]; if ( rankingPercentage > otherRankingPercentage ) { result = NSOrderedDescending ; } else if ( rankingPercentage < otherRankingPercentage ) { result = NSOrderedAscending ; result = [ to caseInsensitiveCompare : [ inLog to ]]; -( NSComparisonResult ) compareRankReverse: ( AIChatLog * ) inLog NSComparisonResult result ; CGFloat otherRankingPercentage = [ inLog rankingPercentage ]; if ( rankingPercentage > otherRankingPercentage ) { result = NSOrderedAscending ; } else if ( rankingPercentage < otherRankingPercentage ) { result = NSOrderedDescending ; result = [[ inLog to ] caseInsensitiveCompare : to ]; #pragma mark Date utilities //Given an Adium log file name, return an NSCalendarDate with year, month, and day specified static NSCalendarDate * dateFromFileName ( NSString * fileName ) unsigned long minute = 0 ; unsigned long second = 0 ; if ( scandate ([ fileName UTF8String ], & year , & month , & day , & hasTime , & hour , & minute , & second , & tzone )) { if ( year && month && day ) { AICalendarDate * calendarDate ; calendarDate = [ AICalendarDate dateWithYear : year timeZone :(( tzone == NSNotFound ) ? nil : [ NSTimeZone timeZoneForSecondsFromGMT : ( tzone * 60 )])]; [ calendarDate setGranularity : ( hasTime ? AISecondGranularity : AIDayGranularity )];