]> err.no Git - sope/blob - sope-appserver/NGObjWeb/NGHttp/NGHttpMessage.m
increased element nesting depth
[sope] / sope-appserver / NGObjWeb / NGHttp / NGHttpMessage.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with SOPE; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21
22 #include "NGHttpMessage.h"
23 #include "common.h"
24 #include "NGHttpCookie.h"
25
26 @interface NGHttpMessage(PrivateMethods)
27 - (void)extractCommonHeaders;
28 @end
29
30 @implementation NGHttpMessage
31
32 - (id)initWithHeader:(NGHashMap *)_header version:(NSString *)_version {
33   if ((self = [super init])) {
34     self->header = [_header retain];
35     self->body   = nil;
36
37     if ([_version hasSuffix:@"0.9"]) {
38       self->majorVersion = 0;
39       self->minorVersion = 9;
40     }
41     else if ([_version hasSuffix:@"1.0"]) {
42       self->majorVersion = 1;
43       self->minorVersion = 0;
44     }
45     else if ([_version hasSuffix:@"1.1"]) {
46       self->majorVersion = 1;
47       self->minorVersion = 1;
48     }
49     else {
50       self->majorVersion = 0;
51       self->minorVersion = 9;
52     }
53     
54     [self extractCommonHeaders];
55   }
56   return self;
57 }
58 - (id)init {
59   return [self initWithHeader:nil version:nil];
60 }
61
62 - (void)dealloc {
63   [self->header release];
64   [self->body   release];
65   [super dealloc];
66 }
67
68 /* headers */
69
70 - (void)extractCommonHeaders {
71 }
72
73 - (void)setValue:(id)_value ofHeaderFieldWithName:(NSString *)_name {
74   if (![self->header isKindOfClass:[NGMutableHashMap class]]) {
75     id new = [self->header mutableCopy];
76     [self->header release];
77     self->header = new;
78   }
79   [(NGMutableHashMap *)self->header setObject:_value forKey:_name];
80 }
81 - (void)addValue:(id)_value toHeaderFieldWithName:(NSString *)_name {
82   if (![self->header isKindOfClass:[NGMutableHashMap class]]) {
83     id new = [self->header mutableCopy];
84     [self->header release];
85     self->header = new;
86   }
87   [(NGMutableHashMap *)self->header addObject:_value forKey:_name];
88 }
89 - (void)removeValue:(id)_value fromHeaderFieldWithName:(NSString *)_name {
90   if (![self->header isKindOfClass:[NGMutableHashMap class]]) {
91     id new = [self->header mutableCopyWithZone:[self zone]];
92     [self->header release];
93     self->header = new;
94   }
95   [(NGMutableHashMap *)self->header removeAllObjects:_value forKey:_name];
96 }
97
98 /* common headers */
99
100 - (void)setContentType:(NGMimeType *)_type {
101   [self setValue:_type ofHeaderFieldWithName:@"content-type"];
102 }
103 - (void)setContentLength:(unsigned)_length {
104   [self setValue:[NSNumber numberWithUnsignedInt:_length]
105         ofHeaderFieldWithName:@"content-length"];
106 }
107
108 - (unsigned)contentLength {
109   return [[self->header objectForKey:@"content-length"] intValue];
110 }
111
112 - (id)valueOfHeaderFieldWithName:(NSString *)_name {
113   return [self->header objectForKey:_name];
114 }
115
116 /* accessors */
117
118 - (NSString *)httpVersion {
119   return [NSString stringWithFormat:@"HTTP/%i.%i",
120                      self->majorVersion,
121                      self->minorVersion];
122 }
123 - (char)majorVersion {
124   return self->majorVersion;
125 }
126 - (char)minorVersion {
127   return self->minorVersion;
128 }
129
130 /* Cookies */
131
132 - (NSArray *)cookies {
133   return [self->header objectForKey:@"cookie"];
134 }
135
136 - (id)valueOfCookieWithName:(NSString *)_name {
137   NSArray *cookies   = [self->header objectForKey:@"cookie"];
138   int     pos, count = [cookies count];
139
140   //NSLog(@"cookies=%@", cookies);
141
142   for (pos = 0; pos < count; pos++) {
143     NGHttpCookie *cookie = [cookies objectAtIndex:pos];
144
145     NSAssert([cookie isKindOfClass:[NGHttpCookie class]],
146              @"invalid cookie value");
147     
148     if ([[cookie cookieName] isEqualToString:_name])
149       return [cookie value];
150   }
151   return nil;
152 }
153
154 - (void)addClientCookie:(NGHttpCookie *)_cookie {
155   // 'Set-Cookie' header
156   [(NGMutableHashMap *)self->header addObject:_cookie forKey:@"set-cookie"];
157 }
158 - (NSArray *)clientCookies {
159   return [self->header objectsForKey:@"set-cookie"];
160 }
161
162 /* NGPart */
163
164 - (NSEnumerator *)valuesOfHeaderFieldWithName:(NSString *)_name {
165   return [self->header objectEnumeratorForKey:_name];
166 }
167 - (NSEnumerator *)headerFieldNames {
168   return [self->header keyEnumerator];
169 }
170
171 - (void)setBody:(id)_body {
172   ASSIGN(self->body, _body);
173 }
174 - (id)body {
175   return self->body;
176 }
177
178 /* NGMimePart */
179
180 - (NGMimeType *)contentType {
181   id type;
182   
183   if ((type = [self valueOfHeaderFieldWithName:@"content-type"]) == nil)
184     return [NGMimeType mimeType:@"text/plain"];
185
186   if (![type isKindOfClass:[NGMimeType class]])
187     type = [NGMimeType mimeType:[type stringValue]];
188   
189   return type;
190 }
191 - (NSString *)contentId {
192   return [[self->header objectForKey:@"content-id"] stringValue];
193 }
194 - (NSArray *)contentLanguage {
195   id val;
196
197   if ((val = [self->header objectForKey:@"content-language"]) == nil)
198     return nil;
199
200   if (![val isKindOfClass:[NSArray class]])
201     val = [[val stringValue] componentsSeparatedByString:@","];
202   
203   return val;
204 }
205 - (NSString *)contentMd5 {
206   return [[self->header objectForKey:@"content-md5"] stringValue];
207 }
208 - (NSString *)encoding {
209   return [[self->header objectForKey:@"content-encoding"] stringValue];
210 }
211 - (NSString *)contentDescription {
212   return [[self->header objectForKey:@"content-description"] stringValue];
213 }
214
215 @end /* NGHttpMessage */
216
217 /* constants */
218
219 // used in 'Accept-Encoding' and 'Content-Encoding'
220 NSString *NGHttpContentCoding_gzip      = @"gzip";
221 NSString *NGHttpContentCoding_compress  = @"compress";
222 NSString *NGHttpContentCoding_deflate   = @"deflate";
223 NSString *NGHttpContentCoding_identity  = @"identity";
224
225 // used in 'Transfer-Encoding'
226 NSString *NGHttpTransferCoding_chunked  = @"chunked";
227 NSString *NGHttpTransferCoding_identity = @"identity";
228 NSString *NGHttpTransferCoding_gzip     = @"gzip";
229 NSString *NGHttpTransferCoding_compress = @"compress";
230 NSString *NGHttpTransferCoding_deflate  = @"deflate";