]> err.no Git - sope/blob - sope-appserver/NGObjWeb/Templates/WOxComponentElemBuilder.m
improved SOPE security exceptions
[sope] / sope-appserver / NGObjWeb / Templates / WOxComponentElemBuilder.m
1 /*
2   Copyright (C) 2002-2004 SKYRIX Software AG
3
4   This file is part of OpenGroupware.org.
5
6   OGo 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   OGo 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 OGo; 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 // $Id$
22
23 #include <NGObjWeb/WOxElemBuilder.h>
24
25 /*
26   This builder builds references to subcomponents. The subcomponent name is
27   derived from the tagname.
28   
29   NOTE: this builder is a "final destination" for all bind(var) namespace
30   tags !
31   
32   Sample:
33     <var:Embed a="a"/>
34
35   Supported tags:
36     <var:script src=...>....</var:script> maps to a component script part ...
37     <var:component className=... />       maps to WOSwitchComponent
38     <var:* ..../>
39 */
40
41 @interface WOxComponentElemBuilder : WOxElemBuilder
42 {
43 }
44
45 @end
46
47 #include <SaxObjC/XMLNamespaces.h>
48 #include <DOM/DOMProtocols.h>
49 #include <DOM/DOMText.h>
50 #include <NGObjWeb/WOAssociation.h>
51 #include <NGObjWeb/WOComponentScript.h>
52 #include "WOChildComponentReference.h"
53 #include "common.h"
54
55 @interface NSObject(LineInfo)
56 - (unsigned)line;
57 @end
58
59 @implementation WOxComponentElemBuilder
60
61 static BOOL debugOn = NO;
62
63 + (void)initialize {
64   NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
65   debugOn = 
66     [[ud objectForKey:@"WOxComponentElemBuilderDebugEnabled"] boolValue];
67 }
68
69 /* extracting associations */
70
71 - (NSMutableDictionary *)associationsForAttributes:(id<DOMNamedNodeMap>)_attrs
72   templateBuilder:(id)_b
73 {
74   NSMutableDictionary *assocs;
75   
76   if ((assocs = [_b associationsForAttributes:_attrs]) == nil)
77     return nil;
78   
79   // should we check the tag or do we always remove className ?
80   if ([assocs objectForKey:@"className"])
81     [assocs removeObjectForKey:@"className"];
82   else if ([assocs objectForKey:@"value"])
83     [assocs removeObjectForKey:@"value"];
84   return assocs;
85 }
86
87 /* building elements */
88
89 - (WOElement *)buildComponentReferenceElement:(id<DOMElement>)_element
90   templateBuilder:(id)_b 
91 {
92   /*
93     TODO: I don't think that this already works - it uses the 'value'
94           binding but WOComponentReference expects 'component'
95   */
96   static Class LiveChildRefClass = Nil;
97   NSMutableDictionary *assocs;
98   NSArray             *children;
99   NSString            *value;
100   WOElement           *de;
101   
102   if (LiveChildRefClass == Nil)
103     LiveChildRefClass = NSClassFromString(@"WOComponentReference");
104   
105   if (debugOn)
106     [self debugWithFormat:@"build component-reference: %@",_element];
107   
108   value = [_element attribute:@"value" namespaceURI:XMLNS_OD_BIND];
109   if ([value length] == 0) return nil;
110   
111   /* construct child elements */
112   
113   children = [_element hasChildNodes]
114     ? [_b buildNodes:[_element childNodes] templateBuilder:_b]
115     : nil;
116   
117   /* build associations */
118   
119   assocs = [self associationsForAttributes:[_element attributes]
120                  templateBuilder:_b];
121   [assocs setObject:[WOAssociation associationWithKeyPath:value]
122           forKey:@"component"];
123   
124   /* build element */
125   
126   if (debugOn) {
127     [self debugWithFormat:
128             @"  create reference for keypath: '%@': children=%@, assocs=%@", 
129             value, children, assocs];
130   }
131   
132   de = [[LiveChildRefClass alloc] 
133                            initWithName:[_b uniqueIDForNode:_element]
134                            associations:assocs
135                            contentElements:children];
136   if (debugOn) [self debugWithFormat:@"  built: %@", de];
137   return de;
138 }
139
140 - (WOElement *)processScriptElement:(id<DOMElement>)_e templateBuilder:(id)_b {
141   /* process a component related script */
142   NSString *src;
143   
144   [self debugWithFormat:@"processing script element: %@", _e];
145   
146   /* first process src attribute ... */
147   if ((src = [_e attribute:@"src" namespaceURI:XMLNS_OD_BIND])) {
148     /* create script part for src ... */
149     [self logWithFormat:@"create script part for src '%@', not implemented",
150             src];
151   }
152     
153   /* create script part for content ... */
154   if ([_e hasChildNodes]) {
155     WOComponentScriptPart *lscript;
156     NSEnumerator      *e;
157     id                subnode;
158     NSMutableString   *content;
159     unsigned          line;
160     NSURL             *url;
161       
162     content = [[NSMutableString alloc] initWithCapacity:256];
163       
164     line = ([(NSObject *)_e respondsToSelector:@selector(line)])
165       ? [(id)_e line] : 0;
166     
167     url = nil;
168       
169     e = [(NSArray *)[_e childNodes] objectEnumerator];
170     while ((subnode = [e nextObject])) {
171       [content appendString:[subnode textValue]];
172     }
173       
174     lscript = [WOComponentScriptPart alloc];
175     lscript = [lscript initWithURL:url startLine:line script:content];
176     [content release];
177       
178     [_b addComponentScriptPart:lscript];
179     [lscript release];
180   }
181   
182   return nil;
183 }
184
185 - (WOElement *)buildElement:(id<DOMElement>)_element templateBuilder:(id)_b {
186   static Class ChildRefClass = Nil;
187   NSMutableDictionary *bindings;
188   NSArray  *children;
189   NSString *cid;
190   NSString *tagName;
191   NSString *compName;
192   
193   if (![[_element namespaceURI] isEqualToString:XMLNS_OD_BIND]) {
194     if (debugOn) {
195       [self debugWithFormat:
196               @"do not process element, not in bind namespace: %@", _element];
197     }
198     return nil;
199   }
200   
201   tagName = [_element tagName];
202   compName = nil;
203   
204   if ([tagName isEqualToString:@"script"])
205     return [self processScriptElement:_element templateBuilder:_b];
206   
207   if ([tagName isEqualToString:@"component"]) {
208     compName = [_element attribute:@"className" namespaceURI:XMLNS_OD_BIND];
209     if ([compName length] == 0) {
210       compName = [_element attribute:@"classname"
211                            namespaceURI:XMLNS_OD_BIND];
212     }
213     if ([compName length] == 0)
214       compName = [_element attribute:@"name" namespaceURI:XMLNS_OD_BIND];
215     
216     /* check whether we should use a "live" reference to a component object */
217     
218     if ([compName length] == 0) {
219       NSString *value;
220       
221       value = [_element attribute:@"value" namespaceURI:XMLNS_OD_BIND];
222       if ([value length] > 0) {
223         return [self buildComponentReferenceElement:_element 
224                      templateBuilder:_b];
225       }
226     }
227     
228     if ([compName length] == 0) {
229       [self logWithFormat:
230               @"missing 'name' or 'value' attribute in var:component: %@", 
231               [_element attributes]];
232       return nil;
233     }
234   }
235   else {
236     [self logWithFormat:@"Creating component %@ using tag. "
237           @"<var:component name='%@'/> is preferred !", 
238           _element, _element];
239   }
240   
241   if (debugOn)
242     [self debugWithFormat:@"creating static component reference: %@",_element];
243   
244   if (ChildRefClass == Nil)
245     ChildRefClass = NSClassFromString(@"WOChildComponentReference");
246   
247   cid = [_b uniqueIDForNode:_element];
248   if (debugOn)
249     [self debugWithFormat:@"BUILD Component(%@): %@", cid, _element];
250   
251   /* construct child elements */
252   
253   children = [_element hasChildNodes]
254     ? [_b buildNodes:[_element childNodes] templateBuilder:_b]
255     : nil;
256   
257   if (compName == nil)
258     compName = [_element tagName];
259
260   bindings = [self associationsForAttributes:[_element attributes]
261                    templateBuilder:_b];
262   if (debugOn)
263     [self debugWithFormat:@"  using bindings: %@", bindings];
264   
265   [_b registerSubComponentWithId:cid
266       componentName:compName
267       bindings:bindings];
268   
269   return [[ChildRefClass alloc]
270                          initWithName:cid
271                          associations:nil
272                          contentElements:children];
273 }
274
275 /* debugging */
276
277 - (BOOL)isDebuggingEnabled {
278   return debugOn;
279 }
280
281 @end /* WOxComponentElemBuilder */