]> err.no Git - sope/blob - sope-appserver/NGObjWeb/DynamicElements/WOFileUpload.m
improved query string handling
[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     [self warnWithFormat:
98             @"Tried to apply file-upload value of eid=%@ from "
99             @"a non multipart-form request (value=%@).",
100             [_ctx elementID], formValue];
101     return;
102   }
103   
104 #if 0
105   NSLog(@"%@: value=%@ ..", [self elementID], formValue);
106 #endif
107   
108   if ([self->data isValueSettable])
109     [self->data setValue:formValue inComponent:[_ctx component]];
110   
111   /* the remainder is for locating the file path */
112   
113   if (![self->filePath isValueSettable])
114     return;
115   
116   body = [[_rq httpRequest] body];
117   if (![body isKindOfClass:[NGMimeMultipartBody class]])
118     /* TODO: shouldn't we log something? */
119     return;
120   
121   /* search for part of current form element */
122   
123   parts = [body parts];
124   for (i = 0, count = [parts count]; i < count; i++) {
125     static Class DispClass = Nil;
126     NSString       *formName;
127     id             disposition;
128     id<NGMimePart> bodyPart;
129             
130     bodyPart = [parts objectAtIndex:i];
131     disposition = [[bodyPart valuesOfHeaderFieldWithName:
132                                @"content-disposition"] nextObject];
133     
134     if (disposition == nil)
135       continue;
136     
137     if (DispClass == Nil)
138       DispClass = [NGMimeContentDispositionHeaderField class];
139               
140     if (![disposition isKindOfClass:DispClass]) {
141       disposition =
142         [[DispClass alloc] initWithString:[disposition stringValue]];
143       disposition = [disposition autorelease];
144     }
145     
146     formName = [(NGMimeContentDispositionHeaderField *)disposition name];
147       
148     if ([formName isEqualToString:currentId]) {
149       [self->filePath setValue:[disposition filename]
150                       inComponent:[_ctx component]];
151       break;
152     }
153   }
154 }
155
156 /* generating response */
157
158 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
159   NSString *v;
160   
161   if ([[_ctx request] isFromClientComponent])
162     return;
163   
164   v = [self->value stringValueInComponent:[_ctx component]];
165       
166   WOResponse_AddCString(_response, "<input type=\"file\" name=\"");
167   [_response appendContentHTMLAttributeValue:OWFormElementName(self, _ctx)];
168   WOResponse_AddChar(_response, '"');
169   if (v != nil) {
170     WOResponse_AddCString(_response, " value=\"");
171     [_response appendContentHTMLAttributeValue:v];
172     WOResponse_AddChar(_response, '"');
173   }
174   [self appendExtraAttributesToResponse:_response inContext:_ctx];
175   
176   if (self->otherTagString) {
177     WOResponse_AddChar(_response, ' ');
178     WOResponse_AddString(_response,
179                          [self->otherTagString stringValueInComponent:
180                                 [_ctx component]]);
181   }
182   WOResponse_AddEmptyCloseParens(_response, _ctx);
183 }
184
185 /* description */
186
187 - (NSString *)associationDescription {
188   NSMutableString *str;
189   
190   str = [NSMutableString stringWithCapacity:32];
191   [str appendString:[super associationDescription]];
192   
193   if (self->filePath != nil) [str appendFormat:@" path=%@", self->filePath];
194   if (self->data     != nil) [str appendFormat:@" data=%@", self->data];
195   
196   return str;
197 }
198
199 @end /* WOFileUpload */