/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE 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. SOPE 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 SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "NGHttp+WO.h" #include #include #include #include #include "common.h" #include @interface WORequest(NGSupport) - (void)_setHttpRequest:(NGHttpRequest *)_request; @end @implementation NGHttpRequest(WOSupport) static Class NSArrayClass = Nil; - (id)initWithWORequest:(WORequest *)_request { NGHashMap *hm; hm = [NGHashMap hashMapWithDictionary:[_request headers]]; self = [self initWithMethod:[_request method] uri:[_request uri] header:hm version:[_request httpVersion]]; [self setBody:[_request content]]; /* transfer cookies */ if ([[_request cookies] isNotEmpty]) [self warnWithFormat:@"cannot transfer cookies to NGHttpRequest yet !"]; /* transfer headers !!! */ return self; } - (WORequest *)woRequest { NSAutoreleasePool *pool; WORequest *request; NSDictionary *woHeaders; pool = [[NSAutoreleasePool alloc] init]; /* Note: headers are added below ... */ woHeaders = nil; request = [[WORequest alloc] initWithMethod:[self methodName] uri:[self uri] httpVersion:[self httpVersion] headers:woHeaders content:[self woContent] userInfo:nil]; request = [request autorelease]; [request _setHttpRequest:self]; /* process charset */ // DUP: WOSimpleHTTPParser { NSStringEncoding enc = 0; NGMimeType *rqContentType = [self contentType]; NSString *charset = [rqContentType valueOfParameter:@"charset"]; if ([charset isNotEmpty]) { enc = [NSString stringEncodingForEncodingNamed:charset]; } else if (rqContentType != nil) { /* process default charsets for content types */ NSString *majorType = [rqContentType type]; if ([majorType isEqualToString:@"text"]) { NSString *subType = [rqContentType subType]; if ([subType isEqualToString:@"calendar"]) { /* RFC2445, section 4.1.4 */ enc = NSUTF8StringEncoding; } } else if ([majorType isEqualToString:@"application"]) { NSString *subType = [rqContentType subType]; if ([subType isEqualToString:@"xml"]) { // TBD: we should look at the actual content! ( bodyPart; NSString *name; id partBody; bodyPart = [parts objectAtIndex:i]; disposition = [[bodyPart valuesOfHeaderFieldWithName:@"content-disposition"]nextObject]; if (disposition == nil) { [self errorWithFormat: @"did not find content disposition in form part %@", bodyPart]; continue; } /* morph to disposition field in case it's unparsed ... */ if (![disposition isKindOfClass:DispClass]) { disposition = [[DispClass alloc] initWithString:[disposition stringValue]]; [disposition autorelease]; } name = [disposition name]; partBody = [bodyPart body]; if (partBody) [(NGMutableHashMap *)formContent addObject:partBody forKey:name]; } return formContent; } - (NGHashMap *)_decodeFormContentURLParameters:(id)formContent { /* all this sounds expensive ;-) */ NSString *s; unsigned urilen; char *uribuf; const char *p = uribuf; NGHashMap *map; if ((s = [self uri]) == nil) return formContent; if ([s rangeOfString:@"?"].length == 0) return formContent; urilen = [s cStringLength]; p = uribuf = malloc(urilen + 4); [s getCString:uribuf]; // UNICODE? if ((p = index(p, '?')) == NULL) { if (uribuf) free(uribuf); return formContent; } p++; // skip the '?' map = NGDecodeUrlFormParameters((unsigned char *)p, strlen((char *)p)); if (uribuf != NULL) free(uribuf); uribuf = NULL; p = NULL; if (map == nil) return formContent; if (formContent == nil) return map; map = [map autorelease]; // NGDecodeUrlFormParameters returns a retained map! if ([formContent isKindOfClass:[NGHashMap class]]) { NSEnumerator *keys; id key, tmp; tmp = formContent; formContent = [[NGMutableHashMap alloc] initWithHashMap:tmp]; [tmp release]; tmp = nil; keys = [map keyEnumerator]; while ((key = [keys nextObject]) != nil) { NSEnumerator *values; id value; values = [map objectEnumeratorForKey:key]; while ((value = [values nextObject]) != nil) [formContent addObject:value forKey:key]; } } else if ([formContent isKindOfClass:[NSDictionary class]]) { NSEnumerator *keys; id key, tmp; tmp = formContent; formContent = [[NGMutableHashMap alloc] initWithDictionary:tmp]; [tmp release]; keys = [map keyEnumerator]; while ((key = [keys nextObject]) != nil) { NSEnumerator *values; id value; values = [map objectEnumeratorForKey:key]; while ((value = [values nextObject]) != nil) [formContent addObject:value forKey:key]; } } return formContent; } - (NGHashMap *)formParameters { id formContent; if (multipartFormData == nil) multipartFormData = [[NGMimeType mimeType:@"multipart/form-data"] retain]; if ([[self methodName] isEqualToString:@"POST"]) { NGMimeType *contentType = [self contentType]; #if 0 NSLog(@"%s: process POST, ctype %@", __PRETTY_FUNCTION__, contentType); #endif formContent = [contentType hasSameType:multipartFormData] ? [self _decodeMultiPartFormDataContent] : [[self body] retain]; } else formContent = nil; /* decode URL parameters */ formContent = [self _decodeFormContentURLParameters:formContent]; return [formContent autorelease]; } @end /* NGHttpRequest */