2 inherit "../client/client_base";
3 inherit "base/xml_data";
8 class export : public client_base,xml_data{
18 mapping mUsers, mGroups, mObjects, mExclude;
20 mapping mSwitches = ([]);
22 void handle_error(mixed err)
24 Stdio.append_file("export_errors.log", sprintf("-------\n%s%O\n", ctime(time()), err));
27 string compose_scalar(mixed s)
31 if ( s->get_object_class() & CLASS_USER ) {
33 name = s->get_identifier();
36 else if ( s->get_object_class() & CLASS_GROUP ) {
38 name = s->get_identifier();
41 else if ( s->get_object_class() & CLASS_MODULE ) {
43 name = s->get_identifier();
48 int oid = set_object(s);
49 object env = send_cmd(s, "get_environment");
50 if ( !objectp(env) ) {
52 return "<object><type>ID</type><id>"+s->get_object_id() +
55 name = send_cmd(mVariables["filepath:tree"], "object_to_filename",
58 return "<object><type>"+type+"</type><id><![CDATA["+name+"]]></id></object>";
61 return ::compose_scalar(s);
64 void update_content(object obj, string path)
66 if ( Stdio.exist(path) )
68 string content = send_cmd(obj, "get_content", ({ }));
70 if ( !stringp(content) )
72 // create the directory structure !
75 array tokens = (path/"/");
76 dir = tokens[..sizeof(tokens)-2]*"/";
79 Stdio.File f = Stdio.File(path, "wct");
84 void obj_from_server(object obj, string path)
86 Stdio.File xml = Stdio.File(path + "._xml_", "wct");
90 xml->write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"+
92 obj->get_object_class()+"\">\n");
94 mapping attributes = send_cmd(obj, "query_attributes");
95 foreach(indices(attributes), string|int a) {
96 if ( !stringp(attributes[a]) )
98 if ( !utf8_check(attributes[a]) )
99 attributes[a] = string_to_utf8(attributes[a]);
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 }) );
110 xml->write("<attributes-locked>\n"+
111 compose_struct(a_lock) + "\n</attributes-locked>\n");
113 mapping sanction = send_cmd(obj, "get_sanction" );
114 mapping msanction = send_cmd(obj, "get_meta_sanction" );
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);
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");
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");
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"))+
136 object creator = send_cmd(obj, "get_creator");
137 xml->write("<creator>"+compose(creator)+"</creator>\n");
138 xml->write("</Object>\n");
142 void annotation_from_server(object ann)
144 werror("Checking out " + ann->get_identifier() +"["+ann->get_object_id()+
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());
153 void store_meta(object obj, string subpath, array inventory)
155 Stdio.mkdirhier(outPath + subpath);
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"+
161 " <adress>"+mSwitches->server+"</adress>\n"+
162 " <port>"+mSwitches->port+"</port>\n"+
163 " <checkout>"+mSwitches->checkout + "</checkout>\n"+
165 xml->write(" <files>\n");
166 foreach(inventory, object o ) {
169 string id = o->get_identifier();
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");
177 xml->write(" </files>\n</folder>");
183 string readable_filename(string fname)
185 if ( !stringp(fname) )
186 return "__unknown__";
187 fname = replace(fname, ({ "&"}), ({ "und"}));
188 return utf8_to_string(fname);
191 void object_from_server(object obj, string subpath, int|void d)
195 if ( obj->get_object_class() & CLASS_USER || obj->get_object_class() & CLASS_SCRIPT )
198 if ( mExclude[subpath] == 1 ) {
202 string path = send_cmd(mVariables["filepath:tree"],
203 "object_to_filename", ({ obj }));
204 string id = send_cmd(obj, "get_identifier");
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()+"_";
212 path = outPath + subpath + "/" + id;
214 // create the directory structure !
216 array tokens = (path/"/");
217 dir = tokens[..sizeof(tokens)-2]*"/";
218 Stdio.mkdirhier(dir);
220 werror("Checking out " + path);
221 // now write xml for the object
222 obj_from_server(obj, path);
226 if ( obj->get_object_class() & CLASS_CONTAINER && (iDepth==0 || d < iDepth))
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);
232 if ( arrayp(inv) && sizeof(inv) > 0 )
233 store_meta(obj, subpath + "/" + readable_filename(obj->get_identifier()), inv);
237 string group_to_string(object grp)
239 return grp->get_identifier();
243 void store_group(string group)
246 if ( (int)group > 0 ) {
247 grp = send_cmd((int)group, "this");
248 group = grp->get_identifier();
251 grp = send_cmd(mVariables["groups"], "lookup", group);
252 array users = send_cmd(grp, "get_members");
253 do_store_groups(users, grp, group);
259 void do_store_groups(array groups, object grp, string group)
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) {
272 if ( g->get_object_class() & CLASS_GROUP ) {
273 f->write(" <subgroup name=\""+g->query_attribute("OBJ_NAME")+"\">"+
274 g->get_identifier()+ "</subgroup>\n");
276 else if ( grp->is_admin(g) )
277 f->write(" <member admin='true'>"+g->get_identifier()+ "</member>\n");
279 f->write(" <member>"+g->get_identifier()+ "</member>\n");
281 f->write("</group>\n");
283 foreach(groups, object grp)
284 if ( grp->get_object_class() & CLASS_GROUP )
285 do_store_groups(grp->get_members(), grp, grp->get_identifier());
291 void store_users(string group)
293 object grp = send_cmd(mVariables["groups"], "lookup", group);
294 array users = send_cmd(grp, "get_members");
295 do_store_users(users, group);
301 void do_store_users(array users, void|string group)
305 if ( !stringp(group) )
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) {
318 if ( u->get_object_class() & CLASS_GROUP )
321 attr = send_cmd(user, "query_attributes",
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"] = "";
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)
361 f->write(" <group>"+grp->get_identifier()+"</group>\n");
363 f->write(" </user>\n");
366 f->write("</users>\n");
373 void store_users_and_groups()
377 path = outPath + "/__groups__/";
379 Stdio.mkdirhier(path);
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");
386 foreach(indices(mUsers), object u) {
387 obj_from_server(u, path + u->get_identifier());
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");
394 foreach(indices(mGroups), object g) {
395 obj_from_server(g, path + g->get_identifier());
406 path = outPath + "/__objects__/";
407 Stdio.mkdirhier(path);
409 foreach(indices(mObjects), 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());
419 array get_all_rooms(array groups)
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());
431 array get_all_users(object grp)
434 array u = send_cmd(grp, "get_members");
435 foreach(u, object user) {
436 if ( user->get_object_class() & CLASS_USER )
438 else if ( user->get_object_class() & CLASS_GROUP )
439 users += get_all_users(user);
444 void room_from_server(object start, void|string 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);
455 int main(int argc, array argv)
458 string server= "localhost";
459 string directory = "/";
461 string user = "root";
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");
484 for ( i = 1; i < sizeof(argv); i++ ) {
486 if ( sscanf(argv[i], "--%s=%s", cmd, arg) == 2 ||
487 sscanf(argv[i], "--%s", cmd) == 1 )
489 if ( stringp(arg) && strlen(arg) > 0 )
490 sscanf(arg, "\"%s\"", arg);
505 case "user": // checkout user of group
506 mSwitches->user = arg;
508 case "group": // checkout user of group
509 mSwitches->group = arg;
517 case "with-annotations":
521 write("Usage is export "+
522 "--in=<server-path> --out=<export-path>\n");
525 werror(sprintf("Unknown parameter %s\n", argv[i]));
530 werror("Connecting "+server+":"+port+"\n");
531 if ( connect_server(server, port) ) {
532 if ( outPath[-1] == '/' )
533 outPath = outPath[..strlen(outPath)-2];
535 Stdio.mkdirhier(outPath);
536 werror("Exporting to " + outPath + "\n");
538 mSwitches->server = server;
539 mSwitches->port = port;
540 mSwitches->checkout = directory;
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;
551 login(user, pw, CLIENT_STATUS_CONNECTED, "ftp");
552 // now get the inventory from the root room
554 if ( mSwitches->user ) {
555 store_users(mSwitches->user );
558 if ( mSwitches->group ) {
559 store_group(mSwitches->group);
563 object start = mVariables["rootroom"];
564 object group = send_cmd(mVariables["groups"], "lookup", directory);
565 if ( (int)directory > 0 ) {
566 int dir = (int)directory;
568 start = send_cmd(dir, "this");
570 else if ( directory == "all" ) {
571 start = mVariables["groups"];
573 else if ( directory == "all" ) {
574 start = mVariables["groups"];
576 else if ( objectp(group) )
578 else if ( directory != "/" ) {
579 int oid = set_object(mVariables["filepath:tree"]);
580 start = send_command(COAL_COMMAND, ({ "path_to_object",
581 ({ directory }), }));
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);
589 if ( !objectp(start) ) {
590 werror("Start Directory not found !");
593 if ( directory == "all" ) {
594 array members = send_cmd(start, "get_groups");
596 mapping workrooms = ([ ]);
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 });
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");
615 f->write("</groups>");
619 if ( directory == "all" ) {
620 array members = send_cmd(start, "get_groups");
622 mapping workrooms = ([ ]);
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 });
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");
641 f->write("</groups>");
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");
662 f->write("</groups>");
667 room_from_server(start);
670 store_users_and_groups();
674 werror("Failed to connect\n");