/* Copyright (C) 2004 Helge Hess This file is part of OpenGroupware.org. OGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. OGo 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with OGo; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "DAVOperation.h" #import #include #include #include #include #include #include @interface DAVOperation(Privates) - (NSString *)_authorization; - (id)xmlParser; @end @implementation DAVOperation static id parser = nil; static SaxDAVHandler *sax = nil; - (id)xmlParser { if (parser != nil) return parser; parser = [[[SaxXMLReaderFactory standardXMLReaderFactory] createXMLReader] retain]; if (parser == nil) { NSLog(@"ERROR: did not find an XML parser!"); return nil; } sax = [[SaxDAVHandler alloc] init]; [parser setContentHandler:sax]; [parser setDTDHandler:sax]; [parser setErrorHandler:sax]; return parser; } - (id)init { if ((self = [super init])) { } return self; } - (id)initWithURL:(id)_url { if ([_url isKindOfClass:[NSString class]]) _url = [NSURL URLWithString:_url]; if ((self = [self init])) { self->url = [_url copy]; } return self; } - (void)dealloc { [self->url release]; [self->content release]; [self->http release]; [super dealloc]; } /* accessors */ - (void)setDelegate:(id)_delegate { self->delegate = _delegate; self->dFlags.handlesDidReceivePropertiesForURL = \ [_delegate respondsToSelector: @selector(operation:didReceiveProperties:forURI:)]; self->dFlags.handlesProvideLoginAndPassword = \ [_delegate respondsToSelector: @selector(operation:provideLogin:andPassword:)]; self->dFlags.handlesOperationDidStart = \ [_delegate respondsToSelector:@selector(operationDidStart:)]; self->dFlags.handlesOperationDidFinish = \ [_delegate respondsToSelector:@selector(operationDidFinish:)]; } - (id)delegate { return self->delegate; } /* accessor */ - (NSURL *)url { return self->url; } /* authentication */ - (NSString *)_authorization { NSString *login, *password, *tmp; if(!self->dFlags.handlesProvideLoginAndPassword) return nil; [[self delegate] operation:self provideLogin:&login andPassword:&password]; tmp = [login stringByAppendingString:@":"]; tmp = [tmp stringByAppendingString:password]; if(tmp != nil) { tmp = [tmp stringByEncodingBase64]; tmp = [@"basic " stringByAppendingString:tmp]; } return tmp; } /* parsing results */ - (void)parseContent { NSLog(@"subclass should parse %d bytes ...", [self->content length]); } /* HTTP delegate */ #if WORKING_APPLE_JUNK - (void)connection:(NSURLConnection *)_http didReceiveResponse:(NSURLResponse *)_response { [self->contentType release]; self->contentType = nil; self->contentType = [[_response MIMEType] copy]; } - (void)connection:(NSURLConnection *)_http didReceiveData:(NSData *)_d { if ([_d length] == 0) return; if (self->content == nil) self->content = [[NSMutableData alloc] initWithCapacity:1024]; [self->content appendData:_d]; } - (NSCachedURLResponse *)connection:(NSURLConnection *)_http willCacheResponse:(NSCachedURLResponse *)_response { /* do not cache WebDAV responses */ return nil; } - (void)connectionDidFinishLoading:(NSURLConnection *)_http { if (_http == self->http) { [self->http release]; self->http = nil; } NSLog(@"done (%d bytes, %@) ...", [self->content length], self->contentType); [self parseContent]; } #else - (void)canReadRequest:(NSNotification *)_notification { WOResponse *r; NSLog(@"can read response ..."); r = [[_notification object] readResponse]; [self->contentType release]; self->contentType = nil; [self->content release]; self->content = nil; self->content = [[r content] copy]; self->contentType = [[r headerForKey:@"content-type"] copy]; [self parseContent]; } #endif /* fetching */ - (id)buildRequest { NSLog(@"%s: subclass needs to override this method!", __PRETTY_FUNCTION__); return nil; } - (BOOL)start { id request; if (self->http != nil) { NSLog(@"request is already running!"); return NO; } request = [self buildRequest]; #if WORKING_APPLE_JUNK self->http = [[NSURLConnection alloc] initWithRequest:request delegate:self]; #else self->http = [[WOHTTPConnection alloc] initWithURL:[self url]]; if (![self->http sendRequest:request]) { [self->http release]; self->http = nil; return NO; } [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(canReadRequest:) name:WOHTTPConnectionCanReadResponse object:self->http]; #endif if(self->http && self->dFlags.handlesOperationDidStart) [[self delegate] operationDidStart:self]; return self->http != nil ? YES : NO; } @end /* DAVOperation */ @implementation DAVPropFindOperation - (id)initWithURL:(id)_url andPropertyNames:(NSArray *)_props { if ((self = [self initWithURL:_url])) { self->propNames = [_props copy]; } return self; } - (void)dealloc { [self->propNames release]; [super dealloc]; } /* parsing results */ - (void)davHandler:(SaxDAVHandler *)_handler receivedProperties:(NSDictionary *)_record forURI:(NSString *)_uri { if(self->dFlags.handlesDidReceivePropertiesForURL) [[self delegate] operation:self didReceiveProperties:_record forURI:_uri]; } - (void)parseContent { [sax setDelegate:self]; [[self xmlParser] parseFromSource:self->content systemId:[[self url] absoluteString]]; [sax setDelegate:nil]; [sax reset]; NSLog(@" done."); if(self->dFlags.handlesOperationDidFinish) [[self delegate] operationDidFinish:self]; [[NSNotificationCenter defaultCenter] postNotificationName:@"ZzzJobDone" object:self]; } /* request */ - (id)buildRequest { #if WORKING_APPLE_JUNK NSMutableURLRequest *request; #else WORequest *request; #endif NSMutableString *s; NSEnumerator *e; NSString *authorization; NSData *rqData; id prop; s = [NSMutableString stringWithCapacity:256]; [s appendString:@"\n"]; [s appendString:@"\n"]; e = [self->propNames objectEnumerator]; while ((prop = [e nextObject]) != nil) { NSString *ns = @""; if ([prop isKindOfClass:[NSArray class]]) { if ([(NSArray *)prop count] == 1) prop = [prop objectAtIndex:0]; else { ns = [prop objectAtIndex:0]; prop = [prop objectAtIndex:1]; } } if ([ns length] > 0) [s appendFormat:@" <%@ xmlns=\"%@\" />\n", prop, ns]; else [s appendFormat:@" <%@ />\n", prop]; } [s appendString:@"\n"]; rqData = [s dataUsingEncoding:NSUTF8StringEncoding]; authorization = [self _authorization]; #if WORKING_APPLE_JUNK request = [NSMutableURLRequest requestWithURL:[self url]]; [request setHTTPMethod:@"PROPFIND"]; [request setHTTPBody:rqData]; /* Note: the capitalization of the header *is* significant! */ [request setValue:@"text/xml" forHTTPHeaderField:@"Content-Type"]; [request setValue:[NSString stringWithFormat:@"%d", [rqData length]] forHTTPHeaderField:@"Content-Length"]; if (authorization != nil) [request setValue:authorization forHTTPHeaderField:@"authorization"]; #else request = [[WORequest alloc] initWithMethod:@"PROPFIND" uri:[[self url] path] httpVersion:@"HTTP/1.1" headers:nil content:rqData userInfo:nil]; request = [request autorelease]; /* Note: the capitalization of the header *is* significant! */ [request setHeader:@"text/xml" forKey:@"content-type"]; [request setHeader:[NSString stringWithFormat:@"%d", [rqData length]] forKey:@"content-length"]; if (authorization != nil) [request setHeader:authorization forKey:@"authorization"]; #endif return request; } @end /* DAVPropFindOperation */