connection._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: connection.pike,v 1.2 2010/02/13 09:30:55 astra Exp $
18  */
19 inherit "client_base";
20 inherit "base/xml_parser";
21 #include <coal.h>
22 #include <client.h>
23 #include <classes.h>
24 #include <attributes.h>
25 //! upload the package on the server
26 //! And run update routines...
27 class connection : public client_base,xml_parser{
28 public:
29 
30 
31 
32 
33 /*
34  * installation script
35  * the pike call will include the pathnames to the server location
36  */
37 
38 
39 //#define CHECK_ONLY
40 
41  object fsystem; // the filesystem to use
42  string _fs;
43 
44  int debug_output = 0;
45 
46 private mapping mFiles = ([ ]);
47 object _docfactory, _contfactory, _filepath;
48 int iInstall, iUpdate, iError;
49 
50 int handle_error(mixed err) {
51  if ( arrayp(err) && sizeof(err)>1 ) {
52  if ( stringp(err[1]) ) werror( "Error: %s\n", err[1] );
53  else werror( "Error: %O\n", err[1] );
54  }
55  else werror( "Error: %O\n", err );
56  throw( ({ "", backtrace() }) );
57  if ( debug_output ) {
58  werror( "Debug output:\n%O\n", err );
59  throw( ({ "", backtrace() }) );
60  }
61  exit(1);
62 }
63 
64 object open_file(string fname, string fs)
65 {
66  return Filesystem.Tar(fs)->open(fname, "r");
67 }
68 
69 array get_directory(string dname)
70 {
71  return fsystem->get_dir(dname);
72 }
73 
74 void set_debug ( int debug )
75 {
76  debug_output = debug;
77 }
78 
79 int get_debug ()
80 {
81  return debug_output;
82 }
83 
84 /*****************************************************************************
85  * XML stuff
86  */
87 mapping xmlMap(NodeXML n)
88 {
89  mapping res = ([ ]);
90  if ( !objectp(n) )
91  return res;
92 
93  foreach ( n->children, NodeXML children) {
94  if ( children->name == "member" ) {
95  mixed key,value;
96  foreach(children->children, object o) {
97 
98  if ( o->name == "key" )
99  key = unserialize(o->children[0]);
100  else if ( o->name == "value" )
101  value = unserialize(o->children[0]);
102  }
103  res[key] = value;
104  }
105  }
106  return res;
107 }
108 
109 array xmlArray(NodeXML n)
110 {
111  array res = ({ });
112  foreach ( n->children, NodeXML children) {
113  res += ({ unserialize(children) });
114  }
115  return res;
116 }
117 
118 mixed unserialize(NodeXML n)
119 {
120  switch ( n->name ) {
121  case "struct":
122  return xmlMap(n);
123  break;
124  case "array":
125  return xmlArray(n);
126  break;
127  case "int":
128  return (int)n->data;
129  break;
130  case "float":
131  return (float)n->data;
132  break;
133  case "string":
134  return n->data;
135  break;
136  case "object":
137  string type = n->children[0]->data;
138  string id = n->children[1]->data;
139  object obj;
140  int oid;
141 
142  switch(type) {
143  case "Group":
144  oid = set_object(mVariables["groups"]);
145  break;
146  case "User":
147  oid = set_object(mVariables["users"]);
148  break;
149  case "Module":
150  oid = set_object(0);
151  obj = send_command(COAL_COMMAND, ({ "get_module", ({ id }) }));
152  set_object(oid);
153  return obj;
154  break;
155  default:
156 
157 
158  oid = set_object(mVariables["filepath:tree"]);
159  obj = send_command(COAL_COMMAND, ({ "path_to_object", ({ id }) }));
160  set_object(oid);
161  return obj;
162  break;
163  }
164 
165  obj = send_command(COAL_COMMAND, ({ "lookup", ({ id }) }));
166  set_object(oid);
167  return obj;
168  }
169  return 0;
170 }
171 
172 void save_xml(NodeXML n, object obj)
173 {
174  set_object(obj);
175  mapping attributes = xmlMap(n->get_node("/Object/attributes/struct"));
176  mapping a_acquire = xmlMap(n->get_node("/Object/attributes-acquire/struct"));
177  mapping sanction = xmlMap(n->get_node("/Object/sanction/struct"));
178  mapping msanction = xmlMap(n->get_node("/Object/sanction-meta/struct"));
179  mixed acquire = unserialize(n->get_node("/Object/acquire/*"));
180  mapping a_lock = xmlMap(n->get_node("/Object/attributes-locked/struct"));
181 
182 
183  foreach(indices(sanction), object sanc) {
184  if ( objectp(sanc) ) {
185  send_command(COAL_COMMAND, ({ "sanction_object",
186  ({ sanc, sanction[sanc] }) }) );
187  }
188  }
189  foreach(indices(msanction), object msanc) {
190  if ( objectp(msanc) ) {
191  send_command(COAL_COMMAND, ({ "sanction_object_meta",
192  ({ msanc, msanction[msanc] }) }) );
193  }
194  }
195  mixed key;
196 
197  send_command(COAL_COMMAND, ({ "unlock_attributes" }));
198  foreach(indices(a_acquire), key) {
199  if ( stringp(a_acquire[key]) ) // environment only, may not work *g*
200  send_command(COAL_COMMAND, ({ "set_acquire_attribute",
201  ({ key, 1 }) }));
202  else if ( !intp(a_acquire[key]) )
203  send_command(COAL_COMMAND, ({ "set_acquire_attribute",
204  ({ key, a_acquire[key] }) }));
205  }
206  send_command(COAL_COMMAND, ({ "set_attributes", ({ attributes }) }) );
207  foreach(indices(a_lock), key ) {
208  if ( a_lock[key] != 0 ) {
209  send_command(COAL_COMMAND, ({ "lock_attribute", ({ key }) }));
210  }
211  }
212 
213  // acquire string should be environment function, but thats default ...
214  // cannot handle functions yet
215  if ( objectp(acquire) || acquire == 0 )
216  send_command(COAL_COMMAND, ({ "set_acquire", ({ acquire }) }));
217 
218 }
219 
220 
221 void object_to_server(object obj)
222 {
223  string path = "xml";
224 
225  if ( obj->get_object_class() & CLASS_USER )
226  return;
227 
228 
229  if ( !objectp(_filepath) )
230  _filepath = send_cmd(0, "get_module", "filepath:tree");
231 
232  object pname = send_cmd(_filepath, "object_to_filename", obj);
233  path += pname;
234 
235  set_object(obj);
236 
237  werror("\r"+(" "*79));
238  werror("\rreading... " + path+".xml");
239  Stdio.File f;
240  mixed err = catch {
241  f = open_file(path+".xml", _fs);
242  };
243  // if the file does not exist its not part of the reference
244  // server installation
245  if ( !objectp(f) ) {
246 #if 0
247  werror("\r"+path+".xml ... file not found !\n");
248 #endif
249  return;
250  }
251  string xml = f->read();
252  f->close();
253  NodeXML n = parse_data(xml);
254  save_xml(n, obj);
255 }
256 
257 object upload_file(object dir, string fname, object f)
258 {
259  if ( search(fname, ".") == 0 || search(fname, "#") >= 0 ) {
260  return 0;
261  }
262  object obj = send_cmd(dir, "get_object_byname", fname);
263  if ( !objectp(obj) ) {
264  werror(" (Created)");
265  iInstall++;
266  obj = send_cmd(_docfactory, "execute", ([ "name": fname, ]));
267  send_cmd(obj, "move", dir);
268  }
269  else
270  iUpdate++;
271 
272 
273  send_cmd(obj, "set_content", f->read());
274  string filename=send_cmd(_filepath, "object_to_filename", obj);
275  mFiles[filename] = obj;
276  return obj;
277 }
278 
279 object create_folder(string inCont, string folderName)
280 {
281  return send_cmd(_filepath,"make_directory", ({ inCont, folderName }) );
282 }
283 
284 void upload_directory(object location, string dir, mapping vars)
285 {
286  object f, cont;
287 
288  if ( !objectp(location) )
289  error("Dont know where to install - location non-object !");
290  array files = fsystem->get_dir(dir);
291  if ( !arrayp(files) ) {
292  werror("Directory "+ dir + " is empty .. skipping...\n");
293  return 0;
294  }
295  string path = send_cmd(_filepath, "object_to_filename", location);
296  if ( !stringp(path) )
297  error("Path is not resolvable (no string)!");
298  if ( strlen(path) == 0 )
299  error("Path has zero length !");
300  cont = send_cmd(location, "get_object_byname", basename(dir));
301  if ( !objectp(cont) ) {
302  werror("\rFolder %s does not exist on server, creating...",
303  basename(dir));
304 #ifdef CHECK_ONLY
305  return;
306 #endif
307  cont = create_folder(path, basename(dir));
308  }
309  path = path + (path[-1] !='/' ?"/":"") + basename(dir);
310  mFiles[path] = cont;
311  werror("\r%s", " "*79); //clear the line
312  werror("\rDIRECTORY: %s", path);
313  array dirs = ({ });
314 
315  foreach( files, string fname ) {
316  if ( basename(fname)=="CVS" ||
317  search(fname, ".")==0 ||
318  search(fname, "#")>= 0 )
319  continue;
320 
321  if ( fsystem->stat(fname)->isdir() )
322  dirs += ({ fname });
323  else
324  {
325  werror("\r%s", " "*79); //clear the line
326  werror("\rUploading: (%s)/%s", path, basename(fname));
327  f = open_file(fname, vars->fs);
328 #ifndef CHECK_ONLY
329  upload_file(cont, basename(fname), f);
330 #endif
331  f->close();
332  }
333  }
334  foreach ( dirs, string dir_name ) {
335  upload_directory(cont, dir_name, vars);
336  }
337 }
338 
339 
340 void upload_package(mapping vars)
341 {
342 
343  object f;
344  write("Register package...\n");
345  _docfactory = send_cmd(0, "get_factory", CLASS_DOCUMENT);
346  if ( !objectp(_docfactory) )
347  throw(({"Document Factory not found in server !"}));
348  _contfactory = send_cmd(0, "get_factory", CLASS_CONTAINER);
349  if ( !objectp(_contfactory) )
350  throw( ({ "Container factory not found inside server !" }));
351  _filepath = send_cmd(0, "get_module", "filepath:tree");
352  if ( !objectp(_filepath) )
353  error("Unable to find filepath on server !");
354  object _rootroom = send_cmd(_filepath, "path_to_object", "/");
355  object dest = send_cmd(_filepath, "path_to_object", vars->dest);
356  if ( !objectp(dest) ) {
357  dest = send_cmd(_filepath, "make_directory",vars->dest);
358  }
359 
360 
361  array files = fsystem->get_dir("/files");
362  if ( !arrayp(files) || sizeof(files) == 0 ) {
363  files = fsystem->get_dir("files");
364  if ( !arrayp(files) || sizeof(files) == 0 ) {
365  werror("Invalid SPM Archive: Empty files/ Directory !\n");
366  return;
367  }
368  }
369  foreach( files, string fname ) {
370  if ( basename(fname) == "CVS" )
371  continue;
372 
373  object stat = fsystem->stat(fname);
374  if ( stat->isdir() ) {
375  upload_directory(dest, "/"+fname, vars);
376  }
377  else {
378  f = Filesystem.Tar(vars->fs)->open(fname,"r");
379  upload_file(dest, basename(fname), f);
380  f->close();
381  }
382  }
383  // now some script needs to be called on the server...
384  // they first have to be uploaded from the package/ directory
385  // and will be installed in the package/ directory of the
386  // server
387  array additional = ({ });
388  files = get_directory("/package");
389  object pdir = send_cmd(_rootroom, "get_object_byname", "packages");
390  if ( !objectp(pdir) ) {
391  werror("Creating Packages Folder !\n");
392  pdir = create_folder("/", "packages");
393  }
394 
395  object exe;
396  int isUpgrade = 0;
397 
398  foreach ( files, string package ) {
399  object file = Filesystem.Tar(vars->fs)->open(package,"r");
400  object o = upload_file(pdir, basename(package), file);
401  file->close();
402  exe = send_cmd(o, "get_instance");
403  if ( !objectp(exe) ) {
404  exe = send_cmd(o, "execute", ([ "name":vars->package,]));
405  if ( !objectp(exe) ) {
406  array errlist = o->get_errors();
407  werror("Failed to install package main component. Errors are:\n"+
408  (arrayp(errlist) ? (errlist * "\n") : "No errors can be found ?!")+"\n");
409  return;
410  }
411  send_cmd(exe, "move", pdir);
412  werror("\n\nSetting up " + package + "\n");
413  // return additional files
414  send_cmd(exe, "set_attribute", ({ "package:components", mFiles }));
415 
416  additional = send_cmd(exe, "spm_install_package");
417  }
418  else {
419  werror("\n\nFound previous package Version=" +
420  send_cmd(exe, "get_version") + "\n");
421  // upgrade!
422  isUpgrade = 1;
423  werror("Upgrading Installation...\n");
424  // return additional files
425  additional = send_cmd(exe, "spm_upgrade_package");
426  send_cmd(exe, "check_package_integrity");
427  }
428  // check if module is registered
429  werror("\nChecking Registration: "+ vars->package+"...");
430 
431  object reg = send_cmd(0, "get_module", vars->package);
432  if ( !objectp(reg) ) {
433  werror("registered.\n");
434  send_cmd(1, "register_module", ({ vars->package, exe }));
435  }
436  else
437  werror("found.\n");
438  }
439  if ( !objectp(exe) ) {
440  werror("Unable to find package main component !\nFILE DUMP=%O\n", files);
441  return;
442  }
443  if(arrayp(additional))
444  foreach(additional, object installed ) {
445  if ( !objectp(installed) ) {
446  werror("Error on Installation: Script failed to upgrade.\n");
447  continue;
448  }
449  string installedP = send_cmd(_filepath,"object_to_filename",installed);
450  mFiles[installedP] = installed;
451  werror("Installed Script = " + installedP + "\n");
452  }
453  if ( !isUpgrade ) {
454  werror("Reading XML Object Descriptions !\n");
455  // finally do the xml settings
456  foreach(indices(mFiles), string comp) {
457  object_to_server(mFiles[comp]);
458  }
459  // after loading all xml descriptions ...
460  foreach(indices(mFiles), string comp) {
461  if ( mFiles[comp]->get_object_class() & CLASS_DOCXSL &&
462  objectp(mFiles[comp+".xml"]) )
463  catch(send_cmd(mFiles[comp], "load_xml_structure"));
464  }
465 
466  }
467  else
468  werror("Skipping XML on UPGRADING\n");
469 
470  send_cmd(exe, "set_attribute", ({ "package:components", mFiles }));
471 }
472 
473 void configure_web()
474 {
475  werror("Configure Web Package!\n");
476  object _filepath = send_cmd(0, "get_module", "filepath:tree");
477  object web = send_cmd(_filepath, "path_to_object", "/packages/package:web");
478  mFiles = send_cmd(web, "query_attribute", "package:components");
479  foreach(indices(mFiles), string comp) {
480  object_to_server(mFiles[comp]);
481  }
482 }
483 
484 array list_packages(int|void quiet)
485 {
486  _filepath = send_cmd(0, "get_module", "filepath:tree");
487  object _packages = send_cmd(_filepath, "path_to_object",
488  "/home/admin/packages");
489  array packages = send_cmd(_packages, "get_inventory");
490  if ( quiet != 1 ) {
491  werror("List of Packages on sTeam server:\n");
492  foreach(packages, object pck) {
493  werror(" " + pck->get_identifier() + ":\t"+
494  send_cmd(pck, "query_attribute", OBJ_DESC)+"\n");
495  }
496  }
497  return packages;
498 }
499 
500 string get_package(string pck_name)
501 {
502  array packages = list_packages(1);
503  foreach ( packages, object pck )
504  if ( pck->get_identifier() == pck_name ) {
505  werror("Retrieving "+pck_name+"\n");
506  return send_cmd(pck, "get_content");
507  }
508  return 0;
509 }
510 
511 void set_fsystem(object fs, mapping vars)
512 {
513  iInstall = 0;
514  iUpdate = 0;
515  iError = 0;
516  fsystem = fs;
517  _fs = vars->fs;
518 }
519 
520 int start(string server, int port, string user, string pw)
521 {
522  int start_time = time();
523 
524  werror("Connecting to sTeam server...\n");
525  while ( !connect_server(server, port) ) {
526  if ( time() - start_time > 120 ) {
527  throw (({" Couldn't connect to server. Please check steam.log for details! \n", backtrace()}));
528  }
529  werror("Failed to connect... still trying ... (server running ?)\n");
530  sleep(10);
531  }
532 
533  mixed err = catch {
534  if ( !stringp(login(user, pw,CLIENT_STATUS_CONNECTED)))
535  throw("Wrong Password !");
536  };
537  if ( err != 0 ) {
538  werror("Error on installation: \n"+sprintf("%O", err));
539  throw(({"Wrong Password !", backtrace()}) );
540  return 0;
541  }
542  mVariables["filepath:tree"] = send_cmd(0, "get_module", "filepath:tree");
543  return 1;
544 }
545 
546 
547 
548 
549 
550 };