]> err.no Git - sope/blob - sope-appserver/NGObjWeb/DynamicElements/WOFileUpload.m
693eaf5df1d2b038841f2dde6b5a8e24f2733b32
[sope] / sope-appserver / NGObjWeb / DynamicElements / WOFileUpload.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 "WOInput.h"
23
24 @interface WOFileUpload : WOInput
25 {
26   // WODynamicElement: extraAttributes
27   // WODynamicElement: otherTagString
28   // inherited: name
29   // inherited: value
30   // inherited: disabled
31 @protected
32   WOAssociation *filePath; // dispostion 'filename'
33   WOAssociation *data;     // uploaded data
34 }
35
36 @end /* WOFileUpload */
37
38 #include "decommon.h"
39 #include <NGMime/NGMime.h>
40 #include <NGHttp/NGHttp.h>
41
42 @interface WORequest(UsedPrivates)
43 - (id)httpRequest;
44 @end
45
46 @implementation WOFileUpload
47
48 static NGMimeType *multipartFormData = nil;
49
50 + (void)initialize {
51   static BOOL isInitialized = NO;
52   if (isInitialized) return;
53   isInitialized = YES;
54
55   multipartFormData = [[NGMimeType mimeType:@"multipart/form-data"] retain];
56 }
57
58 - (id)initWithName:(NSString *)_name
59   associations:(NSDictionary *)_config
60   template:(WOElement *)_t
61 {
62
63   if ((self = [super initWithName:_name associations:_config template:_t])) {
64     self->filePath = OWGetProperty(_config, @"filePath");
65     self->data     = OWGetProperty(_config, @"data");
66   }
67   return self;
68 }
69
70 - (void)dealloc {
71   [self->filePath release];
72   [self->data     release];
73   [super dealloc];
74 }
75
76 /* handling requests */
77
78 - (void)takeValuesFromRequest:(WORequest *)_rq inContext:(WOContext *)_ctx {
79   NGMimeMultipartBody *body;
80   NGMimeType *contentType;
81   NSString   *currentId;
82   id         formValue  = nil;
83   NSArray    *parts;
84   unsigned   i, count;
85   
86   if ([self->disabled boolValueInComponent:[_ctx component]])
87     return;
88
89   currentId = OWFormElementName(self, _ctx);
90
91   if ((formValue = [_rq formValueForKey:currentId]) == nil)
92     return;
93
94   contentType = [[_rq httpRequest] contentType];
95       
96   if (![contentType hasSameType:multipartFormData]) {
97     NSLog(@"WARNING: tried to apply file-upload value of %@ from "
98           @"a non multipart-form request (value=%@) !",
99           [_ctx elementID], formValue);
100     return;
101   }
102   
103 #if 0
104   NSLog(@"%@: value=%@ ..", [self elementID], formValue);
105 #endif
106
107   if ([self->data isValueSettable])
108     [self->data setValue:formValue inComponent:[_ctx component]];
109
110   if (![self->filePath isValueSettable])
111     return;
112   
113   body = [[_rq httpRequest] body];
114   if (![body isKindOfClass:[NGMimeMultipartBody class]])
115     /* TODO: shouldn't we log something? */
116     return;
117   
118   /* search for part of current form element */
119   
120   parts = [body parts];
121   for (i = 0, count = [parts count]; i < count; i++) {
122     static Class DispClass = Nil;
123     NSString       *formName;
124     id             disposition;
125     id<NGMimePart> bodyPart;
126             
127     bodyPart = [parts objectAtIndex:i];
128     disposition = [[bodyPart valuesOfHeaderFieldWithName:
129                                @"content-disposition"] nextObject];
130     
131     if (disposition == nil)
132       continue;
133     
134     if (DispClass == Nil)
135       DispClass = [NGMimeContentDispositionHeaderField class];
136               
137     if (![disposition isKindOfClass:DispClass]) {
138       disposition =
139         [[DispClass alloc] initWithString:[disposition stringValue]];
140       disposition = [disposition autorelease];
141     }
142               
143     formName = [(NGMimeContentDispositionHeaderField *)disposition name];
144       
145     if ([formName isEqualToString:currentId]) {
146       [self->filePath setValue:[disposition filename]
147                       inComponent:[_ctx component]];
148       break;
149     }
150   }
151 }
152
153 /* generating response */
154
155 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
156   NSString *v;
157   
158   if ([[_ctx request] isFromClientComponent])
159     return;
160   
161   v = [self->value stringValueInComponent:[_ctx component]];
162       
163   WOResponse_AddCString(_response, "<input type=\"file\" name=\"");
164   [_response appendContentHTMLAttributeValue:OWFormElementName(self, _ctx)];
165   WOResponse_AddChar(_response, '"');
166   if (v != nil) {
167     WOResponse_AddCString(_response, " value=\"");
168     [_response appendContentHTMLAttributeValue:v];
169     WOResponse_AddChar(_response, '"');
170   }
171   [self appendExtraAttributesToResponse:_response inContext:_ctx];
172   
173   if (self->otherTagString) {
174     WOResponse_AddChar(_response, ' ');
175     WOResponse_AddString(_response,
176                          [self->otherTagString stringValueInComponent:
177                                 [_ctx component]]);
178   }
179   WOResponse_AddEmptyCloseParens(_response, _ctx);
180 }
181
182 /* description */
183
184 - (NSString *)associationDescription {
185   NSMutableString *str;
186   
187   str = [NSMutableString stringWithCapacity:32];
188   [str appendString:[super associationDescription]];
189   
190   if (self->filePath != nil) [str appendFormat:@" path=%@", self->filePath];
191   if (self->data     != nil) [str appendFormat:@" data=%@", self->data];
192   
193   return str;
194 }
195
196 @end /* WOFileUpload */