import._pike
Go to the documentation of this file.
1 /*0*/
2 inherit "../client/client_base";
3 inherit "base/xml_parser";
4 inherit "base/xml_data";
5 #include <coal.h>
6 #include <macros.h>
7 #include <classes.h>
8 #include <client.h>
9 #include <access.h>
10 class import : public client_base,xml_parser,xml_data{
11 public:
12 
13 
14 #define WARNING(s) werror(s)
15 #define MESSAGE(s, args...) werror(s+"\n", args);
16 
17  string sDirectory;
18  mapping mSwitches;
19  mapping mObjects;
20  array aObjects; // array of created objects
21 mapping mAttributes = ([ ]);
22 
23 Stdio.File creatorLog = Stdio.File("creators.log", "wct");
24 
25 mapping xmlMap(NodeXML n)
26 {
27  mapping res = ([ ]);
28  foreach ( n->children, NodeXML children) {
29  if ( children->name == "member" ) {
30  mixed key,value;
31  foreach(children->children, object o) {
32 
33  if ( o->name == "key" )
34  key = unserialize(o->children[0]);
35  else if ( o->name == "value" )
36  value = unserialize(o->children[0]);
37  }
38  res[key] = value;
39  }
40  }
41  return res;
42 }
43 
44 array xmlArray(NodeXML n)
45 {
46  array res = ({ });
47  foreach ( n->children, NodeXML children) {
48  res += ({ unserialize(children) });
49  }
50  return res;
51 }
52 
53 object create_object(string id, string path)
54 {
55  object obj;
56  Stdio.File f;
57 
58  MESSAGE("Creating object id="+id);
59 
60 
61  mixed err = catch {
62  f = Stdio.File(sDirectory + "/__objects__/"+id+"._xml_", "r");
63  };
64 
65  if ( err != 0 || !objectp(f) ) {
66  werror("Warning: Failed to find %s\n", id+".xml");
67  return 0;
68  }
69 
70 
71  string xml = f->read();
72  f->close();
73 
74  NodeXML n = parse_data(xml);
75  set_object(0);
76  int clnum = (int)n->get_node("/Object")->attributes["class"];
77  object factory = send_command(COAL_COMMAND, ({ "get_factory", ({
78  clnum }) }) );
79  set_object(factory);
80  object linkto = n->get_node("/Object/linkto");
81  mapping vars = ([ "name": "import", ]);
82  if ( objectp(linkto) ) {
83  object lt = mVariables["filepath:tree"]->path_to_object(linkto->data);
84  if ( clnum & CLASS_EXIT )
85  vars["exit_to"] = lt;
86  else
87  vars["link_to"] = lt;
88  }
89  obj = send_command(COAL_COMMAND, ({ "execute", ({ vars }) }) );
90  mObjects[id] = obj;
91  aObjects += ({ obj });
92 
93  err = catch {
94  f = Stdio.File(sDirectory + "/__objects__/"+id, "r");
95  if ( objectp(f) ) {
96  werror("Uploading Document");
97  send_cmd(obj, "set_content", ({ f->read() }) , 1);
98  f->close();
99  werror(".... finished.\n");
100  }
101  };
102  object_to_server(obj, path + "objects/"+id, n);
103 
104  return obj;
105 }
106 
107 void create_groups()
108 {
109  Stdio.File f;
110  mixed err = catch {
111  f = Stdio.File(sDirectory + "/groups/groups.xml", "r");
112  };
113  if ( err != 0 || !objectp(f) )
114  return;
115  NodeXML n = parse_data(f->read());
116  f->close();
117  foreach(n->get_node("/groups/array")->get_nodes("object"), NodeXML g) {
118  object grp;
119  string grp_name;
120 
121  MESSAGE("Group:" + g->get_node("id")->data);
122  grp_name = g->get_node("id")->data;
123  set_object(mVariables["groups"]);
124  grp = send_command(COAL_COMMAND, ({ "lookup", ({ grp_name }) }));
125  if ( !objectp(grp) ) {
126  MESSAGE("Creating: " + grp_name);
127  set_object(mVariables["Group.factory"]);
128  grp = send_command(COAL_COMMAND,
129  ({ "execute", ({([ "name": grp_name, ]) }) }) );
130  aObjects += ({ grp });
131  }
132  else {
133  MESSAGE("Skipping " + grp_name + " ... group exists !");
134  }
135 
136  }
137 }
138 
139 object create_group(string name, string|object parent)
140 {
141  object factory = mVariables["Group.factory"];
142  if ( stringp(parent) )
143  parent = mVariables->groups->lookup(parent);
144  werror("Creating group %s, parent=%O\n", name, parent);
145  object group = factory->execute( ([
146  "name": name,
147  "parentgroup": parent, ]) );
148  return group;
149 }
150 
151 object import_groups(string fname)
152 {
153  Stdio.File f;
154  mixed err = catch {
155  f = Stdio.File(fname, "r");
156  };
157  if ( err != 0 || !objectp(f) ) {
158  werror("Fatal: cannot read %s\n", fname);
159  return 0;
160  }
161  string str = f->read();
162  NodeXML n;
163  err = catch {
164  n = parse_data(str);
165  };
166  f->close();
167  object grp = n->get_node("/group");
168  string grpname = grp->attributes->name;
169  string identifier = grp->attributes->identifier;
170  werror("Looking up group %s\n", identifier);
171  object group = mVariables["groups"]->lookup(identifier);
172  array grps = identifier / ".";
173  string parent;
174  if ( sizeof(grps) > 2 ) {
175  parent = grps[..sizeof(grps)-2] * ".";
176  }
177  else
178  sscanf(identifier, "%s.%*s", parent);
179 
180  werror("Importing group " + grpname + " ... ");
181  if ( !objectp(group) ) {
182  group = create_group(grpname, parent);
183  werror("created!\n");
184  }
185  else
186  werror("found on server.\n");
187 
188  foreach(grp->get_nodes("member"), object m) {
189  object user = mVariables->users->lookup(m->data);
190  if ( objectp(user) ) {
191  group->add_member(user);
192  if ( mappingp(m->attributes) && m->attributes->admin )
193  group->sanction_object(user, SANCTION_INSERT|SANCTION_MOVE|SANCTION_WRITE);
194  }
195  }
196  string path = dirname(fname);
197  foreach(grp->get_nodes("subgroup"), object sg) {
198  object g = import_groups(path+"/__group_"+sg->data+"__.xml");
199  group->add_member(g);
200  }
201  if ( mSwitches->rooms ) {
202  object wr = group->query_attribute("GROUP_WORKROOM");
203  string wrname = wr->get_identifier();
204  werror("Checking for %s in %s ...", wrname, path);
205  if ( Stdio.exist(path + "/" + wrname) ) {
206  werror("yes.\n");
207  sDirectory = path;
208  container_to_server(wr, path+"/"+wrname, wrname);
209  }
210  else
211  werror("no.\n");
212  }
213  return group;
214 }
215 
216 void import_users(string fname)
217 {
218  Stdio.File f;
219  mixed err = catch {
220  f = Stdio.File(fname, "r");
221  };
222  if ( err != 0 || !objectp(f) )
223  return;
224  string str = f->read();
225  NodeXML n;
226  err = catch {
227  n = parse_data(str);
228  };
229  f->close();
230  string grp = n->get_node("/users")->attributes->group;
231  object group = send_cmd(mVariables->groups, "lookup", grp);
232 
233  foreach(n->get_nodes("/users/user"), object u) {
234  if ( u->get_node("nickname")->data == "0" )
235  continue;
236  mapping attr = ([ ]);
237  foreach(u->get_children(), object s) {
238  if ( stringp(s->data) && s->data != "0" )
239  attr[s->name] = s->data;
240  }
241  object user = send_cmd(mVariables["users"],"lookup", u->get_node("nickname")->data);
242  werror("Importing %s ... ", u->get_node("nickname")->data);
243  if ( !xml.utf8_check(lower_case(attr->nickname)) || search(attr->nickname, " ") >= 0 || !stringp(attr->pw)) {
244  werror(" name not utf-8....\n");
245  continue;
246  }
247  if ( !objectp(user) ) {
248  user = send_cmd(mVariables["User.factory"], "execute", attr);
249  werror("New User!\n");
250  }
251  else
252  werror("exists...\n");
253  send_cmd(user, "set_user_password", ({ attr["pw"], 1}) );
254  send_cmd(user, "activate_user");
255  if ( objectp(group) )
256  send_cmd(group, "add_member", user);
257  }
258 
259 }
260 
261 void create_users()
262 {
263  Stdio.File f;
264  mixed err = catch {
265  f = Stdio.File(sDirectory + "/groups/users.xml", "r");
266  };
267  if ( err != 0 || !objectp(f) )
268  return;
269  NodeXML n = parse_data(f->read());
270  f->close();
271  foreach(n->get_node("/users/array")->get_nodes("object"), NodeXML u) {
272  object user;
273  string user_name;
274 
275  MESSAGE("User:" + u->get_node("id")->data);
276  user_name = u->get_node("id")->data;
277  f = Stdio.File(sDirectory + "/groups/"+user_name+".xml", "r");
278  NodeXML user_n = parse_data(f->read());
279  f->close();
280 
281  set_object(mVariables["users"]);
282  user = send_command(COAL_COMMAND, ({ "lookup", ({ user_name }) }));
283  if ( !objectp(user) ) {
284  MESSAGE("Creating: " + user_name);
285  set_object(mVariables["User.factory"]);
286  user = send_command(COAL_COMMAND,
287  ({ "execute", ({([ "name": user_name,
288  "pw":user_n->get_node(
289  "/Object/password")->data,
290  ]) })}));
291  object_to_server(user, sDirectory + "/groups/"+user_name);
292  aObjects += ({ user });
293  }
294  else {
295  MESSAGE("Skipping " + user_name + " - user exists !");
296  }
297  }
298 }
299 
300 
301 mixed unserialize(NodeXML n)
302 {
303  switch ( n->name ) {
304  case "struct":
305  return xmlMap(n);
306  break;
307  case "array":
308  return xmlArray(n);
309  break;
310  case "int":
311  return (int)n->data;
312  break;
313  case "float":
314  return (float)n->data;
315  break;
316  case "string":
317  return n->data;
318  break;
319  case "object":
320  string type = n->children[0]->data;
321  string id = n->children[1]->data;
322  object obj;
323  int oid;
324 
325  switch(type) {
326  case "Group":
327  oid = set_object(mVariables["groups"]);
328  break;
329  case "User":
330  oid = set_object(mVariables["users"]);
331  break;
332  case "Module":
333  oid = set_object(0); // set the object to _Server
334  obj = send_command(COAL_COMMAND, ({ "get_module", ({ id }) }));
335  if ( !objectp(obj) )
336  WARNING("Failed to find module " +id + " on target server !");
337  set_object(oid);
338  return obj;
339  break;
340  case "ID":
341  if ( objectp(mObjects[id]) )
342  return mObjects[id];
343  return create_object(id, sDirectory+"/objects");
344  break;
345  default:
346  oid = set_object(mVariables["filepath:tree"]);
347  obj = send_command(COAL_COMMAND, ({ "path_to_object", ({ id }) }));
348  if ( !objectp(obj) )
349  WARNING("Failed to find path " +id + " on target server !\n");
350  set_object(oid);
351  return obj;
352  break;
353  }
354  obj = send_command(COAL_COMMAND, ({ "lookup", ({ id }) }));
355 
356  set_object(oid);
357  return obj;
358  }
359  return 0;
360 }
361 
362 array read_meta(string path)
363 {
364  Stdio.File f = Stdio.File(path + "/__steam__.xml", "r");
365  string meta = f->read();
366  f->close();
367  NodeXML n = parse_data(meta);
368  n = n->get_node("/folder/files");
369  array nodes = n->get_nodes("file");
370  array res = ({ });
371  foreach(nodes, object node) {
372  res += ({ node->get_data() });
373  }
374  return res;
375 }
376 
377 void container_to_server(object obj, string directory, string path)
378 {
379  object o;
380  if ( obj->get_object_class() & CLASS_USER )
381  return;
382  array dir = get_dir(directory);
383  dir = read_meta(directory);
384  foreach(dir, string fname) {
385  if ( fname == "xml" || fname == "files" ) continue;
386  fname = utf8_to_string(fname);
387  NodeXML n;
388  Stdio.File f;
389  mixed err = catch {
390  f = Stdio.File(sDirectory + "/" +path + "/" + fname+"._xml_","r");
391  if ( !objectp(f) )
392  f = Stdio.File(sDirectory + "/" +path + "/" + fname+".xml","r");
393  };
394  if ( arrayp(err) ) {
395  werror("Failed to load file %s\n%O\n", fname, err);
396  }
397  // if the file does not exist its not part of the reference
398  // server installation
399  if ( !objectp(f) )
400  continue;
401 
402  string xml = f->read();
403  f->close();
404 
405  n = parse_data(xml);
406 
407 
408  // is that object already on the server ?
409  o = send_cmd(obj, "get_object_byname", string_to_utf8(fname));
410 
411  if ( Stdio.is_dir(directory + "/" + fname) ) {
412  werror("- Directory:"+fname+":");
413 
414  int cl = (int)n->attributes["class"];
415 
416  if ( !objectp(o) ) {
417  if ( mSwitches->test ) {
418  werror("Missing: " + fname + "\n");
419  continue;
420  }
421  werror("Creating container/room: " + fname+"\n");
422 
423  set_object(send_cmd(0, "get_factory", cl));
424  o = send_command(COAL_COMMAND, ({ "execute", ({
425  ([ "name": string_to_utf8(fname), ]) }) }));
426  aObjects += ({ o });
427  send_cmd(o, "move", obj, 1);
428  object_to_server(o, sDirectory + path +"/"+ fname, n);
429  }
430  container_to_server(o, directory + "/"+ fname, path +"/"+fname);
431  }
432  else if ( !Stdio.exist(directory + "/" + fname) ) {
433  // no document
434  int classid = (int)(n->get_node("/Object")->attributes->class);
435  werror("Object class = %d\n", classid);
436  object factory = send_cmd(0, "get_factory", classid);
437  if ( classid & 256 )
438  o = send_cmd(factory, "execute", ([ "name":string_to_utf8(fname), "url":"http://www.dummy.de",]));
439  else
440  o = send_cmd(factory, "execute", ([ "name":string_to_utf8(fname), ]));
441 
442  send_cmd(o, "move", obj);
443  object_to_server(o, sDirectory+path+"/"+fname, n);
444  }
445  else {
446  f = Stdio.File(directory + "/" + fname, "r");
447  werror("- File:"+fname+":");
448  if ( !objectp(o) ) {
449  if ( mSwitches->test ) {
450  werror("Missing!!!\n");
451  continue;
452  }
453  o = send_cmd(mVariables["Document.factory"], "execute",
454  ([
455  "name": string_to_utf8(fname),
456  "move":obj, ]) );
457  send_cmd(o, "move", obj);
458  if ( !objectp(o) ) {
459  werror("Failed to create document !");
460  continue;
461  }
462  aObjects += ({ o });
463  object_to_server(o, sDirectory + path +"/"+ fname, n);
464  }
465  if ( !mSwitches->test ) {
466  send_cmd(o, "set_content", ({ f->read() }), 1);
467  if ( mSwitches->update ) {
468  object_to_server(o, sDirectory + path + "/" + fname, n);
469  }
470  }
471  else {
472  werror(" found. Skipping upload.\n");
473  }
474  f->close();
475  }
476  }
477 }
478 
479 object annotation_to_server(NodeXML ann, string path)
480 {
481  return create_object(ann->get_node("id")->data, path);
482 }
483 
484 
485 int handle_error(mixed err)
486 {
487  return 0;
488 }
489 
490 void object_to_server(object obj, string path, NodeXML|void n)
491 {
492  MESSAGE("reading... " + path+".xml");
493  set_object(obj);
494  if ( !objectp(n) ) {
495  Stdio.File f;
496  mixed err = catch {
497  f = Stdio.File(path + ".xml", "r");
498  };
499  // if the file does not exist its not part of the reference
500  // server installation
501  if ( !objectp(f) ) {
502  werror("Not found !\n");
503  return;
504  }
505  string xml = f->read();
506  f->close();
507  n = parse_data(xml);
508  }
509  mapping attributes = xmlMap(n->get_node("/Object/attributes/struct"));
510  mapping a_acquire = xmlMap(
511  n->get_node("/Object/attributes-acquire/struct"));
512  mapping sanction = xmlMap(n->get_node("/Object/sanction/struct"));
513  mapping msanction = xmlMap(n->get_node("/Object/sanction-meta/struct"));
514  mixed acquire = unserialize(n->get_node("/Object/acquire")->children[0]);
515  mapping a_lock = xmlMap(n->get_node("/Object/attributes-locked/struct"));
516 
517 
518  if ( obj->get_object_class() & CLASS_USER ) {
519  array groups =
520  unserialize(n->get_node("/Object/groups/array"));
521  foreach(groups, object grp) {
522  send_cmd(grp, "add_member", obj, 1);
523  }
524  }
525  if ( obj->get_object_class() & CLASS_LINK && objectp(n->get_node("/Object/linkto")) )
526  {
527  string link = n->get_node("/Object/linkto")->data;
528 
529  if ( stringp(link) ) {
530  object lnk = mVariables["filepath:tree"]->path_to_object(link);
531  if ( objectp(lnk) )
532  obj->set_link_object(lnk);
533  else
534  werror("Cannot resolve the link %s\n", link);
535  }
536  else
537  werror("Link not found %O\n", n->get_node("/Object/linkto"));
538  }
539  foreach(indices(sanction), object sanc) {
540  if ( objectp(sanc) ) {
541  send_cmd(obj, "sanction_object", ({ sanc, sanction[sanc] }), 1 );
542  }
543  }
544  foreach(indices(msanction), object msanc) {
545  if ( objectp(msanc) ) {
546  send_cmd(obj, "sanction_object_meta", ({ sanction[msanc] }), 1);
547  }
548  }
549  mixed key;
550 
551 
552 
553  send_cmd(obj, "unlock_attributes", ({ }), 1);
554  foreach(indices(a_acquire), key) {
555  if ( stringp(a_acquire[key]) ) // environment only, may not work *g*
556  send_cmd(obj, "set_acquire_attribute", ({ key, 1 }), 1);
557  else
558  send_cmd(obj, "set_acquire_attribute", ({ key, a_acquire[key]}),1);
559  }
560  foreach(indices(attributes), string key) {
561  send_cmd(obj, "set_attribute", ({ key, attributes[key] }), 1);
562  }
563  //send_cmd(obj, "set_attributes", attributes, 1);
564  foreach(indices(a_lock), key ) {
565  if ( a_lock[key] != 0 ) {
566  send_cmd(obj, "lock_attribute", ({ key }), 1);
567  }
568  }
569 
570  // acquire string should be environment function, but is default setting...
571  // cannot handle functions yet
572  if ( objectp(acquire) )
573  send_cmd(obj, "set_acquire", ({ acquire }), 1);
574  mixed creator = unserialize(n->get_node("/Object/creator/object"));
575  send_cmd(obj, "set_creator",({ creator }), 1);
576  if ( objectp(creator) )
577  creatorLog->write(obj->get_object_id() + ", creator="+creator->get_identifier()+"\n");
578  NodeXML annotations = n->get_node("/Object/annotations/array");
579  if ( objectp(annotations) ) {
580  array anns = send_cmd(obj, "get_annotations", ({ }), 1);
581  // if the object already has annotations remove them !
582  if ( arrayp(anns) ) {
583  foreach(anns, object a) {
584  send_cmd(obj, "remove_annotation", a, 1);
585  }
586  }
587  werror("%d Annotations....\n", sizeof(annotations->children));
588  foreach(annotations->children, NodeXML ann) {
589  object annotation = annotation_to_server(ann, dirname(path));
590  send_cmd(obj, "add_annotation", ({ annotation }), 1);
591  }
592  }
593  foreach(indices(mAttributes), string idx) {
594 
595  send_cmd(obj, "set_attribute", ({ idx, mAttributes[idx] }), 1);
596  }
597 }
598 
599 int _import(string server, int port, string directory, string outPath)
600 {
601  if ( connect_server(server, port) ) {
602  string user = "root";
603  string pw = "steam";
604 
605  int t = time();
606 
607  Stdio.Readline rl = Stdio.Readline();
608  string iuser = rl->read("User ? ["+ user + "]: ");
609  string ipw = rl->read("Password ? ["+pw+"]: ");
610  if ( iuser != "" ) user = iuser;
611  if ( ipw != "" ) pw = ipw;
612  if ( !login(user, pw, CLIENT_STATUS_CONNECTED) ) {
613  error("Wrong User or Password !\n");
614  }
615  // now get the inventory from the root room
616  if ( mSwitches->users ) {
617  import_users(mSwitches->users);
618  return 1;
619  }
620  if ( mSwitches->group ) {
621  import_groups(mSwitches->group);
622  return 1;
623  }
624 
625  if ( search(mSwitches->create, "groups") >= 0 )
626  create_groups();
627  if ( search(mSwitches->create, "users") >= 0 )
628  create_users();
629  if ( search(mSwitches->create, "objects") >= 0 ) {
630  object start = mVariables["rootroom"];
631 
632  if ( (int)directory > 0 ) {
633  int dir = (int)directory;
634  start = send_cmd(0, "find_object", dir);
635  MESSAGE("Starting with %O", start);
636  }
637  else if ( directory != "/" ) {
638  int oid = set_object(mVariables["filepath:tree"]);
639  if ( (int)outPath > 0 )
640  start = send_cmd((int)outPath, "this");
641  else
642  start = send_command(COAL_COMMAND, ({ "path_to_object",
643  ({ outPath }), }));
644  MESSAGE("Starting with %O", start);
645  }
646  container_to_server(start, directory, "");
647  }
648  // file of objects that are created during installation
649  Stdio.File f = Stdio.File("install.xml", "wct");
650  f->write(compose(aObjects));
651  f->close();
652  werror("\n-- finished: Import created " + sizeof(aObjects) +
653  " new objects on server in " + (time()-t) + " seconds !\n");
654  } else
655  werror("Cannot connect to server !\n");
656  return 0;
657 }
658 
659 
660 int main(int argc, array argv)
661 {
662  int port = 1900;
663  string server= "localhost";
664  string directory = "/";
665  int iDepth;
666  string outPath = "";
667  mObjects = ([ ]);
668  aObjects = ({ });
669  mSwitches = ([ "create": "users,groups,objects", ]);
670 
671  for ( int i = 1; i < sizeof(argv); i++ ) {
672  string cmd, arg;
673 
674  if ( sscanf(argv[i], "--%s=%s", cmd, arg) >= 1 ) {
675  switch ( cmd ) {
676  case "server":
677  server = arg;
678  break;
679  case "port":
680  port = (int) arg;
681  break;
682  case "in":
683  directory = arg;
684  break;
685  case "depth":
686  iDepth = (int)arg;
687  break;
688  case "users":
689  mSwitches["users"] = arg;
690  break;
691  case "group":
692  mSwitches["group"] = arg;
693  break;
694  case "rooms":
695  mSwitches["rooms"] = true;
696  break;
697  case "out":
698  outPath = arg;
699  break;
700  case "test":
701  mSwitches["test"] = true;
702  break;
703  case "update":
704  mSwitches["update"] = true;
705  default:
706  break;
707  }
708  }
709  }
710 
711  //subpath is another switch
712  sDirectory = directory;
713  _import(server, port, directory, outPath);
714 }
715 
716 
717 
718 };