diff --git a/.gitignore b/.gitignore index bc41820..7d91e7a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Mac OS X *.DS_Store +.DS_Store # Xcode *.pbxuser diff --git a/src/.DS_Store b/src/.DS_Store index 907d341..6c8193a 100644 Binary files a/src/.DS_Store and b/src/.DS_Store differ diff --git a/src/ACWebDAV/.DS_Store b/src/ACWebDAV/.DS_Store index 8f906be..72a255a 100644 Binary files a/src/ACWebDAV/.DS_Store and b/src/ACWebDAV/.DS_Store differ diff --git a/src/ACWebDAV/ACWebDAVClient.h b/src/ACWebDAV/ACWebDAVClient.h index 205c3d7..2556f0c 100644 --- a/src/ACWebDAV/ACWebDAVClient.h +++ b/src/ACWebDAV/ACWebDAVClient.h @@ -71,11 +71,15 @@ @protocol ACWebDAVClientDelegate @optional +- (BOOL)needToCancelDownload; +- (void)resetCancelDownload:(BOOL)cancel; +- (BOOL)needToCancelUpload; +- (void)resetCancelUpload:(BOOL)cancel; - (void)client:(ACWebDAVClient*)client failedWithError:(NSError*)error; - (void)client:(ACWebDAVClient*)client failedWithErrorCode:(int)errorCode; -- (void)client:(ACWebDAVClient*)client loadedMetadata:(ACWebDAVItem*)item; +- (void)client:(ACWebDAVClient*)client loadedMetadata:(NSArray *)items; - (void)client:(ACWebDAVClient*)client loadMetadataFailedWithError:(NSError*)error; - (void)client:(ACWebDAVClient*)client loadMetadataFailedWithErrorCode:(int)errorCode; diff --git a/src/ACWebDAV/ACWebDAVClient.m b/src/ACWebDAV/ACWebDAVClient.m index 79cebcf..13f7189 100644 --- a/src/ACWebDAV/ACWebDAVClient.m +++ b/src/ACWebDAV/ACWebDAVClient.m @@ -42,6 +42,10 @@ +(ACWebDAVClient*)clientForMobileMeWithUsername:(NSString *)_username password:( return [self clientWithHost:[@"http://idisk.mac.com/" stringByAppendingString:_username] username:_username password:_password]; } + + + + #pragma mark - #pragma mark Properties @@ -57,6 +61,11 @@ -(void)setHost:(NSString*)value { } } + + + + + #pragma mark - #pragma mark Client Methods @@ -112,7 +121,7 @@ -(void)copyFrom:(NSString*)fromHref toPath:(NSString*)toHref { -(void)copyFrom:(NSString*)fromHref toPath:(NSString*)toHref overwrite:(BOOL)overwrite { ACWebDAVLocation* location = [ACWebDAVLocation locationWithHost:self.host href:fromHref username:self.username password:self.password]; ACWebDAVLocation* destination = [ACWebDAVLocation locationWithHost:self.host href:toHref username:self.username password:self.password]; - ACWebDAVCopyRequest* request = [ACWebDAVCopyRequest requestToCopyItem:[ACWebDAVItem itemWithLocation:location] toLocation:destination delegate:self]; + ACWebDAVCopyRequest* request = [ACWebDAVCopyRequest requestToCopyItem:[ACWebDAVItem itemWithLocation:location] toLocation:destination overWrite:NO delegate:self]; [request start]; } @@ -123,7 +132,7 @@ -(void)moveFrom:(NSString*)fromHref toPath:(NSString*)toHref { -(void)moveFrom:(NSString*)fromHref toPath:(NSString*)toHref overwrite:(BOOL)overwrite { ACWebDAVLocation* location = [ACWebDAVLocation locationWithHost:self.host href:fromHref username:self.username password:self.password]; ACWebDAVLocation* destination = [ACWebDAVLocation locationWithHost:self.host href:toHref username:self.username password:self.password]; - ACWebDAVMoveRequest* request = [ACWebDAVMoveRequest requestToMoveItem:[ACWebDAVItem itemWithLocation:location] toLocation:destination delegate:self]; + ACWebDAVMoveRequest* request = [ACWebDAVMoveRequest requestToMoveItem:[ACWebDAVItem itemWithLocation:location] toLocation:destination overWrite:NO delegate:self]; [request start]; } @@ -142,23 +151,56 @@ -(void)unlockPath:(NSString *)href token:(NSString*)token { [request start]; } + + + + + + #pragma mark - #pragma mark Delegate Handlers --(void)request:(ACWebDAVPropertyRequest*)request didReturnItems:(NSArray*)items { - if([self.delegate respondsToSelector:@selector(client:loadedMetadata:)]) { + +#pragma mark - List Request Methods +-(void)request:(ACWebDAVPropertyRequest*)request didReturnItems:(NSArray*)items +{ + NSLog(@"============= didReturnItems ==============="); + if([self.delegate respondsToSelector:@selector(client:loadedMetadata:)]) + { if(items == nil || items.count < 1) { [self.delegate client:self loadedMetadata:nil]; - } else { - [self.delegate client:self loadedMetadata:[items objectAtIndex:0]]; + } + else + { + [self.delegate client:self loadedMetadata:items]; } } } --(void)request:(ACWebDAVDownloadRequest*)request didUpdateDownloadProgress:(float)percent { - if([self.delegate respondsToSelector:@selector(client:downloadProgress:forFile:)]) { - [self.delegate client:self downloadProgress:percent forFile:[request.userInfo objectForKey:@"destinationPath"]]; - } +-(void)request:(ACWebDAVDownloadRequest*)request didUpdateDownloadProgress:(float)percent +{ + if([self.delegate respondsToSelector:@selector(needToCancelDownload)]) + { + BOOL cancel = [self.delegate needToCancelDownload]; + if (cancel==NO) + { + if([self.delegate respondsToSelector:@selector(client:downloadProgress:forFile:)]) + { + [self.delegate client:self downloadProgress:percent + forFile:[request.userInfo objectForKey:@"destinationPath"]]; + } + } + else + { + [request cancel]; + if ([self.delegate respondsToSelector:@selector(resetCancelDownload:)]) + { + [self.delegate resetCancelDownload:NO]; + } + } + } + + } -(void)request:(ACWebDAVDownloadRequest*)request didCompleteDownload:(NSData*)data { @@ -168,7 +210,14 @@ -(void)request:(ACWebDAVDownloadRequest*)request didCompleteDownload:(NSData*)da [self.delegate client:self downloadedFileData:data]; } } else { - [data writeToFile:path atomically:YES]; + if ([data writeToFile:path atomically:YES]) + { + NSLog(@"write to file:%@ Success",path); + } + else + { + NSLog(@"write to file:%@ Failed",path); + } if([self.delegate respondsToSelector:@selector(client:downloadedFile:)]) { [self.delegate client:self downloadedFile:path]; } diff --git a/src/ACWebDAV/Classes/ACWebDAVFile.m b/src/ACWebDAV/Classes/ACWebDAVFile.m index 4bc673b..005de5a 100644 --- a/src/ACWebDAV/Classes/ACWebDAVFile.m +++ b/src/ACWebDAV/Classes/ACWebDAVFile.m @@ -25,6 +25,23 @@ -(id)initWithDictionary:(NSDictionary *)d { return self; } +-(NSString *)description +{ + NSString *typeStr = (self.type==ACWebDAVItemTypeCollection)?@"Collection":@"File"; + return [NSString stringWithFormat:@"\n=====item=====\n{\ttype:%@\n\tdisplayName:%@\n\thref:%@\n\tabsoluteHref:%@\n\tparentHref:%@\n\tabsoluteParentHref:%@\n\tcreationDate:%@\n\tlastModifiedDate:%@\n\turl:%@\n\tcontentType:%@\n\tcontentLength:%lld\n}", + typeStr, + self.displayName, + self.href, + self.absoluteHref, + self.parentHref, + self.absoluteParentHref, + self.creationDate, + self.lastModifiedDate, + self.url, + self.contentType, + self.contentLength]; +} + -(void)dealloc { [contentType release]; [super dealloc]; diff --git a/src/ACWebDAV/Classes/ACWebDAVItem.m b/src/ACWebDAV/Classes/ACWebDAVItem.m index d04ea47..8211891 100644 --- a/src/ACWebDAV/Classes/ACWebDAVItem.m +++ b/src/ACWebDAV/Classes/ACWebDAVItem.m @@ -8,14 +8,20 @@ #import "ACWebDAVItem.h" #import "ACWebDAV.h" +#import "ISO8601DateFormatter.h" +#import "NSDateRFC1123.h" + + + @implementation ACWebDAVItem @synthesize type, href, displayName, creationDate, lastModifiedDate, location, delegate, lock; --(id)initWithDictionary:(NSDictionary*)d { - if((self = [super init])) { - +-(id)initWithDictionary:(NSDictionary*)d +{ + if((self = [super init])) + { // Set the type if([[d objectForKey:@"resourcetype"] isEqualToString:@"collection"]) { type = ACWebDAVItemTypeCollection; @@ -26,25 +32,39 @@ -(id)initWithDictionary:(NSDictionary*)d { // Set the href href = [[d objectForKey:@"href"] retain]; - static NSDateFormatter* dateFormatter; - if(dateFormatter == nil) { - dateFormatter = [[NSDateFormatter alloc] init]; - [dateFormatter setDateFormat:@"EEE, dd MMM yyyy HH:mm:ss Z"]; - } - + // Set the display name + displayName = [[d objectForKey:@"displayname"] retain]; + + + + //=============================== + // Date Setting + //=============================== // Set the creation date - if([d objectForKey:@"creationdate"] != nil) { - creationDate = [[dateFormatter dateFromString:[d objectForKey:@"creationdate"]] retain]; + NSString *createDateStr = [d objectForKey:@"creationdate"]; + NSString *modifyDateStr = [d objectForKey:@"getlastmodified"]; + + if(createDateStr != nil) + { + ISO8601DateFormatter *formatter = [[ISO8601DateFormatter alloc] init]; + creationDate = [formatter dateFromString:createDateStr]; + [formatter release]; + + //change the GMT Date to localDate + NSTimeZone *zone = [NSTimeZone systemTimeZone]; + NSInteger timeInterval = [zone secondsFromGMTForDate:creationDate]; + creationDate = [[creationDate dateByAddingTimeInterval: timeInterval] retain]; } - // Set the last modified date - if([d objectForKey:@"getlastmodified"] != nil) { - lastModifiedDate = [[dateFormatter dateFromString:[d objectForKey:@"getlastmodified"]] retain]; + if(modifyDateStr != nil) + { + lastModifiedDate = [NSDate dateFromRFC1123:modifyDateStr]; + + //change the GMT Date to localDate + NSTimeZone *zone = [NSTimeZone systemTimeZone]; + NSInteger timeInterval = [zone secondsFromGMTForDate:lastModifiedDate]; + lastModifiedDate = [[lastModifiedDate dateByAddingTimeInterval: timeInterval] retain]; } - - // Set the display name - displayName = [[d objectForKey:@"displayname"] retain]; - } return self; } @@ -126,6 +146,20 @@ -(void)request:(ACWebDAVPropertyRequest *)request didReceiveProperties:(NSArray* [self.delegate ACWebDAVItem:self didReceiveProperties:[properties objectAtIndex:0]]; } } +-(NSString *)description +{ + NSString *typeStr = (self.type==ACWebDAVItemTypeCollection)?@"Collection":@"File"; + return [NSString stringWithFormat:@"=====item=====\n{\ttype:%@\n\tdisplayName:%@\n\thref:%@\n\tabsoluteHref:%@\n\tparentHref:%@\n\tabsoluteParentHref:%@\n\tcreationDate:%@\n\tlastModifiedDate:%@\n\turl:%@\n}", + typeStr, + self.displayName, + self.href, + self.absoluteHref, + self.parentHref, + self.absoluteParentHref, + self.creationDate, + self.lastModifiedDate, + self.url]; +} -(void)dealloc { [href release]; diff --git a/src/ACWebDAV/ISO8601/ISO8601DateFormatter.h b/src/ACWebDAV/ISO8601/ISO8601DateFormatter.h new file mode 100755 index 0000000..af4b57c --- /dev/null +++ b/src/ACWebDAV/ISO8601/ISO8601DateFormatter.h @@ -0,0 +1,79 @@ +/*ISO8601DateFormatter.h + * + *Created by Peter Hosey on 2009-04-11. + *Copyright 2009 Peter Hosey. All rights reserved. + */ + +#import + +/*This class converts dates to and from ISO 8601 strings. A good introduction to ISO 8601: + * + *Parsing can be done strictly, or not. When you parse loosely, leading whitespace is ignored, as is anything after the date. + *The loose parser will return an NSDate for this string: @" \t\r\n\f\t 2006-03-02!!!" + *Leading non-whitespace will not be ignored; the string will be rejected, and nil returned. See the README that came with this addition. + * + *The strict parser will only accept a string if the date is the entire string. The above string would be rejected immediately, solely on these grounds. + *Also, the loose parser provides some extensions that the strict parser doesn't. + *For example, the standard says for "-DDD" (an ordinal date in the implied year) that the logical representation (meaning, hierarchically) would be "--DDD", but because that extra hyphen is "superfluous", it was omitted. + *The loose parser will accept the extra hyphen; the strict parser will not. + *A full list of these extensions is in the README file. + */ + +/*The format to either expect or produce. + *Calendar format is YYYY-MM-DD. + *Ordinal format is YYYY-DDD, where DDD ranges from 1 to 366; for example, 2009-32 is 2009-02-01. + *Week format is YYYY-Www-D, where ww ranges from 1 to 53 (the 'W' is literal) and D ranges from 1 to 7; for example, 2009-W05-07. + */ +enum { + ISO8601DateFormatCalendar, + ISO8601DateFormatOrdinal, + ISO8601DateFormatWeek, +}; +typedef NSUInteger ISO8601DateFormat; + +//The default separator for time values. Currently, this is ':'. +extern unichar ISO8601DefaultTimeSeparatorCharacter; + +@interface ISO8601DateFormatter: NSFormatter +{ + NSString *lastUsedFormatString; + NSDateFormatter *unparsingFormatter; + + NSCalendar *parsingCalendar, *unparsingCalendar; + + NSTimeZone *defaultTimeZone; + ISO8601DateFormat format; + unichar timeSeparator; + BOOL includeTime; + BOOL parsesStrictly; +} + +//Call this if you get a memory warning. ++ (void) purgeGlobalCaches; + +@property(nonatomic, retain) NSTimeZone *defaultTimeZone; + +#pragma mark Parsing + +//As a formatter, this object converts strings to dates. + +@property BOOL parsesStrictly; + +- (NSDateComponents *) dateComponentsFromString:(NSString *)string; +- (NSDateComponents *) dateComponentsFromString:(NSString *)string timeZone:(out NSTimeZone **)outTimeZone; +- (NSDateComponents *) dateComponentsFromString:(NSString *)string timeZone:(out NSTimeZone **)outTimeZone range:(out NSRange *)outRange; + +- (NSDate *) dateFromString:(NSString *)string; +- (NSDate *) dateFromString:(NSString *)string timeZone:(out NSTimeZone **)outTimeZone; +- (NSDate *) dateFromString:(NSString *)string timeZone:(out NSTimeZone **)outTimeZone range:(out NSRange *)outRange; + +#pragma mark Unparsing + +@property ISO8601DateFormat format; +@property BOOL includeTime; +@property unichar timeSeparator; + +- (NSString *) stringFromDate:(NSDate *)date; +- (NSString *) stringFromDate:(NSDate *)date timeZone:(NSTimeZone *)timeZone; + +@end diff --git a/src/ACWebDAV/ISO8601/ISO8601DateFormatter.m b/src/ACWebDAV/ISO8601/ISO8601DateFormatter.m new file mode 100755 index 0000000..35a6b14 --- /dev/null +++ b/src/ACWebDAV/ISO8601/ISO8601DateFormatter.m @@ -0,0 +1,880 @@ +/*ISO8601DateFormatter.m + * + *Created by Peter Hosey on 2009-04-11. + *Copyright 2009 Peter Hosey. All rights reserved. + */ + +#import +#import "ISO8601DateFormatter.h" + +#ifndef DEFAULT_TIME_SEPARATOR +# define DEFAULT_TIME_SEPARATOR ':' +#endif +unichar ISO8601DefaultTimeSeparatorCharacter = DEFAULT_TIME_SEPARATOR; + +//Unicode date formats. +#define ISO_CALENDAR_DATE_FORMAT @"yyyy-MM-dd" +//#define ISO_WEEK_DATE_FORMAT @"YYYY-'W'ww-ee" //Doesn't actually work because NSDateComponents counts the weekday starting at 1. +#define ISO_ORDINAL_DATE_FORMAT @"yyyy-DDD" +#define ISO_TIME_FORMAT @"HH:mm:ss" +#define ISO_TIME_WITH_TIMEZONE_FORMAT ISO_TIME_FORMAT @"Z" +//printf formats. +#define ISO_TIMEZONE_UTC_FORMAT @"Z" +#define ISO_TIMEZONE_OFFSET_FORMAT @"%+.2d%.2d" + +@interface ISO8601DateFormatter(UnparsingPrivate) + +- (NSString *) replaceColonsInString:(NSString *)timeFormat withTimeSeparator:(unichar)timeSep; + +- (NSString *) stringFromDate:(NSDate *)date formatString:(NSString *)dateFormat timeZone:(NSTimeZone *)timeZone; +- (NSString *) weekDateStringForDate:(NSDate *)date timeZone:(NSTimeZone *)timeZone; + +@end + +static NSMutableDictionary *timeZonesByOffset; + +@implementation ISO8601DateFormatter + ++ (void) initialize { + if (!timeZonesByOffset) { + timeZonesByOffset = [[NSMutableDictionary alloc] init]; + } +} + ++ (void) purgeGlobalCaches { + timeZonesByOffset = nil; +} + +- (NSCalendar *) makeCalendarWithDesiredConfiguration { + NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; + calendar.firstWeekday = 2; //Monday + calendar.timeZone = [NSTimeZone defaultTimeZone]; + return calendar; +} + +- (id) init { + if ((self = [super init])) { + parsingCalendar = [self makeCalendarWithDesiredConfiguration]; + unparsingCalendar = [self makeCalendarWithDesiredConfiguration]; + + format = ISO8601DateFormatCalendar; + timeSeparator = ISO8601DefaultTimeSeparatorCharacter; + includeTime = NO; + parsesStrictly = NO; + } + return self; +} + +@synthesize defaultTimeZone; + +- (void) setDefaultTimeZone:(NSTimeZone *)tz +{ + if (defaultTimeZone != tz) + { + defaultTimeZone = tz; + + unparsingCalendar.timeZone = defaultTimeZone; + } +} + +//The following properties are only here because GCC doesn't like @synthesize in category implementations. + +#pragma mark Parsing + +@synthesize parsesStrictly; + +static NSUInteger read_segment(const unsigned char *str, const unsigned char **next, NSUInteger *out_num_digits); +static NSUInteger read_segment_4digits(const unsigned char *str, const unsigned char **next, NSUInteger *out_num_digits); +static NSUInteger read_segment_2digits(const unsigned char *str, const unsigned char **next); +static double read_double(const unsigned char *str, const unsigned char **next); +static BOOL is_leap_year(NSUInteger year); + +/*Valid ISO 8601 date formats: + * + *YYYYMMDD + *YYYY-MM-DD + *YYYY-MM + *YYYY + *YY //century + * //Implied century: YY is 00-99 + * YYMMDD + * YY-MM-DD + * -YYMM + * -YY-MM + * -YY + * //Implied year + * --MMDD + * --MM-DD + * --MM + * //Implied year and month + * ---DD + * //Ordinal dates: DDD is the number of the day in the year (1-366) + *YYYYDDD + *YYYY-DDD + * YYDDD + * YY-DDD + * -DDD + * //Week-based dates: ww is the number of the week, and d is the number (1-7) of the day in the week + *yyyyWwwd + *yyyy-Www-d + *yyyyWww + *yyyy-Www + *yyWwwd + *yy-Www-d + *yyWww + *yy-Www + * //Year of the implied decade + *-yWwwd + *-y-Www-d + *-yWww + *-y-Www + * //Week and day of implied year + * -Wwwd + * -Www-d + * //Week only of implied year + * -Www + * //Day only of implied week + * -W-d + */ + +- (NSDateComponents *) dateComponentsFromString:(NSString *)string { + return [self dateComponentsFromString:string timeZone:NULL]; +} +- (NSDateComponents *) dateComponentsFromString:(NSString *)string timeZone:(out NSTimeZone **)outTimeZone { + return [self dateComponentsFromString:string timeZone:outTimeZone range:NULL]; +} +- (NSDateComponents *) dateComponentsFromString:(NSString *)string timeZone:(out NSTimeZone **)outTimeZone range:(out NSRange *)outRange { + NSDate *now = [NSDate date]; + + NSDateComponents *components = [[NSDateComponents alloc] init]; + NSDateComponents *nowComponents = [parsingCalendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:now]; + + NSUInteger + //Date + year, + month_or_week = 0U, + day = 0U, + //Time + hour = 0U; + NSTimeInterval + minute = 0.0, + second = 0.0; + //Time zone + NSInteger tz_hour = 0; + NSInteger tz_minute = 0; + + enum { + monthAndDate, + week, + dateOnly + } dateSpecification = monthAndDate; + + BOOL strict = self.parsesStrictly; + unichar timeSep = self.timeSeparator; + + if (strict) timeSep = ISO8601DefaultTimeSeparatorCharacter; + NSAssert(timeSep != '\0', @"Time separator must not be NUL."); + + BOOL isValidDate = ([string length] > 0U); + NSTimeZone *timeZone = nil; + + const unsigned char *ch = (const unsigned char *)[string UTF8String]; + + NSRange range = { 0U, 0U }; + const unsigned char *start_of_date = NULL; + if (strict && isspace(*ch)) { + range.location = NSNotFound; + isValidDate = NO; + } else { + //Skip leading whitespace. + NSUInteger i = 0U; + for(NSUInteger len = strlen((const char *)ch); i < len; ++i) { + if (!isspace(ch[i])) + break; + } + + range.location = i; + ch += i; + start_of_date = ch; + + NSUInteger segment; + NSUInteger num_leading_hyphens = 0U, num_digits = 0U; + + if (*ch == 'T') { + //There is no date here, only a time. Set the date to now; then we'll parse the time. + isValidDate = isdigit(*++ch); + + year = nowComponents.year; + month_or_week = nowComponents.month; + day = nowComponents.day; + } else { + while(*ch == '-') { + ++num_leading_hyphens; + ++ch; + } + + segment = read_segment(ch, &ch, &num_digits); + switch(num_digits) { + case 0: + if (*ch == 'W') { + if ((ch[1] == '-') && isdigit(ch[2]) && ((num_leading_hyphens == 1U) || ((num_leading_hyphens == 2U) && !strict))) { + year = nowComponents.year; + month_or_week = 1U; + ch += 2; + goto parseDayAfterWeek; + } else if (num_leading_hyphens == 1U) { + year = nowComponents.year; + goto parseWeekAndDay; + } else + isValidDate = NO; + } else + isValidDate = NO; + break; + + case 8: //YYYY MM DD + if (num_leading_hyphens > 0U) + isValidDate = NO; + else { + day = segment % 100U; + segment /= 100U; + month_or_week = segment % 100U; + year = segment / 100U; + } + break; + + case 6: //YYMMDD (implicit century) + if (num_leading_hyphens > 0U) + isValidDate = NO; + else { + day = segment % 100U; + segment /= 100U; + month_or_week = segment % 100U; + year = nowComponents.year; + year -= (year % 100U); + year += segment / 100U; + } + break; + + case 4: + switch(num_leading_hyphens) { + case 0: //YYYY + year = segment; + + if (*ch == '-') ++ch; + + if (!isdigit(*ch)) { + if (*ch == 'W') + goto parseWeekAndDay; + else + month_or_week = day = 1U; + } else { + segment = read_segment(ch, &ch, &num_digits); + switch(num_digits) { + case 4: //MMDD + day = segment % 100U; + month_or_week = segment / 100U; + break; + + case 2: //MM + month_or_week = segment; + + if (*ch == '-') ++ch; + if (!isdigit(*ch)) + day = 1U; + else + day = read_segment(ch, &ch, NULL); + break; + + case 3: //DDD + day = segment % 1000U; + dateSpecification = dateOnly; + if (strict && (day > (365U + is_leap_year(year)))) + isValidDate = NO; + break; + + default: + isValidDate = NO; + } + } + break; + + case 1: //YYMM + month_or_week = segment % 100U; + year = segment / 100U; + + if (*ch == '-') ++ch; + if (!isdigit(*ch)) + day = 1U; + else + day = read_segment(ch, &ch, NULL); + + break; + + case 2: //MMDD + day = segment % 100U; + month_or_week = segment / 100U; + year = nowComponents.year; + + break; + + default: + isValidDate = NO; + } //switch(num_leading_hyphens) (4 digits) + break; + + case 1: + if (strict) { + //Two digits only - never just one. + if (num_leading_hyphens == 1U) { + if (*ch == '-') ++ch; + if (*++ch == 'W') { + year = nowComponents.year; + year -= (year % 10U); + year += segment; + goto parseWeekAndDay; + } else + isValidDate = NO; + } else + isValidDate = NO; + break; + } + case 2: + switch(num_leading_hyphens) { + case 0: + if (*ch == '-') { + //Implicit century + year = nowComponents.year; + year -= (year % 100U); + year += segment; + + if (*++ch == 'W') + goto parseWeekAndDay; + else if (!isdigit(*ch)) { + goto centuryOnly; + } else { + //Get month and/or date. + segment = read_segment_4digits(ch, &ch, &num_digits); + NSLog(@"(%@) parsing month; segment is %lu and ch is %s", string, (unsigned long)segment, ch); + switch(num_digits) { + case 4: //YY-MMDD + day = segment % 100U; + month_or_week = segment / 100U; + break; + + case 1: //YY-M; YY-M-DD (extension) + if (strict) { + isValidDate = NO; + break; + } + case 2: //YY-MM; YY-MM-DD + month_or_week = segment; + if (*ch == '-') { + if (isdigit(*++ch)) + day = read_segment_2digits(ch, &ch); + else + day = 1U; + } else + day = 1U; + break; + + case 3: //Ordinal date. + day = segment; + dateSpecification = dateOnly; + break; + } + } + } else if (*ch == 'W') { + year = nowComponents.year; + year -= (year % 100U); + year += segment; + + parseWeekAndDay: //*ch should be 'W' here. + if (!isdigit(*++ch)) { + //Not really a week-based date; just a year followed by '-W'. + if (strict) + isValidDate = NO; + else + month_or_week = day = 1U; + } else { + month_or_week = read_segment_2digits(ch, &ch); + if (*ch == '-') ++ch; + parseDayAfterWeek: + day = isdigit(*ch) ? read_segment_2digits(ch, &ch) : 1U; + dateSpecification = week; + } + } else { + //Century only. Assume current year. + centuryOnly: + year = segment * 100U + nowComponents.year % 100U; + month_or_week = day = 1U; + } + break; + + case 1:; //-YY; -YY-MM (implicit century) + NSLog(@"(%@) found %lu digits and one hyphen, so this is either -YY or -YY-MM; segment (year) is %lu", string, (unsigned long)num_digits, (unsigned long)segment); + NSUInteger current_year = nowComponents.year; + NSUInteger current_century = (current_year % 100U); + year = segment + (current_year - current_century); + if (num_digits == 1U) //implied decade + year += current_century - (current_year % 10U); + + if (*ch == '-') { + ++ch; + month_or_week = read_segment_2digits(ch, &ch); + NSLog(@"(%@) month is %lu", string, (unsigned long)month_or_week); + } + + day = 1U; + break; + + case 2: //--MM; --MM-DD + year = nowComponents.year; + month_or_week = segment; + if (*ch == '-') { + ++ch; + day = read_segment_2digits(ch, &ch); + } + break; + + case 3: //---DD + year = nowComponents.year; + month_or_week = nowComponents.month; + day = segment; + break; + + default: + isValidDate = NO; + } //switch(num_leading_hyphens) (2 digits) + break; + + case 7: //YYYY DDD (ordinal date) + if (num_leading_hyphens > 0U) + isValidDate = NO; + else { + day = segment % 1000U; + year = segment / 1000U; + dateSpecification = dateOnly; + if (strict && (day > (365U + is_leap_year(year)))) + isValidDate = NO; + } + break; + + case 3: //--DDD (ordinal date, implicit year) + //Technically, the standard only allows one hyphen. But it says that two hyphens is the logical implementation, and one was dropped for brevity. So I have chosen to allow the missing hyphen. + if ((num_leading_hyphens < 1U) || ((num_leading_hyphens > 2U) && !strict)) + isValidDate = NO; + else { + day = segment; + year = nowComponents.year; + dateSpecification = dateOnly; + if (strict && (day > (365U + is_leap_year(year)))) + isValidDate = NO; + } + break; + + default: + isValidDate = NO; + } + } + + if (isValidDate) { + if (isspace(*ch) || (*ch == 'T')) ++ch; + + if (isdigit(*ch)) { + hour = read_segment_2digits(ch, &ch); + if (*ch == timeSep) { + ++ch; + if ((timeSep == ',') || (timeSep == '.')) { + //We can't do fractional minutes when '.' is the segment separator. + //Only allow whole minutes and whole seconds. + minute = read_segment_2digits(ch, &ch); + if (*ch == timeSep) { + ++ch; + second = read_segment_2digits(ch, &ch); + } + } else { + //Allow a fractional minute. + //If we don't get a fraction, look for a seconds segment. + //Otherwise, the fraction of a minute is the seconds. + minute = read_double(ch, &ch); + second = modf(minute, &minute); + if (second > DBL_EPSILON) + second *= 60.0; //Convert fraction (e.g. .5) into seconds (e.g. 30). + else if (*ch == timeSep) { + ++ch; + second = read_double(ch, &ch); + } + } + } + + if (!strict) { + if (isspace(*ch)) ++ch; + } + + switch(*ch) { + case 'Z': + timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"]; + break; + + case '+': + case '-':; + BOOL negative = (*ch == '-'); + if (isdigit(*++ch)) { + //Read hour offset. + segment = *ch - '0'; + if (isdigit(*++ch)) { + segment *= 10U; + segment += *(ch++) - '0'; + } + tz_hour = (NSInteger)segment; + if (negative) tz_hour = -tz_hour; + + //Optional separator. + if (*ch == timeSep) ++ch; + + if (isdigit(*ch)) { + //Read minute offset. + segment = *ch - '0'; + if (isdigit(*++ch)) { + segment *= 10U; + segment += *ch - '0'; + } + tz_minute = segment; + if (negative) tz_minute = -tz_minute; + } + + NSTimeInterval timeZoneOffset = (tz_hour * 3600) + (tz_minute * 60); + NSNumber *offsetNum = [NSNumber numberWithDouble:timeZoneOffset]; + timeZone = [timeZonesByOffset objectForKey:offsetNum]; + if (!timeZone) { + timeZone = [NSTimeZone timeZoneForSecondsFromGMT:timeZoneOffset]; + if (timeZone) + [timeZonesByOffset setObject:timeZone forKey:offsetNum]; + } + } + } + } + } + + if (isValidDate) { + components.year = year; + components.day = day; + components.hour = hour; + components.minute = (NSInteger)minute; + components.second = (NSInteger)second; + + switch(dateSpecification) { + case monthAndDate: + components.month = month_or_week; + break; + + case week:; + //Adapted from . + //This works by converting the week date into an ordinal date, then letting the next case handle it. + NSUInteger prevYear = year - 1U; + NSUInteger YY = prevYear % 100U; + NSUInteger C = prevYear - YY; + NSUInteger G = YY + YY / 4U; + NSUInteger isLeapYear = (((C / 100U) % 4U) * 5U); + NSUInteger Jan1Weekday = (isLeapYear + G) % 7U; + enum { monday, tuesday, wednesday, thursday/*, friday, saturday, sunday*/ }; + components.day = ((8U - Jan1Weekday) + (7U * (Jan1Weekday > thursday))) + (day - 1U) + (7U * (month_or_week - 2)); + + case dateOnly: //An "ordinal date". + break; + } + } + } //if (!(strict && isdigit(ch[0]))) + + if (outRange) { + if (isValidDate) + range.length = ch - start_of_date; + else + range.location = NSNotFound; + + *outRange = range; + } + if (outTimeZone) { + *outTimeZone = timeZone; + } + + return components; +} + +- (NSDate *) dateFromString:(NSString *)string { + return [self dateFromString:string timeZone:NULL]; +} +- (NSDate *) dateFromString:(NSString *)string timeZone:(out NSTimeZone **)outTimeZone { + return [self dateFromString:string timeZone:outTimeZone range:NULL]; +} +- (NSDate *) dateFromString:(NSString *)string timeZone:(out NSTimeZone **)outTimeZone range:(out NSRange *)outRange { + NSTimeZone *timeZone = nil; + NSDateComponents *components = [self dateComponentsFromString:string timeZone:&timeZone range:outRange]; + if (outTimeZone) + *outTimeZone = timeZone; + parsingCalendar.timeZone = timeZone; + + return [parsingCalendar dateFromComponents:components]; +} + +- (BOOL)getObjectValue:(id *)outValue forString:(NSString *)string errorDescription:(NSString **)error { + NSDate *date = [self dateFromString:string]; + if (outValue) + *outValue = date; + return (date != nil); +} + +#pragma mark Unparsing + +@synthesize format; +@synthesize includeTime; +@synthesize timeSeparator; + +- (NSString *) replaceColonsInString:(NSString *)timeFormat withTimeSeparator:(unichar)timeSep { + if (timeSep != ':') { + NSMutableString *timeFormatMutable = [timeFormat mutableCopy]; + [timeFormatMutable replaceOccurrencesOfString:@":" + withString:[NSString stringWithCharacters:&timeSep length:1U] + options:NSBackwardsSearch | NSLiteralSearch + range:(NSRange){ 0UL, [timeFormat length] }]; + timeFormat = timeFormatMutable; + } + return timeFormat; +} + +- (NSString *) stringFromDate:(NSDate *)date { + NSTimeZone *timeZone = self.defaultTimeZone; + if (!timeZone) timeZone = [NSTimeZone defaultTimeZone]; + return [self stringFromDate:date timeZone:timeZone]; +} + +- (NSString *) stringFromDate:(NSDate *)date timeZone:(NSTimeZone *)timeZone { + switch (self.format) { + case ISO8601DateFormatCalendar: + return [self stringFromDate:date formatString:ISO_CALENDAR_DATE_FORMAT timeZone:timeZone]; + case ISO8601DateFormatWeek: + return [self weekDateStringForDate:date timeZone:timeZone]; + case ISO8601DateFormatOrdinal: + return [self stringFromDate:date formatString:ISO_ORDINAL_DATE_FORMAT timeZone:timeZone]; + default: + [NSException raise:NSInternalInconsistencyException format:@"self.format was %d, not calendar (%d), week (%d), or ordinal (%d)", self.format, ISO8601DateFormatCalendar, ISO8601DateFormatWeek, ISO8601DateFormatOrdinal]; + return nil; + } +} + +- (NSString *) stringFromDate:(NSDate *)date formatString:(NSString *)dateFormat timeZone:(NSTimeZone *)timeZone { + if (includeTime) + dateFormat = [dateFormat stringByAppendingFormat:@"'T' %@", [self replaceColonsInString:ISO_TIME_FORMAT withTimeSeparator:self.timeSeparator]]; + + unparsingCalendar.timeZone = timeZone; + + if (dateFormat != lastUsedFormatString) { + unparsingFormatter = nil; + lastUsedFormatString = dateFormat; + } + + if (!unparsingFormatter) { + unparsingFormatter = [[NSDateFormatter alloc] init]; + unparsingFormatter.formatterBehavior = NSDateFormatterBehavior10_4; + unparsingFormatter.dateFormat = dateFormat; + unparsingFormatter.calendar = unparsingCalendar; + } + + NSString *str = [unparsingFormatter stringForObjectValue:date]; + + if (includeTime) { + NSInteger offset = [timeZone secondsFromGMT]; + offset /= 60; //bring down to minutes + if (offset == 0) + str = [str stringByAppendingString:ISO_TIMEZONE_UTC_FORMAT]; + else + str = [str stringByAppendingFormat:ISO_TIMEZONE_OFFSET_FORMAT, offset / 60, offset % 60]; + } + + //Undo the change we made earlier + unparsingCalendar.timeZone = self.defaultTimeZone; + + return str; +} + +- (NSString *) stringForObjectValue:(id)value { + NSParameterAssert([value isKindOfClass:[NSDate class]]); + + return [self stringFromDate:(NSDate *)value]; +} + +/*Adapted from: + * Algorithm for Converting Gregorian Dates to ISO 8601 Week Date + * Rick McCarty, 1999 + * http://personal.ecu.edu/mccartyr/ISOwdALG.txt + */ +- (NSString *) weekDateStringForDate:(NSDate *)date timeZone:(NSTimeZone *)timeZone { + unparsingCalendar.timeZone = timeZone; + NSDateComponents *components = [unparsingCalendar components:NSYearCalendarUnit | NSWeekdayCalendarUnit | NSDayCalendarUnit fromDate:date]; + + //Determine the ordinal date. + NSDateComponents *startOfYearComponents = [unparsingCalendar components:NSYearCalendarUnit fromDate:date]; + startOfYearComponents.month = 1; + startOfYearComponents.day = 1; + NSDateComponents *ordinalComponents = [unparsingCalendar components:NSDayCalendarUnit fromDate:[unparsingCalendar dateFromComponents:startOfYearComponents] toDate:date options:0]; + ordinalComponents.day += 1; + + enum { + monday, tuesday, wednesday, thursday, friday, saturday, sunday + }; + enum { + january = 1, february, march, + april, may, june, + july, august, september, + october, november, december + }; + + NSInteger year = components.year; + NSInteger week = 0; + //The old unparser added 6 to [calendarDate dayOfWeek], which was zero-based; components.weekday is one-based, so we now add only 5. + NSInteger dayOfWeek = (components.weekday + 5) % 7; + NSInteger dayOfYear = ordinalComponents.day; + + NSInteger prevYear = year - 1; + + BOOL yearIsLeapYear = is_leap_year(year); + BOOL prevYearIsLeapYear = is_leap_year(prevYear); + + NSInteger YY = prevYear % 100; + NSInteger C = prevYear - YY; + NSInteger G = YY + YY / 4; + NSInteger Jan1Weekday = (((((C / 100) % 4) * 5) + G) % 7); + + NSInteger weekday = ((dayOfYear + Jan1Weekday) - 1) % 7; + + if((dayOfYear <= (7 - Jan1Weekday)) && (Jan1Weekday > thursday)) { + week = 52 + ((Jan1Weekday == friday) || ((Jan1Weekday == saturday) && prevYearIsLeapYear)); + --year; + } else { + NSInteger lengthOfYear = 365 + yearIsLeapYear; + if((lengthOfYear - dayOfYear) < (thursday - weekday)) { + ++year; + week = 1; + } else { + NSInteger J = dayOfYear + (sunday - weekday) + Jan1Weekday; + week = J / 7 - (Jan1Weekday > thursday); + } + } + + NSString *timeString; + if(includeTime) { + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + unichar timeSep = self.timeSeparator; + if (!timeSep) timeSep = ISO8601DefaultTimeSeparatorCharacter; + formatter.dateFormat = [self replaceColonsInString:ISO_TIME_WITH_TIMEZONE_FORMAT withTimeSeparator:timeSep]; + + timeString = [formatter stringForObjectValue:date]; + } else + timeString = @""; + + return [NSString stringWithFormat:@"%lu-W%02lu-%02lu%@", (unsigned long)year, (unsigned long)week, ((unsigned long)dayOfWeek) + 1U, timeString]; +} + +@end + +static NSUInteger read_segment(const unsigned char *str, const unsigned char **next, NSUInteger *out_num_digits) { + NSUInteger num_digits = 0U; + NSUInteger value = 0U; + + while(isdigit(*str)) { + value *= 10U; + value += *str - '0'; + ++num_digits; + ++str; + } + + if (next) *next = str; + if (out_num_digits) *out_num_digits = num_digits; + + return value; +} +static NSUInteger read_segment_4digits(const unsigned char *str, const unsigned char **next, NSUInteger *out_num_digits) { + NSUInteger num_digits = 0U; + NSUInteger value = 0U; + + if (isdigit(*str)) { + value += *(str++) - '0'; + ++num_digits; + } + + if (isdigit(*str)) { + value *= 10U; + value += *(str++) - '0'; + ++num_digits; + } + + if (isdigit(*str)) { + value *= 10U; + value += *(str++) - '0'; + ++num_digits; + } + + if (isdigit(*str)) { + value *= 10U; + value += *(str++) - '0'; + ++num_digits; + } + + if (next) *next = str; + if (out_num_digits) *out_num_digits = num_digits; + + return value; +} +static NSUInteger read_segment_2digits(const unsigned char *str, const unsigned char **next) { + NSUInteger value = 0U; + + if (isdigit(*str)) + value += *str - '0'; + + if (isdigit(*++str)) { + value *= 10U; + value += *(str++) - '0'; + } + + if (next) *next = str; + + return value; +} + +//strtod doesn't support ',' as a separator. This does. +static double read_double(const unsigned char *str, const unsigned char **next) { + double value = 0.0; + + if (str) { + NSUInteger int_value = 0; + + while(isdigit(*str)) { + int_value *= 10U; + int_value += (*(str++) - '0'); + } + value = int_value; + + if (((*str == ',') || (*str == '.'))) { + ++str; + + register double multiplier, multiplier_multiplier; + multiplier = multiplier_multiplier = 0.1; + + while(isdigit(*str)) { + value += (*(str++) - '0') * multiplier; + multiplier *= multiplier_multiplier; + } + } + } + + if (next) *next = str; + + return value; +} + +static BOOL is_leap_year(NSUInteger year) { + return \ + ((year % 4U) == 0U) + && (((year % 100U) != 0U) + || ((year % 400U) == 0U)); +} diff --git a/src/ACWebDAV/ISO8601/LICENSE.txt b/src/ACWebDAV/ISO8601/LICENSE.txt new file mode 100755 index 0000000..65e9e22 --- /dev/null +++ b/src/ACWebDAV/ISO8601/LICENSE.txt @@ -0,0 +1,9 @@ +Copyright © 2006 Peter Hosey + All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +Neither the name of Peter Hosey nor the names of his contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/ACWebDAV/RFC1123/NSDateRFC1123.h b/src/ACWebDAV/RFC1123/NSDateRFC1123.h new file mode 100755 index 0000000..7638830 --- /dev/null +++ b/src/ACWebDAV/RFC1123/NSDateRFC1123.h @@ -0,0 +1,30 @@ +// +// NSDateRFC1123.h +// Filmfest +// +// Created by Marcus Rohrmoser on 19.08.09. +// Copyright 2009 __MyCompanyName__. All rights reserved. +// + +#import + +/** Category on NSDate to add rfc1123 dates. Donated from the Filmfest App for free use as in free beer. + http://blog.mro.name/2009/08/nsdateformatter-http-header/ and + http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1 + */ +@interface NSDate (NSDateRFC1123) + +/** + Convert a RFC1123 'Full-Date' string (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1) into NSDate. + @param value_ something like either @"Fri, 14 Aug 2009 14:45:31 GMT" or @"Sunday, 06-Nov-94 08:49:37 GMT" or @"Sun Nov 6 08:49:37 1994" + @return nil if not parseable. + */ ++(NSDate*)dateFromRFC1123:(NSString*)value_; + +/** + Convert NSDate into a RFC1123 'Full-Date' string (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1). + @return something like @"Fri, 14 Aug 2009 14:45:31 GMT" + */ +-(NSString*)rfc1123String; + +@end \ No newline at end of file diff --git a/src/ACWebDAV/RFC1123/NSDateRFC1123.m b/src/ACWebDAV/RFC1123/NSDateRFC1123.m new file mode 100755 index 0000000..d74e007 --- /dev/null +++ b/src/ACWebDAV/RFC1123/NSDateRFC1123.m @@ -0,0 +1,82 @@ +// +// NSDateRFC1123.m +// Filmfest +// +// Created by Marcus Rohrmoser on 19.08.09. +// Copyright 2009 __MyCompanyName__. All rights reserved. +// + +#import "NSDateRFC1123.h" + +@implementation NSDate (NSDateRFC1123) + ++(NSDate*)dateFromRFC1123:(NSString*)value_ +{ + if(value_ == nil) + return nil; + static NSDateFormatter *rfc1123 = nil; + if(rfc1123 == nil) + { + rfc1123 = [[NSDateFormatter alloc] init]; + rfc1123.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; + rfc1123.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"]; + rfc1123.dateFormat = @"EEE',' dd MMM yyyy HH':'mm':'ss z"; + } + NSDate *ret = [rfc1123 dateFromString:value_]; + if(ret != nil) + return ret; + + static NSDateFormatter *rfc850 = nil; + if(rfc850 == nil) + { + rfc850 = [[NSDateFormatter alloc] init]; + rfc850.locale = rfc1123.locale; + rfc850.timeZone = rfc1123.timeZone; + rfc850.dateFormat = @"EEEE',' dd'-'MMM'-'yy HH':'mm':'ss z"; + } + ret = [rfc850 dateFromString:value_]; + if(ret != nil) + return ret; + + static NSDateFormatter *asctime = nil; + if(asctime == nil) + { + asctime = [[NSDateFormatter alloc] init]; + asctime.locale = rfc1123.locale; + asctime.timeZone = rfc1123.timeZone; + asctime.dateFormat = @"EEE MMM d HH':'mm':'ss yyyy"; + } + return [asctime dateFromString:value_]; +} + + +-(NSString*)rfc1123String +{ + static NSDateFormatter *df = nil; + if(df == nil) + { + df = [[NSDateFormatter alloc] init]; + df.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; + df.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"]; + df.dateFormat = @"EEE',' dd MMM yyyy HH':'mm':'ss 'GMT'"; + } + return [df stringFromDate:self]; +} + + +#if 0 +// Fri, 14 Aug 2009 14:45:31 GMT +NSLogD(@"Last-Modified: %@", [vc.response.allHeaderFields objectForKey:@"Last-Modified"]); +// df.calendar = @"gregorian"; +NSLogD(@"Now: %@", [NSDate date]); +for(NSString* fmt in [NSArray arrayWithObjects:@"a", @"b", @"c", @"d", @"e", @"f", @"g", @"h", @"i", @"j", @"k", @"l", @"m", @"n", @"o", @"p", @"q", @"r", @"s", @"t", @"u", @"v", @"w", @"x", @"y", @"z", nil]) +{ + rfc1123.dateFormat = [NSString stringWithFormat:@"%@%@%@", fmt, fmt, fmt]; + rfc1123.dateFormat = fmt; + NSLogD(@"Now (%@): %@", rfc1123.dateFormat, [rfc1123 stringFromDate:[NSDate date]]); + rfc1123.dateFormat = [rfc1123.dateFormat uppercaseString]; + NSLogD(@"Now (%@): %@", rfc1123.dateFormat, [rfc1123 stringFromDate:[NSDate date]]); +} +#endif + +@end \ No newline at end of file diff --git a/src/ACWebDAV/Requests/ACWebDAVCopyRequest.m b/src/ACWebDAV/Requests/ACWebDAVCopyRequest.m index 3f0dd75..901d7da 100644 --- a/src/ACWebDAV/Requests/ACWebDAVCopyRequest.m +++ b/src/ACWebDAV/Requests/ACWebDAVCopyRequest.m @@ -25,12 +25,12 @@ +(ACWebDAVCopyRequest*)requestWithLocation:(ACWebDAVLocation*)_location { } +(ACWebDAVCopyRequest*)requestToCopyItem:(ACWebDAVItem*)item toURL:(NSURL*)_destination delegate:(id) _delegate { - return [self requestToCopyItem:item toLocation:[ACWebDAVLocation locationWithURL:_destination] delegate:_delegate]; + return [self requestToCopyItem:item toLocation:[ACWebDAVLocation locationWithURL:_destination] overWrite:NO delegate:_delegate]; } -+(ACWebDAVCopyRequest*)requestToCopyItem:(ACWebDAVItem*)item toLocation:(ACWebDAVLocation*)_destination delegate:(id) _delegate { ++(ACWebDAVCopyRequest*)requestToCopyItem:(ACWebDAVItem*)item toLocation:(ACWebDAVLocation*)_destination overWrite:(BOOL)overwrite delegate:(id) _delegate { ACWebDAVCopyRequest* request = [self requestWithLocation:item.location]; - request.overwrite = NO; + request.overwrite = overwrite; request.destination = _destination; request.delegate = _delegate; return request; @@ -62,14 +62,14 @@ -(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChalleng - (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSHTTPURLResponse*)response { if([response statusCode] == 201) { - if(self.delegate != nil && [(NSObject*)self.delegate respondsToSelector:@selector(ACWebDAVCopyRequest:didCopyItem:)]) { + if(self.delegate != nil && [(NSObject*)self.delegate respondsToSelector:@selector(request:didCopyItem:)]) { ACWebDAVLocation* newLocation = [ACWebDAVLocation locationWithURL:[response URL] username:self.location.username password:self.location.password]; ACWebDAVItem* item = [[ACWebDAVItem alloc] initWithLocation:newLocation]; [self.delegate request:self didCopyItem:item]; [item release]; } } else { - if(self.delegate != nil && [(NSObject*)self.delegate respondsToSelector:@selector(ACWebDAVCopyRequest:didFailWithErrorCode:)]) { + if(self.delegate != nil && [(NSObject*)self.delegate respondsToSelector:@selector(request:didFailWithErrorCode:)]) { [self.delegate request:self didFailWithErrorCode:[response statusCode]]; } } @@ -82,7 +82,8 @@ -(void)connectionDidFinishLoading:(NSURLConnection *)connection { -(void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error { [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; - if(self.delegate != nil && [(NSObject*)self.delegate respondsToSelector:@selector(ACWebDAVCopyRequest:didFailWithError:)]) { + if(self.delegate != nil && [(NSObject*)self.delegate respondsToSelector:@selector(request:didFailWithError:)]) + { [self.delegate request:self didFailWithError:error]; } [connection release]; diff --git a/src/ACWebDAV/Requests/ACWebDAVDeleteRequest.m b/src/ACWebDAV/Requests/ACWebDAVDeleteRequest.m index 903432f..390433b 100644 --- a/src/ACWebDAV/Requests/ACWebDAVDeleteRequest.m +++ b/src/ACWebDAV/Requests/ACWebDAVDeleteRequest.m @@ -54,7 +54,7 @@ -(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChalleng } - (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSHTTPURLResponse*)response { - if([response statusCode] == 201) { + if([response statusCode] == 201||[response statusCode]==204) { if(self.delegate != nil && [(NSObject*)self.delegate respondsToSelector:@selector(request:didDeleteItem:)]) { ACWebDAVLocation* newLocation = [ACWebDAVLocation locationWithURL:[response URL] username:self.location.username password:self.location.password]; ACWebDAVItem* item = [[ACWebDAVItem alloc] initWithLocation:newLocation]; diff --git a/src/ACWebDAV/Requests/ACWebDAVDownloadRequest.h b/src/ACWebDAV/Requests/ACWebDAVDownloadRequest.h index b045f7c..b46c047 100644 --- a/src/ACWebDAV/Requests/ACWebDAVDownloadRequest.h +++ b/src/ACWebDAV/Requests/ACWebDAVDownloadRequest.h @@ -36,8 +36,10 @@ @property (nonatomic, retain) id delegate; @property (nonatomic, retain) ACWebDAVLocation* location; @property (nonatomic, retain) NSDictionary* userInfo; +@property (nonatomic, retain) NSURLConnection* currentConnection;//new -(void)start; +-(void)cancel; +(ACWebDAVDownloadRequest*)requestToDownloadItem:(ACWebDAVItem*)item delegate:(id) delegate; @end diff --git a/src/ACWebDAV/Requests/ACWebDAVDownloadRequest.m b/src/ACWebDAV/Requests/ACWebDAVDownloadRequest.m index 78910a6..edb3c7c 100644 --- a/src/ACWebDAV/Requests/ACWebDAVDownloadRequest.m +++ b/src/ACWebDAV/Requests/ACWebDAVDownloadRequest.m @@ -11,7 +11,7 @@ @implementation ACWebDAVDownloadRequest -@synthesize delegate, location, userInfo; +@synthesize delegate, location, userInfo,currentConnection; -(id)initWithLocation:(ACWebDAVLocation*)_location { if(self = [self init]) { @@ -34,9 +34,23 @@ -(void)start { [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:self.location.url]; NSURLConnection* conn = [[NSURLConnection alloc] initWithRequest:request delegate:self]; + if (self.currentConnection!=nil) + { + self.currentConnection = nil; + } + self.currentConnection = conn; [conn start]; } +//new +-(void)cancel +{ + [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; + [self.currentConnection cancel]; + [self.currentConnection release]; + NSLog(@"canceled"); +} + -(NSURLRequest*)connection:(NSURLConnection*)connection willSendRequest:(NSURLRequest*)request redirectResponse:(NSURLResponse*)redirectResponse { return request; } @@ -72,7 +86,8 @@ - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLRe } } --(void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)d { +-(void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)d +{ [data appendData:d]; if(self.delegate != nil && [(NSObject*)self.delegate respondsToSelector:@selector(request:didUpdateDownloadProgress:)]) { [self.delegate request:self didUpdateDownloadProgress:(float)data.length/contentLength]; @@ -96,6 +111,7 @@ -(void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error } -(void)dealloc { + [currentConnection release];//new [userInfo release]; [location release]; [(NSObject*)delegate release]; diff --git a/src/ACWebDAV/Requests/ACWebDAVMoveRequest.m b/src/ACWebDAV/Requests/ACWebDAVMoveRequest.m index 5bddb59..bbe75dd 100644 --- a/src/ACWebDAV/Requests/ACWebDAVMoveRequest.m +++ b/src/ACWebDAV/Requests/ACWebDAVMoveRequest.m @@ -25,12 +25,12 @@ +(ACWebDAVMoveRequest*)requestWithLocation:(ACWebDAVLocation*)_location { } +(ACWebDAVMoveRequest*)requestToMoveItem:(ACWebDAVItem*)item toURL:(NSURL*)_destination delegate:(id) _delegate { - return [self requestToMoveItem:item toLocation:[ACWebDAVLocation locationWithURL:_destination] delegate:_delegate]; + return [self requestToMoveItem:item toLocation:[ACWebDAVLocation locationWithURL:_destination] overWrite:NO delegate:_delegate]; } -+(ACWebDAVMoveRequest*)requestToMoveItem:(ACWebDAVItem*)item toLocation:(ACWebDAVLocation*)_destination delegate:(id) _delegate { ++(ACWebDAVMoveRequest*)requestToMoveItem:(ACWebDAVItem*)item toLocation:(ACWebDAVLocation*)_destination overWrite:(BOOL)overwrite delegate:(id) _delegate { ACWebDAVMoveRequest* request = [self requestWithLocation:item.location]; - request.overwrite = NO; + request.overwrite = overwrite; request.destination = _destination; request.delegate = _delegate; return request; @@ -62,14 +62,14 @@ -(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChalleng - (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSHTTPURLResponse*)response { if([response statusCode] == 201) { - if(self.delegate != nil && [(NSObject*)self.delegate respondsToSelector:@selector(ACWebDAVMoveRequest:didMoveItem:)]) { + if(self.delegate != nil && [(NSObject*)self.delegate respondsToSelector:@selector(request:didMoveItem:)]) { ACWebDAVLocation* newLocation = [ACWebDAVLocation locationWithURL:[response URL] username:self.location.username password:self.location.password]; ACWebDAVItem* item = [[ACWebDAVItem alloc] initWithLocation:newLocation]; [self.delegate request:self didMoveItem:item]; [item release]; } } else { - if(self.delegate != nil && [(NSObject*)self.delegate respondsToSelector:@selector(ACWebDAVMoveRequest:didFailWithErrorCode:)]) { + if(self.delegate != nil && [(NSObject*)self.delegate respondsToSelector:@selector(request:didFailWithErrorCode:)]) { [self.delegate request:self didFailWithErrorCode:[response statusCode]]; } } @@ -82,7 +82,8 @@ -(void)connectionDidFinishLoading:(NSURLConnection *)connection { -(void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error { [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; - if(self.delegate != nil && [(NSObject*)self.delegate respondsToSelector:@selector(ACWebDAVMoveRequest:didFailWithError:)]) { + if(self.delegate != nil && [(NSObject*)self.delegate respondsToSelector:@selector(request: didFailWithError:)]) + { [self.delegate request:self didFailWithError:error]; } [connection release];