export._pike
Go to the documentation of this file.
1 /*0*/
2 inherit "../client/client_base";
3 inherit "base/xml_data";
4 #include <coal.h>
5 #include <macros.h>
6 #include <classes.h>
7 #include <client.h>
8 class export : public client_base,xml_data{
9 public:
10 
11 import xml;
12 
13 
14  int iDepth;
15  string outPath;
16  int withAnn;
17 
18  mapping mUsers, mGroups, mObjects, mExclude;
19 
20 mapping mSwitches = ([]);
21 
22 void handle_error(mixed err)
23 {
24  Stdio.append_file("export_errors.log", sprintf("-------\n%s%O\n", ctime(time()), err));
25 }
26 
27 string compose_scalar(mixed s)
28 {
29  if ( objectp(s) ) {
30  string type, name;
31  if ( s->get_object_class() & CLASS_USER ) {
32  type = "User";
33  name = s->get_identifier();
34  mUsers[s] = 1;
35  }
36  else if ( s->get_object_class() & CLASS_GROUP ) {
37  type = "Group";
38  name = s->get_identifier();
39  mGroups[s] = 1;
40  }
41  else if ( s->get_object_class() & CLASS_MODULE ) {
42  type = "Module";
43  name = s->get_identifier();
44  }
45  else {
46  type = "Path";
47 
48  int oid = set_object(s);
49  object env = send_cmd(s, "get_environment");
50  if ( !objectp(env) ) {
51  mObjects[s] = 1;
52  return "<object><type>ID</type><id>"+s->get_object_id() +
53  "</id></object>\n";
54  }
55  name = send_cmd(mVariables["filepath:tree"], "object_to_filename",
56  ({ s }));
57  }
58  return "<object><type>"+type+"</type><id><![CDATA["+name+"]]></id></object>";
59  }
60  else
61  return ::compose_scalar(s);
62 }
63 
64 void update_content(object obj, string path)
65 {
66  if ( Stdio.exist(path) )
67  return;
68  string content = send_cmd(obj, "get_content", ({ }));
69 
70  if ( !stringp(content) )
71  return;
72  // create the directory structure !
73  string dir;
74 
75  array tokens = (path/"/");
76  dir = tokens[..sizeof(tokens)-2]*"/";
77  Stdio.mkdirhier(dir);
78 
79  Stdio.File f = Stdio.File(path, "wct");
80  f->write(content);
81  f->close();
82 }
83 
84 void obj_from_server(object obj, string path)
85 {
86  Stdio.File xml = Stdio.File(path + "._xml_", "wct");
87 
88  set_object(obj);
89 
90  xml->write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"+
91  "<Object class=\""+
92  obj->get_object_class()+"\">\n");
93 
94  mapping attributes = send_cmd(obj, "query_attributes");
95  foreach(indices(attributes), string|int a) {
96  if ( !stringp(attributes[a]) )
97  continue;
98  if ( !utf8_check(attributes[a]) )
99  attributes[a] = string_to_utf8(attributes[a]);
100  }
101  xml->write("<attributes>\n"+compose_struct(attributes)+ "</attributes>\n");
102  mapping acquire_map = send_cmd(obj, "get_acquired_attributes");
103  xml->write("<attributes-acquire>\n"+
104  compose_struct(acquire_map) + "\n</attributes-acquire>\n");
105  mapping a_lock = ([ ]);
106  foreach(indices(attributes), mixed idx) {
107  a_lock[idx] = send_cmd(obj, "is_locked", ({ idx }) );
108 
109  }
110  xml->write("<attributes-locked>\n"+
111  compose_struct(a_lock) + "\n</attributes-locked>\n");
112 
113  mapping sanction = send_cmd(obj, "get_sanction" );
114  mapping msanction = send_cmd(obj, "get_meta_sanction" );
115 
116  if ( withAnn && !(obj->get_object_class() & CLASS_USER) ) {
117  array annotations = send_cmd(obj, "get_annotations");
118  xml->write("<annotations>"+compose(annotations) + "</annotations>\n");
119  foreach(annotations, object ann)
120  annotation_from_server(ann);
121  }
122  if ( obj->get_object_class() & CLASS_USER ) {
123  array groups = send_cmd(obj, "get_groups");
124  xml->write("<groups>"+compose_array(groups) + "</groups>\n");
125  string pw = send_cmd(obj, "get_user_password");
126  xml->write("<password>"+pw +"</password>\n");
127  }
128  if ( obj->get_object_class() & CLASS_LINK && objectp(obj->get_link_object()))
129  xml->write("<linkto>"+mVariables["filepath:tree"]->object_to_filename(obj->get_link_object()) + "</linkto>\n");
130 
131  xml->write("<sanction>\n"+compose_struct(sanction) + "</sanction>\n");
132  xml->write("<sanction-meta>\n"+compose_struct(msanction)+
133  "</sanction-meta>\n");
134  xml->write("<acquire>\n"+compose(send_cmd(obj, "get_acquire"))+
135  "</acquire>\n");
136  object creator = send_cmd(obj, "get_creator");
137  xml->write("<creator>"+compose(creator)+"</creator>\n");
138  xml->write("</Object>\n");
139  xml->close();
140 }
141 
142 void annotation_from_server(object ann)
143 {
144  werror("Checking out " + ann->get_identifier() +"["+ann->get_object_id()+
145  "]\n");
146  string path = outPath + "/__objects__";
147  Stdio.mkdirhier(path);
148  obj_from_server(ann, path + "/" + ann->get_object_id());
149  update_content(ann, path + "/" + ann->get_object_id());
150 }
151 
152 private:
153 void store_meta(object obj, string subpath, array inventory)
154 {
155  Stdio.mkdirhier(outPath + subpath);
156 
157  Stdio.File xml = Stdio.File(outPath + subpath + "/__steam__.xml", "wct");
158  xml->write("<?xml version='1.0' encoding='utf-8'?>\n"+
159  "<folder name='"+string_to_utf8(subpath)+"'>\n"+
160  " <server>\n"+
161  " <adress>"+mSwitches->server+"</adress>\n"+
162  " <port>"+mSwitches->port+"</port>\n"+
163  " <checkout>"+mSwitches->checkout + "</checkout>\n"+
164  " </server>\n\n");
165  xml->write(" <files>\n");
166  foreach(inventory, object o ) {
167  if ( !objectp(o) )
168  continue;
169  string id = o->get_identifier();
170  if ( !stringp(id) )
171  continue;
172  id = replace(id, "&", "und");
173  if ( o->get_object_class() & CLASS_DRAWING )
174  id = "_"+o->get_object_id()+"_";
175  xml->write(" <file>" + id + "</file>\n");
176  }
177  xml->write(" </files>\n</folder>");
178 
179 }
180 
181 public:
182 
183 string readable_filename(string fname)
184 {
185  if ( !stringp(fname) )
186  return "__unknown__";
187  fname = replace(fname, ({ "&"}), ({ "und"}));
188  return utf8_to_string(fname);
189 }
190 
191 void object_from_server(object obj, string subpath, int|void d)
192 {
193  if ( !objectp(obj) )
194  return;
195  if ( obj->get_object_class() & CLASS_USER || obj->get_object_class() & CLASS_SCRIPT )
196  return;
197 
198  if ( mExclude[subpath] == 1 ) {
199  return;
200  }
201 
202  string path = send_cmd(mVariables["filepath:tree"],
203  "object_to_filename", ({ obj }));
204  string id = send_cmd(obj, "get_identifier");
205 
206  id = readable_filename(id);
207  if ( obj->get_object_class() & CLASS_DOCUMENT )
208  update_content(obj, outPath + subpath + "/" + id);
209  else if ( obj->get_object_class() & CLASS_DRAWING )
210  id = "_"+obj->get_object_id()+"_";
211 
212  path = outPath + subpath + "/" + id;
213 
214  // create the directory structure !
215  string dir;
216  array tokens = (path/"/");
217  dir = tokens[..sizeof(tokens)-2]*"/";
218  Stdio.mkdirhier(dir);
219 
220  werror("Checking out " + path);
221  // now write xml for the object
222  obj_from_server(obj, path);
223  werror("... ok\n");
224  array inv;
225 
226  if ( obj->get_object_class() & CLASS_CONTAINER && (iDepth==0 || d < iDepth))
227  {
228  inv = send_cmd(obj, "get_inventory");
229  foreach(inv, object o)
230  object_from_server(o, subpath + "/" + readable_filename(obj->get_identifier()), d+1);
231  }
232  if ( arrayp(inv) && sizeof(inv) > 0 )
233  store_meta(obj, subpath + "/" + readable_filename(obj->get_identifier()), inv);
234 
235 }
236 
237 string group_to_string(object grp)
238 {
239  return grp->get_identifier();
240 }
241 
242 private:
243 void store_group(string group)
244 {
245  object grp;
246  if ( (int)group > 0 ) {
247  grp = send_cmd((int)group, "this");
248  group = grp->get_identifier();
249  }
250  else
251  grp = send_cmd(mVariables["groups"], "lookup", group);
252  array users = send_cmd(grp, "get_members");
253  do_store_groups(users, grp, group);
254 }
255 
256 public:
257 
258 private:
259 void do_store_groups(array groups, object grp, string group)
260 {
261 
262  Stdio.File f;
263  Stdio.mkdirhier(outPath);
264  werror("Exporting Group %s\n", group);
265  f = Stdio.File(outPath+"/__group_"+group+"__.xml", "wct");
266  f->write("<?xml version='1.0' encoding='utf-8'?>\n");
267  f->write("<group identifier=\""+group+"\" name=\""+
268  grp->query_attribute("OBJ_NAME")+"\">\n");
269  foreach(groups, object g) {
270  if ( !objectp(g) )
271  continue;
272  if ( g->get_object_class() & CLASS_GROUP ) {
273  f->write(" <subgroup name=\""+g->query_attribute("OBJ_NAME")+"\">"+
274  g->get_identifier()+ "</subgroup>\n");
275  }
276  else if ( grp->is_admin(g) )
277  f->write(" <member admin='true'>"+g->get_identifier()+ "</member>\n");
278  else
279  f->write(" <member>"+g->get_identifier()+ "</member>\n");
280  }
281  f->write("</group>\n");
282  f->close();
283  foreach(groups, object grp)
284  if ( grp->get_object_class() & CLASS_GROUP )
285  do_store_groups(grp->get_members(), grp, grp->get_identifier());
286 }
287 
288 public:
289 
290 private:
291 void store_users(string group)
292 {
293  object grp = send_cmd(mVariables["groups"], "lookup", group);
294  array users = send_cmd(grp, "get_members");
295  do_store_users(users, group);
296 }
297 
298 public:
299 
300 private:
301 void do_store_users(array users, void|string group)
302 {
303  Stdio.File f;
304 
305  if ( !stringp(group) )
306  group = "steam";
307 
308  Stdio.mkdirhier(outPath);
309  werror("writing %s\n", outPath+"/__users__.xml");
310  f = Stdio.File(outPath+"/__users__.xml", "wct");
311  f->write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
312  f->write("<users group='"+group+"'>\n");
313  foreach(users, object u) {
314  mapping attr;
315  if ( !objectp(u) )
316  continue;
317  object user = u;
318  if ( u->get_object_class() & CLASS_GROUP )
319  continue;
320 
321  attr = send_cmd(user, "query_attributes",
322 #if 1
323  ([
324  "OBJ_NAME":1,
325  "USER_FIRSTNAME":1,
326  "USER_FULLNAME":1,
327  "USER_EMAIL":1,
328  "OBJ_DESC":1,
329  "USER_ADRESS": 1,
330  ])
331  );
332 #else
333  ([
334  102: 1,
335  612:1,
336  616:1,
337  104:1,
338  611: 1,
339  ])
340  );
341  attr["OBJ_NAME"] = attr[102];
342  attr["USER_EMAIL"] = attr[616];
343  attr["USER_FULLNAME"] = string_to_utf8(attr[612]);
344  attr["OBJ_DESC"] = attr[104] || "";
345  attr["OBJ_DESC"] = string_to_utf8(attr->OBJ_DESC);
346  attr["USER_FISTNAME"] = "";
347 #endif
348 
349  string pw = send_cmd(user, "get_user_password");
350  array groups = send_cmd(user, "get_groups");
351  f->write(" <user>\n"+
352  " <nickname>"+attr->OBJ_NAME+"</nickname>\n"+
353  " <firstname>"+attr->USER_FIRSTNAME+"</firstname>\n"+
354  " <fullname>"+attr->USER_FULLNAME+"</fullname>\n"+
355  " <pw>"+pw+"</pw>\n"+
356  " <email>"+attr->USER_EMAIL+"</email>\n"+
357  " <description>"+attr->OBJ_DESC+"</description>\n"+
358  " <contact>"+attr->USER_ADRESS+"</contact>\n");
359  foreach(groups, object grp)
360  if ( objectp(grp) )
361  f->write(" <group>"+grp->get_identifier()+"</group>\n");
362 
363  f->write(" </user>\n");
364  }
365 
366  f->write("</users>\n");
367  f->close();
368 }
369 
370 public:
371 
372 private:
373 void store_users_and_groups()
374 {
375  Stdio.File f;
376  string path;
377  path = outPath + "/__groups__/";
378 
379  Stdio.mkdirhier(path);
380 
381  f = Stdio.File(path+"users.xml", "wct");
382  f->write("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<users>\n");
383  f->write(compose(indices(mUsers)));
384  f->write("</users>\n");
385  f->close();
386  foreach(indices(mUsers), object u) {
387  obj_from_server(u, path + u->get_identifier());
388  }
389  f = Stdio.File(path+"groups.xml", "wct");
390  f->write("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<groups>\n");
391  f->write(compose(indices(mGroups)));
392  f->write("</groups>\n");
393  f->close();
394  foreach(indices(mGroups), object g) {
395  obj_from_server(g, path + g->get_identifier());
396  }
397 }
398 
399 public:
400 
401 private:
402 void store_objects()
403 {
404  string path;
405 
406  path = outPath + "/__objects__/";
407  Stdio.mkdirhier(path);
408 
409  foreach(indices(mObjects), object o) {
410  set_object(o);
411  if ( o->get_object_class() & CLASS_DOCUMENT )
412  update_content(o, path + o->get_object_id());
413  obj_from_server(o, path + o->get_object_id());
414  }
415 }
416 
417 public:
418 
419 array get_all_rooms(array groups)
420 {
421  array rooms = ({ });
422  foreach(groups, object member) {
423  if ( member->get_object_class() & CLASS_GROUP ) {
424  rooms += ({ send_cmd(member, "query_attribute", "GROUP_WORKROOM") });
425  rooms += get_all_rooms(member->get_members());
426  }
427  }
428  return rooms;
429 }
430 
431 array get_all_users(object grp)
432 {
433  array users = ({ });
434  array u = send_cmd(grp, "get_members");
435  foreach(u, object user) {
436  if ( user->get_object_class() & CLASS_USER )
437  users += ({ user });
438  else if ( user->get_object_class() & CLASS_GROUP )
439  users += get_all_users(user);
440  }
441  return users;
442 }
443 
444 void room_from_server(object start, void|string pos)
445 {
446  if ( !stringp(pos) )
447  pos = "";
448  array inv = send_cmd(start, "get_inventory");
449  werror("room_from_server, %O\n", start);
450  foreach(inv, object o)
451  object_from_server(o, pos, 0);
452  store_meta(start, pos, inv);
453 }
454 
455 int main(int argc, array argv)
456 {
457  int port = 1900;
458  string server= "localhost";
459  string directory = "/";
460 
461  string user = "root";
462  string pw = "steam";
463  int i;
464 
465 
466  mUsers = ([ ]);
467  mGroups = ([ ]);
468  mObjects = ([ ]);
469  mExclude = ([ ]);
470 
471  outPath = "export";
472  withAnn = 0;
473 
474  if ( search(argv, "--help") >= 0 ) {
475  werror("sTeam export tool. Options are:\n"+
476  "--server= specify the server.\n"+
477  "--port= server port (COAL).\n"+
478  "--in=Directory to export from on server.\n"+
479  "--out=Directory to store the exported files.\n"+
480  "--depth=How many levels of containers/rooms should be exported?\n");
481  return 0;
482  }
483 
484  for ( i = 1; i < sizeof(argv); i++ ) {
485  string cmd, arg;
486  if ( sscanf(argv[i], "--%s=%s", cmd, arg) == 2 ||
487  sscanf(argv[i], "--%s", cmd) == 1 )
488  {
489  if ( stringp(arg) && strlen(arg) > 0 )
490  sscanf(arg, "\"%s\"", arg);
491 
492  switch ( cmd ) {
493  case "server":
494  server = arg;
495  break;
496  case "port":
497  port = (int) arg;
498  break;
499  case "in":
500  directory = arg;
501  break;
502  case "depth":
503  iDepth = (int)arg;
504  break;
505  case "user": // checkout user of group
506  mSwitches->user = arg;
507  break;
508  case "group": // checkout user of group
509  mSwitches->group = arg;
510  break;
511  case "out":
512  outPath = arg;
513  break;
514  case "exclude":
515  mExclude[arg] = 1;
516  break;
517  case "with-annotations":
518  withAnn = 1;
519  break;
520  case "help":
521  write("Usage is export "+
522  "--in=<server-path> --out=<export-path>\n");
523  break;
524  default:
525  werror(sprintf("Unknown parameter %s\n", argv[i]));
526  break;
527  }
528  }
529  }
530  werror("Connecting "+server+":"+port+"\n");
531  if ( connect_server(server, port) ) {
532  if ( outPath[-1] == '/' )
533  outPath = outPath[..strlen(outPath)-2];
534 
535  Stdio.mkdirhier(outPath);
536  werror("Exporting to " + outPath + "\n");
537 
538  mSwitches->server = server;
539  mSwitches->port = port;
540  mSwitches->checkout = directory;
541 
542 
543 
544  Stdio.Readline rl = Stdio.Readline();
545  string iuser = rl->read("User ? ["+ user + "]: ");
546  string ipw = rl->read("Password ? ["+pw+"]: ");
547  if ( iuser != "" ) user = iuser;
548  if ( ipw != "" ) pw = ipw;
549 
550 
551  login(user, pw, CLIENT_STATUS_CONNECTED, "ftp");
552  // now get the inventory from the root room
553 
554  if ( mSwitches->user ) {
555  store_users(mSwitches->user );
556  return 0;
557  }
558  if ( mSwitches->group ) {
559  store_group(mSwitches->group);
560  return 0;
561  }
562 
563  object start = mVariables["rootroom"];
564  object group = send_cmd(mVariables["groups"], "lookup", directory);
565  if ( (int)directory > 0 ) {
566  int dir = (int)directory;
567  set_object(dir);
568  start = send_cmd(dir, "this");
569  }
570  else if ( directory == "all" ) {
571  start = mVariables["groups"];
572  }
573  else if ( directory == "all" ) {
574  start = mVariables["groups"];
575  }
576  else if ( objectp(group) )
577  start = group;
578  else if ( directory != "/" ) {
579  int oid = set_object(mVariables["filepath:tree"]);
580  start = send_command(COAL_COMMAND, ({ "path_to_object",
581  ({ directory }), }));
582  }
583  array excludes = indices(mExclude);
584  foreach(excludes, string ex) {
585  mExclude["/"+start->get_identifier() + "/" + ex] = 1;
586  werror("Excluding directory:"+ex + "\n");
587  m_delete(mExclude, ex);
588  }
589  if ( !objectp(start) ) {
590  werror("Start Directory not found !");
591  return 1;
592  }
593  if ( directory == "all" ) {
594  array members = send_cmd(start, "get_groups");
595  array rooms = ({ });
596  mapping workrooms = ([ ]);
597 
598  foreach(members, object member) {
599  object grp_wr = send_cmd(member, "query_attribute", "GROUP_WORKROOM");
600  if ( objectp(grp_wr) )
601  rooms += ({ grp_wr });
602  }
603  object steam = send_cmd(start, "lookup", "steam");
604  array users = send_cmd(steam, "get_members");
605  do_store_users(users);
606  foreach(rooms, object room) {
607  workrooms[send_cmd(room, "get_creator")] = room;
608  room_from_server(room, "/"+room->get_identifier());
609  Stdio.File f = Stdio.File(outPath+"/__steam__.xml", "wct");
610  f->write("<?xml version='1.0' encoding='utf-8'?>\n<groups>");
611  foreach(indices(workrooms), object grp) {
612  f->write("<group name='"+grp->get_identifier()+"'>"+
613  workrooms[grp]->get_identifier()+"</group>\n");
614  }
615  f->write("</groups>");
616  f->close();
617  }
618  }
619  if ( directory == "all" ) {
620  array members = send_cmd(start, "get_groups");
621  array rooms = ({ });
622  mapping workrooms = ([ ]);
623 
624  foreach(members, object member) {
625  object grp_wr = send_cmd(member, "query_attribute", "GROUP_WORKROOM");
626  if ( objectp(grp_wr) )
627  rooms += ({ grp_wr });
628  }
629  object steam = send_cmd(start, "lookup", "steam");
630  array users = send_cmd(steam, "get_members");
631  do_store_users(users);
632  foreach(rooms, object room) {
633  workrooms[send_cmd(room, "get_creator")] = room;
634  room_from_server(room, "/"+room->get_identifier());
635  Stdio.File f = Stdio.File(outPath+"/__steam__.xml", "wct");
636  f->write("<?xml version='1.0' encoding='utf-8'?>\n<groups>");
637  foreach(indices(workrooms), object grp) {
638  f->write("<group name='"+grp->get_identifier()+"'>"+
639  workrooms[grp]->get_identifier()+"</group>\n");
640  }
641  f->write("</groups>");
642  f->close();
643  }
644  }
645  if ( start->get_object_class() & CLASS_GROUP ) {
646  //export group structures
647  array members = send_cmd(start, "get_members");
648  array rooms = ({ send_cmd(start,"query_attribute","GROUP_WORKROOM")});
649  array users = get_all_users(start);
650  do_store_users(users);
651  rooms += get_all_rooms(members);
652  mapping workrooms = ([ ]);
653  foreach(rooms, object room) {
654  workrooms[send_cmd(room, "get_creator")] = room;
655  room_from_server(room, "/"+room->get_identifier());
656  Stdio.File f = Stdio.File(outPath+"/__steam__.xml", "wct");
657  f->write("<?xml version='1.0' encoding='utf-8'?>\n<groups>");
658  foreach(indices(workrooms), object grp) {
659  f->write("<group name='"+grp->get_identifier()+"'>"+
660  workrooms[grp]->get_identifier()+"</group>\n");
661  }
662  f->write("</groups>");
663  f->close();
664  }
665  }
666  else {
667  room_from_server(start);
668  }
669 
670  store_users_and_groups();
671  store_objects();
672  }
673  else
674  werror("Failed to connect\n");
675  return 0;
676 }
677 
678 
679 
680 };