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.
18 #import "AIAbstractLogViewerWindowController.h"
19 #import "AILoggerPlugin.h"
20 #import "AICalendarDate.h"
22 @implementation AIChatLog
24 static NSCalendarDate *dateFromFileName(NSString *fileName);
26 - (id)initWithPath:(NSString *)inPath from:(NSString *)inFrom to:(NSString *)inTo serviceClass:(NSString *)inServiceClass
28 if ((self = [super init])) {
29 path = [inPath retain];
30 from = [inFrom retain];
32 serviceClass = [inServiceClass retain];
33 rankingPercentage = 0;
39 - (id)initWithPath:(NSString *)inPath
41 NSString *parentPath = [path stringByDeletingLastPathComponent];
42 NSString *toUID = [parentPath lastPathComponent];
43 NSString *serviceAndFromUID = [[parentPath stringByDeletingLastPathComponent] lastPathComponent];
45 NSString *myServiceClass, *fromUID;
47 //Determine the service and fromUID - should be SERVICE.ACCOUNT_NAME
48 //Check against count to guard in case of old, malformed or otherwise odd folders & whatnot sitting in log base
49 NSArray *serviceAndFromUIDArray = [serviceAndFromUID componentsSeparatedByString:@"."];
51 if ([serviceAndFromUIDArray count] >= 2) {
52 myServiceClass = [serviceAndFromUIDArray objectAtIndex:0];
54 //Use substringFromIndex so we include the rest of the string in the case of a UID with a . in it
55 fromUID = [serviceAndFromUID substringFromIndex:([serviceClass length] + 1)]; //One off for the '.'
58 //Fallback: blank non-nil serviceClass; folderName as the fromUID
60 fromUID = serviceAndFromUID;
63 return [self initWithPath:inPath
66 serviceClass:myServiceClass];
74 [serviceClass release];
89 - (NSString *)serviceClass{
92 - (NSCalendarDate *)date{
93 //Determine the date of this log lazily
95 date = [dateFromFileName([path lastPathComponent]) retain];
101 - (float)rankingPercentage
103 return rankingPercentage;
105 - (void)setRankingPercentage:(float)inRankingPercentage
107 rankingPercentage = inRankingPercentage;
110 - (void)setRankingValueOnArbitraryScale:(float)inRankingValue
112 rankingValue = inRankingValue;
114 - (float)rankingValueOnArbitraryScale
119 - (BOOL)isFromSameDayAsDate:(NSCalendarDate *)inDate
121 return [[self date] dayOfCommonEra] == [inDate dayOfCommonEra];
124 #pragma mark Sort Selectors
126 //Sort by To, then Date
127 - (NSComparisonResult)compareTo:(AIChatLog *)inLog
129 NSComparisonResult result = [to caseInsensitiveCompare:[inLog to]];
130 if (result == NSOrderedSame) {
131 NSTimeInterval interval = [date timeIntervalSinceDate:[inLog date]];
134 result = NSOrderedAscending;
135 } else if (interval > 0) {
136 result = NSOrderedDescending;
142 - (NSComparisonResult)compareToReverse:(AIChatLog *)inLog
144 NSComparisonResult result = [[inLog to] caseInsensitiveCompare:to];
145 if (result == NSOrderedSame) {
146 NSTimeInterval interval = [date timeIntervalSinceDate:[inLog date]];
149 result = NSOrderedAscending;
150 } else if (interval > 0) {
151 result = NSOrderedDescending;
157 //Sort by From, then Date
158 - (NSComparisonResult)compareFrom:(AIChatLog *)inLog
160 NSComparisonResult result = [from caseInsensitiveCompare:[inLog from]];
161 if (result == NSOrderedSame) {
162 NSTimeInterval interval = [date timeIntervalSinceDate:[inLog date]];
165 result = NSOrderedAscending;
166 } else if (interval > 0) {
167 result = NSOrderedDescending;
173 - (NSComparisonResult)compareFromReverse:(AIChatLog *)inLog
175 NSComparisonResult result = [[inLog from] caseInsensitiveCompare:from];
176 if (result == NSOrderedSame) {
177 NSTimeInterval interval = [date timeIntervalSinceDate:[inLog date]];
180 result = NSOrderedAscending;
181 } else if (interval > 0) {
182 result = NSOrderedDescending;
189 //Sort by Date, then To
190 - (NSComparisonResult)compareDate:(AIChatLog *)inLog
192 NSComparisonResult result;
193 NSTimeInterval interval = [[self date] timeIntervalSinceDate:[inLog date]];
196 result = NSOrderedAscending;
197 } else if (interval > 0) {
198 result = NSOrderedDescending;
200 result = [to caseInsensitiveCompare:[inLog to]];
205 - (NSComparisonResult)compareDateReverse:(AIChatLog *)inLog
207 NSComparisonResult result;
208 NSTimeInterval interval = [[inLog date] timeIntervalSinceDate:[self date]];
211 result = NSOrderedAscending;
212 } else if (interval > 0) {
213 result = NSOrderedDescending;
215 result = [[inLog to] caseInsensitiveCompare:to];
221 -(NSComparisonResult)compareRank:(AIChatLog *)inLog
223 NSComparisonResult result;
224 float otherRankingPercentage = [inLog rankingPercentage];
226 if (rankingPercentage > otherRankingPercentage) {
227 result = NSOrderedDescending;
228 } else if (rankingPercentage < otherRankingPercentage) {
229 result = NSOrderedAscending;
231 result = [to caseInsensitiveCompare:[inLog to]];
236 -(NSComparisonResult)compareRankReverse:(AIChatLog *)inLog
238 NSComparisonResult result;
239 float otherRankingPercentage = [inLog rankingPercentage];
241 if (rankingPercentage > otherRankingPercentage) {
242 result = NSOrderedAscending;
243 } else if (rankingPercentage < otherRankingPercentage) {
244 result = NSOrderedDescending;
246 result = [[inLog to] caseInsensitiveCompare:to];
252 #pragma mark Date utilities
254 //Scan an Adium date string, supahfast C style
255 static BOOL scandate(const char *sample,
256 unsigned long *outyear, unsigned long *outmonth, unsigned long *outdate,
257 BOOL *outHasTime, unsigned long *outhour, unsigned long *outminute, unsigned long *outsecond,
258 signed long *outtimezone)
261 unsigned long component;
263 //Read a date, followed by a '('.
264 //First, find the '('.
265 while (*sample != '(') {
274 //current character is a '(' now, so skip over it.
275 ++sample; //start with the next character
278 while (*sample && (*sample < '0' || *sample > '9')) ++sample;
283 component = strtoul(sample, (char **)&sample, 10);
284 if (outyear) *outyear = component;
288 while (*sample && (*sample < '0' || *sample > '9')) ++sample;
293 component = strtoul(sample, (char **)&sample, 10);
294 if (outmonth) *outmonth = component;
298 while (*sample && (*sample < '0' || *sample > '9')) ++sample;
303 component = strtoul(sample, (char **)&sample, 10);
304 if (outdate) *outdate = component;
307 if (*sample == 'T') {
308 ++sample; //start with the next character
309 if (outHasTime) *outHasTime = YES;
312 while (*sample && (*sample < '0' || *sample > '9')) ++sample;
317 component = strtoul(sample, (char **)&sample, 10);
318 if (outhour) *outhour = component;
322 while (*sample && (*sample < '0' || *sample > '9')) ++sample;
327 component = strtoul(sample, (char **)&sample, 10);
328 if (outminute) *outminute = component;
332 while (*sample && (*sample < '0' || *sample > '9')) ++sample;
337 component = strtoul(sample, (char **)&sample, 10);
338 if (outsecond) *outsecond = component;
341 /*get the time zone*/ {
342 while (*sample && ((*sample < '0' || *sample > '9') && *sample != '-' && *sample != '+')) ++sample;
347 signed long timezone_sign = 1;
350 } else if(*sample == '-') {
353 } else if (*sample) {
354 //There's something here, but it's not a time zone. Bail.
358 signed long timezone_hr = 0;
359 if (*sample >= '0' || *sample <= '9') {
360 timezone_hr += *(sample++) - '0';
362 if (*sample >= '0' || *sample <= '9') {
364 timezone_hr += *(sample++) - '0';
366 signed long timezone_min = 0;
367 if (*sample >= '0' || *sample <= '9') {
368 timezone_min += *(sample++) - '0';
370 if (*sample >= '0' || *sample <= '9') {
372 timezone_min += *(sample++) - '0';
374 if (outtimezone) *outtimezone = (timezone_hr * 60 + timezone_min) * timezone_sign;
382 //Given an Adium log file name, return an NSCalendarDate with year, month, and day specified
383 static NSCalendarDate *dateFromFileName(NSString *fileName)
385 unsigned long year = 0;
386 unsigned long month = 0;
387 unsigned long day = 0;
388 unsigned long hour = 0;
389 unsigned long minute = 0;
390 unsigned long second = 0;
391 signed long timezone = NSNotFound;
394 if (scandate([fileName UTF8String], &year, &month, &day, &hasTime, &hour, &minute, &second, &timezone)) {
395 if (year && month && day) {
396 AICalendarDate *calendarDate;
398 calendarDate = [AICalendarDate dateWithYear:year
404 timeZone:((timezone == NSNotFound) ? nil : [NSTimeZone timeZoneForSecondsFromGMT:(timezone * 60)])];
405 [calendarDate setGranularity:(hasTime ? AISecondGranularity : AIDayGranularity)];