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 <NGObjWeb/WOHTMLDynamicElement.h>
23#include "WOElement+private.h"
24#include <NGObjWeb/WOAssociation.h>
25#include <NGObjWeb/WOContext.h>
26#include <NGObjWeb/WOApplication.h>
27#include <NGObjWeb/WOSession.h>
28#include <NGObjWeb/WORequest.h>
29#include <NGObjWeb/WOResponse.h>
30#include "decommon.h"
31
32/*
33  WOMetaRefresh associations:
34
35    href | pageName | action | (directActionName & actionClass)
36    fragmentIdentifier
37    disabled
38    timeout/seconds
39*/
40
41@interface WOMetaRefresh : WOHTMLDynamicElement
42{
43  // WODynamicElement: extraAttributes
44  // WODynamicElement: otherTagString
45@protected
46  WOAssociation *action;
47  WOAssociation *href;
48  WOAssociation *pageName;
49  WOAssociation *directActionName;
50  WOAssociation *actionClass;
51  WOAssociation *disabled;
52  WOAssociation *fragmentIdentifier;
53  WOAssociation *timeout;
54
55  WOAssociation *queryDictionary;
56  NSDictionary  *queryParameters;  /* associations beginning with ? */
57  BOOL          sidInUrl;
58}
59
60@end
61
62@implementation WOMetaRefresh
63
64- (id)initWithName:(NSString *)_name
65  associations:(NSDictionary *)_config
66  template:(WOElement *)_t
67{
68  if ((self = [super initWithName:_name associations:_config template:_t])) {
69    WOAssociation *sidInUrlAssoc;
70
71    sidInUrlAssoc            = OWGetProperty(_config, @"?wosid");
72    self->action             = OWGetProperty(_config, @"action");
73    self->href               = OWGetProperty(_config, @"href");
74    self->pageName           = OWGetProperty(_config, @"pageName");
75    self->fragmentIdentifier = OWGetProperty(_config, @"fragmentIdentifier");
76    self->disabled           = OWGetProperty(_config, @"disabled");
77    self->timeout            = OWGetProperty(_config, @"timeout");
78    self->directActionName   = OWGetProperty(_config, @"directActionName");
79    self->actionClass        = OWGetProperty(_config, @"actionClass");
80
81    self->sidInUrl = (sidInUrlAssoc)
82      ? [sidInUrlAssoc boolValueInComponent:nil]
83      : YES;
84
85    if (self->timeout == nil)
86      self->timeout = OWGetProperty(_config, @"seconds");
87    else if ([OWGetProperty(_config, @"seconds") autorelease] != nil) {
88      [self logWithFormat:
89	      @"WARNING: got both, 'timeout' and 'seconds' bindings!"];
90    }
91
92    self->queryDictionary = OWGetProperty(_config, @"queryDictionary");
93    self->queryParameters = OWExtractQueryParameters(_config);
94  }
95  return self;
96}
97
98- (void)dealloc {
99  [self->queryParameters    release];
100  [self->queryDictionary    release];
101  [self->directActionName   release];
102  [self->actionClass        release];
103  [self->action             release];
104  [self->href               release];
105  [self->pageName           release];
106  [self->fragmentIdentifier release];
107  [self->disabled           release];
108  [self->timeout            release];
109  [super dealloc];
110}
111
112/* handling requests */
113
114- (id)invokeActionForRequest:(WORequest *)_request
115  inContext:(WOContext *)_ctx
116{
117  if ([self->disabled boolValueInComponent:[_ctx component]])
118    return nil;
119
120  if (self->action)
121    return [self executeAction:self->action inContext:_ctx];
122
123  if (self->pageName) {
124    NSString    *name;
125    WOComponent *page;
126
127    name = [self->pageName stringValueInComponent:[_ctx component]];
128    page = [[_ctx application] pageWithName:name inContext:_ctx];
129
130    if (page == nil) {
131      [[_ctx component] logWithFormat:
132                          @"%@[0x%p]: did not find page with name %@ !",
133                          NSStringFromClass([self class]), self, name];
134    }
135    [self debugWithFormat:@"showing page %@", page];
136    return page;
137  }
138
139  [[_ctx component]
140         logWithFormat:@"%@[0x%p]: no action/page set !",
141           NSStringFromClass([self class]), self];
142  return nil;
143}
144
145/* generating response */
146
147- (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
148  WOComponent *sComponent;
149  int         to;
150  NSString    *url;
151  NSString    *queryString;
152  BOOL        addSID;
153
154  if ([_ctx isRenderingDisabled] || [[_ctx request] isFromClientComponent])
155    return;
156
157  sComponent  = [_ctx component];
158  queryString = nil;
159  to = [self->timeout intValueInComponent:sComponent];
160  WOResponse_AddCString(_response, "<meta http-equiv=\"refresh\" content=\"");
161  WOResponse_AddInt(_response, to);
162  WOResponse_AddCString(_response, "; url=");
163
164  if (self->href) {
165    /* a href was explicitly assigned */
166    url = [self->href stringValueInComponent:sComponent];
167    addSID = self->sidInUrl;
168  }
169  else if (self->directActionName) {
170    /* a direct action */
171    NSString *daClass;
172    NSString *daName;
173
174    daClass = [self->actionClass      stringValueInComponent:sComponent];
175    daName  = [self->directActionName stringValueInComponent:sComponent];
176
177    if (daClass) {
178      if (daName) {
179        if (![daClass isEqualToString:@"DirectAction"])
180          daName = [NSString stringWithFormat:@"%@/%@", daClass, daName];
181      }
182      else
183        daName = daClass;
184    }
185
186    url = [_ctx directActionURLForActionNamed:daName queryDictionary:nil];
187    addSID = self->sidInUrl;
188  }
189  else {
190    url = [_ctx componentActionURL];
191    addSID = NO;
192  }
193  WOResponse_AddString(_response, url);
194
195  queryString = [self queryStringForQueryDictionary:
196                        [self->queryDictionary valueInComponent:sComponent]
197                      andQueryParameters:self->queryParameters
198                      inContext:_ctx];
199  if (addSID && [sComponent hasSession]) {
200    WOSession *sn = [sComponent session];
201
202    if ([queryString length] == 0) {
203      queryString = [NSString stringWithFormat:@"%@=%@",
204			      WORequestValueSessionID, [sn sessionID]];
205    }
206    else {
207      queryString = [queryString stringByAppendingFormat:@"&%@=%@",
208			      WORequestValueSessionID, [sn sessionID]];
209    }
210  }
211
212  if (self->fragmentIdentifier) {
213    [_response appendContentCharacter:'#'];
214    WOResponse_AddString(_response,
215                         [self->fragmentIdentifier stringValueInComponent:
216                              sComponent]);
217  }
218
219  if (queryString) {
220    [_response appendContentCharacter:'?'];
221    WOResponse_AddString(_response, queryString);
222  }
223
224  [_response appendContentCharacter:'"']; // close CONTENT attribute
225
226  [self appendExtraAttributesToResponse:_response inContext:_ctx];
227  if (self->otherTagString) {
228    WOResponse_AddChar(_response, ' ');
229    WOResponse_AddString(_response,
230                         [self->otherTagString stringValueInComponent:
231                              [_ctx component]]);
232  }
233  WOResponse_AddEmptyCloseParens(_response, _ctx);
234}
235
236/* description */
237
238- (NSString *)associationDescription {
239  NSMutableString *str = [NSMutableString stringWithCapacity:256];
240
241  if (self->action)   [str appendFormat:@" action=%@",   self->action];
242  if (self->href)     [str appendFormat:@" href=%@",     self->href];
243  if (self->pageName) [str appendFormat:@" pageName=%@", self->pageName];
244  if (self->fragmentIdentifier)
245    [str appendFormat:@" fragment=%@", self->fragmentIdentifier];
246  if (self->disabled) [str appendFormat:@" disabled=%@", self->disabled];
247
248  return str;
249}
250
251@end /* WOMetaRefresh */
252