]> err.no Git - sope/blob - sope-appserver/SoOFS/OFSFile.m
Add libxml2-dev to libsope-xml4.7-dev deps
[sope] / sope-appserver / SoOFS / OFSFile.m
1 /*
2   Copyright (C) 2002-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 "OFSFile.h"
23 #include "OFSFolder.h"
24 #include "OFSFactoryContext.h"
25 #include "OFSFileRenderer.h"
26 #include <NGObjWeb/WOResponse.h>
27 #include "common.h"
28
29 @implementation OFSFile
30
31 + (int)version {
32   return [super version] + 0 /* v1 */;
33 }
34 + (void)initialize {
35   static BOOL didInit = NO;
36   if (!didInit) {
37     didInit = YES;
38     NSAssert2([super version] == 1,
39               @"invalid superclass (%@) version %i !",
40               NSStringFromClass([self superclass]), [super version]);
41   }
42 }
43
44 - (void)dealloc {
45   [self->attrCache release];
46   [super dealloc];
47 }
48
49 /* accessors */
50
51 - (BOOL)isCollection {
52   return NO;
53 }
54 - (BOOL)hasChildren {
55   return NO;
56 }
57
58 - (NSStringEncoding)contentEncoding {
59   return [NSString defaultCStringEncoding];
60 }
61
62 - (NSString *)contentAsString {
63   NSData   *data;
64   NSString *s;
65   
66   if ((data = [[self fileManager] contentsAtPath:[self storagePath]]) == nil)
67     return nil;
68   
69   s = [[NSString alloc] initWithData:data encoding:[self contentEncoding]];
70   return [s autorelease];
71 }
72
73 /* writing content */
74
75 - (NSException *)writeState:(id)_value {
76   // TODO: better name: -writeContent:?
77   NSData *data;
78   id fm;
79   
80   if (_value == nil) {
81     return [NSException exceptionWithHTTPStatus:500
82                         reason:@"missing value to write !"];
83   }
84   
85   // TODO: could support some more objects ?
86   if ([_value isKindOfClass:[NSData class]])
87     data = _value;
88   else
89     data = [[_value stringValue] dataUsingEncoding:[self contentEncoding]];
90   
91   fm = [self fileManager];
92   if (![fm writeContents:data atPath:[self storagePath]]) {
93     if ([fm respondsToSelector:@selector(lastException)]) {
94       NSException *e = [fm lastException];
95       [self logWithFormat:@"write of %i bytes failed: %@", [data length], e];
96       return e;
97     }
98     
99     return [NSException exceptionWithHTTPStatus:500
100                         reason:@"could not write content, reason unknown"];
101   }
102   
103   return nil; /* nil is OK */
104 }
105
106 /* attributes */
107
108 - (NSDictionary *)fileAttributes {
109   id fm;
110   
111   if ((fm = [self fileManager]) == nil)
112     return nil;
113   if (self->attrCache == nil) {
114     self->attrCache =
115       [[fm fileAttributesAtPath:[self storagePath] traverseLink:NO] copy];
116   }
117   return self->attrCache;
118 }
119
120 /* KVC */
121
122 - (BOOL)allowAccessToFileAttribute:(NSString *)_name {
123   return YES;
124 }
125
126 - (id)valueForKey:(NSString *)_name {
127   unsigned nl;
128   unichar  c;
129   
130   if ((nl = [_name length]) == 0)
131     return nil;
132   
133   c = [_name characterAtIndex:0];
134   if (c == 'N' && (nl > 6)) {
135     if ([_name hasPrefix:@"NSFile"]) {
136       if ([self allowAccessToFileAttribute:_name])
137         return [[self fileAttributes] objectForKey:_name];
138     }
139   }
140   
141   return [super valueForKey:_name];
142 }
143
144 /* operations */
145
146 - (NSString *)contentTypeInContext:(WOContext *)_ctx {
147   NSString *ext, *type;
148   
149   type = nil;
150   if ((ext = [[self nameInContainer] pathExtension])) {
151     // TODO: read /etc/mime.types
152     if ([ext isEqualToString:@"html"])       type = @"text/html";
153     else if ([ext isEqualToString:@"xhtml"]) type = @"text/xhtml";
154     else if ([ext isEqualToString:@"gif"])   type = @"image/gif";
155     else if ([ext isEqualToString:@"png"])   type = @"image/png";
156   }
157   return type != nil ? type : (NSString *)@"application/octet-stream";
158 }
159
160 - (id)davContentLength {
161   return [[self fileAttributes] objectForKey:NSFileSize];
162 }
163 - (NSDate *)davLastModified {
164   return [[self fileAttributes] objectForKey:NSFileModificationDate];
165 }
166
167 - (id)rendererForObject:(id)_object inContext:(WOContext *)_ctx {
168   return nil;
169 }
170
171 - (id)viewAction:(WOContext *)_ctx {
172   return self;
173 }
174 - (id)GETAction:(WOContext *)_ctx {
175   return self;
176 }
177 - (id)HEADAction:(WOContext *)_ctx {
178   return self;
179 }
180
181 - (id)PUTAction:(WOContext *)_ctx {
182   NSException *e;
183   NSData *content;
184   
185   if ((e = [self validateForSave])) {
186     [self debugWithFormat:@"object did not validate for save ..."];
187     return e;
188   }
189   
190   if ((content = [[_ctx request] content]) == nil)
191     content = [NSData data];
192   
193   if ((e = [self writeState:content]))
194     return e;
195   
196   return self;
197 }
198
199 /* version control */
200
201 - (BOOL)isCvsControlled {
202   return [[self container] isCvsControlled];
203 }
204 - (BOOL)isSvnControlled {
205   return [[self container] isSvnControlled];
206 }
207
208 /* factory */
209
210 + (id)instantiateInFactoryContext:(OFSFactoryContext *)_ctx {
211   id object;
212   
213   object = [[self soClass] instantiateObject];
214   [object takeStorageInfoFromContext:_ctx];
215   return object;
216 }
217
218 @end /* OFSFile */