Script._pike
Go to the documentation of this file.
1 /* Copyright (C) 2000-2006 Thomas Bopp, Thorsten Hampel, Ludger Merkens
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * $Id: Script.pike,v 1.2 2009/08/07 15:22:37 nicke Exp $
18  */
19 inherit "/classes/Object";
20 inherit httplib;
21 inherit "/base/xml_parser";
22 #include <macros.h>
23 #include <database.h>
24 #include <exception.h>
25 #include <classes.h>
26 #include <attributes.h>
27 #include <types.h>
28 //! the Script class is for web scripts with helper function to
29 //! generate html.
30 class Script : public Object,xml_parser{
31 public:
32 
33 
34 
35 
36 
37 
38 
39 private:
40  void init_script() { }
41 
42 public:
43 protected:
44  void create_script() { }
45 
46 public:
47 
48  mapping mLanguages = ([ ]);
49 
50  int __upgrading = 0;
51 
52 /**
53  * Initialization.
54  */
55 protected:
56  void init()
57 {
58  ::init();
59  init_script();
60 }
61 
62 public:
63 
64 protected:
65  void load_object()
66 {
67  object lobj = do_query_attribute(SCRIPT_LANGUAGE_OBJ);
68  if ( objectp(lobj) )
69  init_languages(lobj);
70 }
71 
72 public:
73 
74 string get_language_term(string term, string language)
75 {
76  if ( mappingp(mLanguages) ) {
77  if ( mappingp(mLanguages[language]) )
78  return mLanguages[language][term];
79  }
80  return "!! unknown internationalization for " + term;
81 }
82 
83 private:
84 void init_languages(object languageObj)
85 {
86  set_attribute(SCRIPT_LANGUAGE_OBJ, languageObj);
87 
88  NodeXML n = parse_data(languageObj->get_content());
89  array nodes = n->get_nodes("language");
90  if ( arrayp(nodes) ) {
91  foreach ( nodes, object node ) {
92  string lang = node->attributes->name;
93  if ( !stringp(lang) )
94  steam_error("Uninitialized language in language document !");
95 
96  mLanguages[lang] = ([ ]);
97  foreach( node->get_nodes("term"), object term ) {
98  if ( !stringp(node->attributes->name) )
99  steam_error("Broken language file - missing name attribute on term.");
100  mLanguages[lang][term->attributes->name] = term->get_data();
101  }
102  }
103  }
104 }
105 
106 public:
107 
108 protected:
109  void create_object()
110 {
111  create_script();
112 }
113 
114 public:
115 
116 protected:
117  object find_document(string path)
118 {
119  object env = get_environment();
120  if ( !objectp(env) ) {
121  env = do_query_attribute(OBJ_SCRIPT);
122  if ( objectp(env) && !(env->get_object_class() & CLASS_CONTAINER) )
123  env = env->get_environment();
124  }
125  return _FILEPATH->resolve_path(env, path);
126 }
127 
128 public:
129 
130 protected:
131  string nav_link(object id, string name) {
132  if ( !objectp(id) )
133  return "";
134  return "<a href=\"/scripts/navigate.pike?object="+id->get_object_id()+"\">"+name+"</a>";
135 }
136 
137 public:
138 
139 /**
140  *
141  *
142  * @return 0 upon successfull checking or string (html code)
143  */
144 protected:
145  string check_variables(mapping req, mapping vars)
146 {
147  foreach ( indices(req), string key ) {
148  if ( !vars[key] )
149  THROW("The variable '"+key+"' was not found, but is "+
150  "required !", E_ERROR);
151  switch(req[key]) {
152  case CMD_TYPE_INT:
153  int v;
154  if ( sscanf(vars[key], "%d", v) == 0 )
155  return error_page(
156  "The variable '"+key+"' needs an integer.. <br/>"+
157  sprintf("%O",vars[key]),
158  "JavaScript:history.back();");
159  break;
160  case CMD_TYPE_STRING:
161  if ( !stringp(vars[key]) )
162  return error_page(
163  "The variable '"+key+"' needs a string.. <br/>"+
164  sprintf("%O",vars[key]),
165  "JavaScript:history.back();");
166  break;
167  default:
168  break;
169  }
170  }
171  return 0;
172 }
173 
174 public:
175 
176 /**
177  * Get the value for a variable set by the web-interface which is always
178  * a string.
179  *
180  * @param the original string value
181  * @return integer or float or still a string
182  */
183 mixed
184 get_value(mixed v)
185 {
186  mixed val;
187 
188  if ( v == 0 ) return 0;
189  if ( intp(v) ) return v;
190 
191  val = v / "\0";
192  if ( sizeof(val) > 1 )
193  return val;
194 
195  if ( sscanf(v, "%d", val) == 1 && ((string)val) == v )
196  return val;
197  if ( sscanf(v, "%f", val) == 1 && search((string)val, v) == 0 )
198  return val;
199  return v;
200 }
201 
202 
203 /**
204  * If multiple values are assigned to a single variable it is
205  * converted to an array in this function.
206  *
207  * @param v - the original string value
208  * @return the resulting array
209  * @see get_value
210  */
211 array get_values(string v)
212 {
213  array res = v / "\0";
214  array result = ({ });
215 
216  foreach ( res, string str ) {
217  if ( stringp(str) && strlen(str) > 0 )
218  result += ({ get_value(str) });
219  }
220  return result;
221 }
222 
223 /**
224  * Extract an array of objects from a given string value.
225  * An object-array is provided by the web-interface as a string of
226  * integers separated by \0
227  *
228  * @param str - the source string
229  * @return an array of objects
230  * @see get_values
231  */
232 protected:
233  array extract_objects(string str)
234 {
235  array result = ({ });
236 
237  if ( !stringp(str) )
238  return result;
239 
240  array res = str / "\0";
241  foreach( res, string oid ) {
242  object obj;
243  obj = find_object((int)oid);
244  if ( objectp(obj) )
245  result += ({ obj });
246  }
247  LOG("Result="+sprintf("%O\n",result));
248  return result;
249 }
250 
251 public:
252 
253 /**
254  * Get an array of objects which are in the vars mapping passed to
255  * steam by the web server. The mapping will contain an array of
256  * object ids.
257  *
258  * @param mapping vars - the parameter mapping.
259  * @param string index - the index to lookup inthe mapping.
260  * @return array of objects found in the mapping.
261  * @see
262  */
263 array get_objects(mapping vars, string index)
264 {
265  array result = ({ });
266 
267  array res;
268  if ( arrayp(vars[index]) )
269  res = vars[index];
270  else if ( !stringp(vars[index]) )
271  return result;
272  else
273  res = vars[index] / "\0";
274 
275  foreach( res, string oid ) {
276  object obj;
277  obj = find_object((int)oid);
278  if ( objectp(obj) )
279  result += ({ obj });
280  }
281  return result;
282 }
283 
284 /**
285  * Replace all variables in a html template.
286  *
287  * @param string templ - the html template string
288  * @param mapping vars - variables to exchange
289  * @return the exchanged template
290  */
291 string html_template(string|object templ, mapping vars)
292 {
293  mapping templ_vars = ([ ]);
294 
295  if ( objectp(templ) ) {
296  if ( !(templ->get_object_class() & CLASS_DOCUMENT) )
297  THROW("Template object is not a document.", E_ERROR);
298 
299  templ = templ->get_content();
300  }
301 
302  foreach(indices(vars), string key) {
303  mixed val = vars[key];
304  if ( stringp(val) )
305  templ_vars["{"+key+"}"] = val;
306  }
307  templ_vars["{SCRIPT}"] = "/scripts/execute.pike?script="+get_object_id();
308 
309  return replace(templ, indices(templ_vars), values(templ_vars));
310 }
311 
312 /**
313  * Create a new instance of a CLASS_
314  *
315  * @param int cid - the class flag
316  * @param mapping vars - vars mapping for the factory.
317  * @return newly created object
318  */
319 object new_instance(int cid, mapping vars)
320 {
321  object factory = _Server->get_factory(cid);
322  object obj = factory->execute(vars);
323  return obj;
324 }
325 
326 /**
327  *
328  *
329  * @param
330  * @return
331  * @see
332  */
333 string html_template_block(string|object templ, string block, array bvars)
334 {
335  mapping templ_vars = ([ ]);
336 
337  if ( objectp(templ) ) {
338  if ( !(templ->get_object_class() & CLASS_DOCUMENT) )
339  THROW("Template object is not a document.", E_ERROR);
340 
341  templ = templ->get_content();
342  }
343 
344  int count = 0;
345  templ = replace(templ, "<!-- END " + block + " -->",
346  "<!-- BEGIN " + block + " -->");
347  array blocks = templ / ("<!-- BEGIN " + block + " -->");
348  string block_html = "";
349  foreach ( bvars, mapping vars ) {
350  templ_vars = ([ ]);
351  foreach( indices(vars), string index )
352  templ_vars["{"+index+"}"] = (string)vars[index];
353  block_html += replace(blocks[1], indices(templ_vars), values(templ_vars));
354  }
355  return blocks[0] + block_html + blocks[2];
356 }
357 
358 /**
359  * Create a selection field for an object. The parameter passed has to be a container
360  * or a Group and will list the content as selections.
361  *
362  * @param
363  * @return
364  * @see
365  */
366 string make_selection(string name, object obj, object|void val, int|void classbit)
367 {
368  string html = "<select name=\""+name+"\">\n";
369  if ( classbit == 0 )
370  classbit = CLASS_OBJECT;
371 
372  array res = ({ });
373 
374  if ( obj->get_object_class() & CLASS_CONTAINER ) {
375  foreach( obj->get_inventory(), object o )
376  if ( o->get_object_class() & classbit )
377  res += ({ o });
378  }
379  else if ( obj->get_object_class() & CLASS_GROUP ) {
380  foreach( obj->get_members(), object m )
381  if ( m->get_object_class() & classbit )
382  res += ({ m });
383  }
384  foreach(res, object r) {
385  html += sprintf("<option value=\"%d\""+
386  (objectp(val) && val == r ? " selected='true'":"")+
387  ">%s</option>",
388  r->get_object_id(),
389  (r->get_object_class() & CLASS_USER ?
390  r->query_attribute(USER_FULLNAME) :
391  r->get_identifier()));
392  }
393  html += "</select>\n";
394  return html;
395 }
396 
397 string image(object obj, mapping args)
398 {
399  return "<image src=\"/scripts/get.pike?object="+obj->get_object_id()+"\""+
400  (args->xsize ? " xsize=\""+args->xsize+"\"":"")+
401  (args->ysize ? " xsize=\""+args->ysize+"\"":"")+
402  " border=\"0\"/>";
403 }
404 
405 /**
406  * Upgrade callback function - the the creation time to current timestamp.
407  *
408  */
409 void upgrade()
410 {
411  __upgrading = 1;
412 }
413 
414 final object get_source_object()
415 {
416  program prg = object_program(this_object());
417  string desc = master()->describe_program(prg);
418  int id;
419  if ( !sscanf(desc, "%*s#%d", id) )
420  sscanf(desc, "%*s#%d", id);
421 
422  return find_object(id);
423 }
424 
425 
426 /**
427  * Describe the Script in a backtrace.
428  *
429  * @return description string of the object
430  */
431 string _sprintf()
432 {
433  return master()->describe_program(object_program(this_object())) + " ("+
434  get_identifier()+", #"+get_object_id()+")";
435 }
436 
437 int is_upgrading() { return __upgrading; }
438 int get_object_class() { return ::get_object_class() | CLASS_SCRIPT; }
439 string describe() { return _sprintf(); }
440 
441 {
442  Test.test( "float value is float", floatp(get_value("1.1")) );
443  Test.test( "string match", get_value("1test") == "1test" );
444  Test.test( "\\0 separated string returns array", arrayp(get_value("a\0b")) );
445  Test.test( "get_value() handles integers correctly",
446  intp(get_value("22")) && get_value("42") == 42 );
447 }
448 
449 
450 
451 };