2 Copyright (C) 2000-2005 SKYRIX Software AG
4 This file is part of SOPE.
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
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.
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
23 #include "WOElement+private.h"
25 #include "WOContext+private.h"
26 #include <NGObjWeb/WOApplication.h>
29 @implementation WOForm
31 static int debugTakeValues = -1;
37 - (id)initWithName:(NSString *)_name
38 associations:(NSDictionary *)_config
39 template:(WOElement *)_c
41 if (debugTakeValues == -1) {
43 [[NSUserDefaults standardUserDefaults] boolForKey:@"WODebugTakeValues"]
45 if (debugTakeValues) NSLog(@"WOForm: WODebugTakeValues on.");
48 if ((self = [super initWithName:_name associations:_config template:_c])) {
49 WOAssociation *sidInUrlAssoc;
52 self->containsForm = YES;
54 sidInUrlAssoc = OWGetProperty(_config, @"?wosid");
55 self->action = OWGetProperty(_config, @"action");
56 self->href = OWGetProperty(_config, @"href");
57 self->pageName = OWGetProperty(_config, @"pageName");
58 self->queryDictionary = OWGetProperty(_config, @"queryDictionary");
59 self->queryParameters = OWExtractQueryParameters(_config);
60 self->actionClass = OWGetProperty(_config, @"actionClass");
61 self->directActionName = OWGetProperty(_config, @"directActionName");
62 self->method = OWGetProperty(_config, @"method");
64 self->sidInUrl = (sidInUrlAssoc != nil)
65 ? [sidInUrlAssoc boolValueInComponent:nil]
68 if ((tmp = OWGetProperty(_config, @"multipleSubmit")) != nil) {
69 /* not required with SOPE, for WO compatibility */
73 self->template = [_c retain];
79 [self->method release];
80 [self->template release];
81 [self->actionClass release];
82 [self->directActionName release];
83 [self->queryDictionary release];
84 [self->queryParameters release];
85 [self->action release];
86 [self->pageName release];
91 /* handle active form elements */
93 - (WOElement *)template {
94 return self->template;
97 // ******************** responder ********************
99 - (void)takeValuesFromRequest:(WORequest *)_request
100 inContext:(WOContext *)_ctx
102 static int alwaysPassIn = -1;
104 if (alwaysPassIn == -1) {
105 alwaysPassIn = [[[NSUserDefaults standardUserDefaults]
106 objectForKey:@"WOFormAlwaysPassDown"]
110 if ([_ctx isInForm]) {
111 [self errorWithFormat:@"(%s): another form is already active in context !",
112 __PRETTY_FUNCTION__];
115 [_ctx setInForm:YES];
117 WOComponent *sComponent = [_ctx component];
118 BOOL doTakeValues = NO;
120 if (self->queryParameters) {
121 /* apply values to ?style parameters */
125 keys = [self->queryParameters keyEnumerator];
126 while ((key = [keys nextObject])) {
127 WOAssociation *assoc;
130 assoc = [self->queryParameters objectForKey:key];
131 value = [_request formValueForKey:key];
133 [assoc setValue:value inComponent:sComponent];
137 if ([[self->href stringValueInComponent:sComponent]
138 isEqualToString:[_request uri]]) {
139 if (debugTakeValues) {
140 NSArray *formValues = [_request formValueKeys];
141 NSLog(@"%s: we are uri active (uri=%@): %@ ..", __PRETTY_FUNCTION__,
142 [_request uri], formValues);
146 else if ([[_ctx elementID] isEqualToString:[_ctx senderID]]) {
147 if (debugTakeValues) {
148 NSArray *formValues = [_request formValueKeys];
149 NSLog(@"%s: we are elem active (eid=%@): %@ ..", __PRETTY_FUNCTION__,
150 [_ctx elementID], formValues);
154 else if (alwaysPassIn) {
156 NSLog(@"%s: taking values from foreign request ",__PRETTY_FUNCTION__);
160 /* finally, let the component decide */
161 doTakeValues = [sComponent shouldTakeValuesFromRequest:_request
163 if (debugTakeValues) {
164 NSLog(@"%s: component should take values: %s ", __PRETTY_FUNCTION__,
165 doTakeValues ? "yes" : "no");
171 NSLog(@"%s: taking values ...", __PRETTY_FUNCTION__);
173 [self->template takeValuesFromRequest:_request inContext:_ctx];
176 NSLog(@"%s: did take values.", __PRETTY_FUNCTION__);
178 else if (debugTakeValues) {
181 @"WOForm: *not* taking values from foreign request "
182 @"(id='%@' vs sid='%@') ...",
183 [_ctx elementID], [_ctx senderID]];
187 if (![_ctx isInForm]) {
189 errorWithFormat:@"(%s:%d): -isInForm is NO !!!",
190 __PRETTY_FUNCTION__, __LINE__];
196 - (id)invokeActionForRequest:(WORequest *)_request
197 inContext:(WOContext *)_ctx
201 [_ctx setInForm:YES];
203 if ([_ctx currentElementID] == nil) {
206 if ((element = [_ctx activeFormElement])) {
208 result = [self->template invokeActionForRequest:_request inContext:_ctx];
211 /* wrong - need to setup correct component stack */
212 result = [[element invokeActionForRequest:_request
217 else if (self->action) {
218 result = [self executeAction:self->action inContext:_ctx];
220 else if (self->pageName) {
221 NSString *pname = nil;
222 WOComponent *page = nil;
224 pname = [self->pageName stringValueInComponent:[_ctx component]];
225 page = [[_ctx application] pageWithName:pname inContext:_ctx];
228 [[_ctx session] logWithFormat:
229 @"%@[0x%08X]: did not find page with name %@ !",
230 NSStringFromClass([self class]), self, pname];
232 NSLog(@"showing page %@", page);
237 result = [self->template invokeActionForRequest:_request inContext:_ctx];
244 - (NSString *)_addHrefToResponse:(WOResponse *)_r inContext:(WOContext *)_ctx {
245 /* post to a fixed hyperlink */
246 WOComponent *sComponent = [_ctx component];
250 s = [self->href stringValueInComponent:sComponent];
251 d = [self->queryDictionary valueInComponent:sComponent];
253 WOResponse_AddString(_r, s);
255 return [self queryStringForQueryDictionary:d
256 andQueryParameters:self->queryParameters
260 - (NSString *)_addActionToResponse:(WOResponse *)_r inContext:(WOContext *)_c {
261 /* post to a component action */
264 WOResponse_AddString(_r, [_c componentActionURL]);
266 d = [self->queryDictionary valueInComponent:[_c component]];
267 return [self queryStringForQueryDictionary:d
268 andQueryParameters:self->queryParameters
272 - (void)_addDirectActionToResponse:(WOResponse *)_r inContext:(WOContext *)_c {
273 /* a direct action link */
274 WOComponent *sComponent;
275 NSString *daClass = nil;
276 NSString *daName = nil;
277 NSMutableDictionary *qd;
281 sComponent = [_c component];
282 daClass = [self->actionClass stringValueInComponent:sComponent];
283 daName = [self->directActionName stringValueInComponent:sComponent];
285 if (daClass != nil) {
287 if (![daClass isEqualToString:@"DirectAction"])
288 daName = [NSString stringWithFormat:@"%@/%@", daClass, daName];
294 qd = [NSMutableDictionary dictionaryWithCapacity:16];
296 /* add query dictionary */
298 if (self->queryDictionary) {
299 if ((tmp = [self->queryDictionary valueInComponent:sComponent]))
300 [qd addEntriesFromDictionary:tmp];
303 /* add ?style parameters */
305 if (self->queryParameters) {
309 keys = [self->queryParameters keyEnumerator];
310 while ((key = [keys nextObject])) {
313 assoc = [self->queryParameters objectForKey:key];
314 value = [assoc stringValueInComponent:sComponent];
316 [qd setObject:(value ? value : @"") forKey:key];
321 if (self->sidInUrl && [_c hasSession]) {
325 [qd setObject:[sn sessionID] forKey:WORequestValueSessionID];
327 if (![sn isDistributionEnabled]) {
328 [qd setObject:[[WOApplication application] number]
329 forKey:WORequestValueInstance];
332 else if (self->sidInUrl) {
333 /* Note: this is not a problem! Eg this occurs on the OGo Main component */
334 [self debugWithFormat:
335 @"Note: session-id is requested, but no session is active?"];
338 uri = [_c directActionURLForActionNamed:daName queryDictionary:qd];
339 WOResponse_AddString(_r, uri);
342 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
343 WOComponent *sComponent;
344 NSString *queryString = nil;
346 if ([[_ctx request] isFromClientComponent]) {
347 [self->template appendToResponse:_response inContext:_ctx];
351 [_ctx setInForm:YES];
352 sComponent = [_ctx component];
354 WOResponse_AddCString(_response, "<form action=\"");
356 if (self->href != nil)
357 queryString = [self _addHrefToResponse:_response inContext:_ctx];
358 else if (self->directActionName != nil || self->actionClass != nil)
359 [self _addDirectActionToResponse:_response inContext:_ctx];
361 queryString = [self _addActionToResponse:_response inContext:_ctx];
364 [_response appendContentCharacter:'?'];
365 WOResponse_AddString(_response, queryString);
368 WOResponse_AddCString(_response, "\" method=\"");
369 WOResponse_AddString(_response,
370 [self->method stringValueInComponent:sComponent]);
371 WOResponse_AddCString(_response, "\"");
374 WOResponse_AddCString(_response, "\" method=\"post\"");
376 [self appendExtraAttributesToResponse:_response inContext:_ctx];
378 if (self->otherTagString) {
379 WOResponse_AddChar(_response, ' ');
380 WOResponse_AddString(_response,
381 [self->otherTagString stringValueInComponent:
384 WOResponse_AddChar(_response, '>');
386 [self->template appendToResponse:_response inContext:_ctx];
388 WOResponse_AddCString(_response, "</form>");
394 - (NSString *)associationDescription {
395 NSMutableString *str = [NSMutableString stringWithCapacity:64];
396 //[str appendString:[super associationDescription]];
398 if (self->action) [str appendFormat:@" action=%@", self->action];
399 if (self->href) [str appendFormat:@" href=%@", self->href];
400 if (self->pageName) [str appendFormat:@" page=%@", self->pageName];
402 if (self->actionClass)
403 [str appendFormat:@" actionClass=%@", self->actionClass];
404 if (self->directActionName)
405 [str appendFormat:@" directAction=%@", self->directActionName];
407 [str appendFormat:@" template=%@", self->template];