1
/* Copyright (C) 2000-2004 Thomas Bopp, Thorsten Hampel, Ludger Merkens
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.
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.
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
17
* $Id: xml_converter.pike,v 1.4 2006/09/28 09:50:38 astra Exp $
20
constant cvs_version="$Id: xml_converter.pike,v 1.4 2006/09/28 09:50:38 astra Exp $";
22
inherit "/kernel/module";
23
inherit "/base/xml_data";
30
#include <attributes.h>
41
#define DEBUG_XML(s) werror(s+"\n")
52
#define ID_THIS_USER 2
54
#ifdef RESTRICTED_NAMES
55
#define OBJ_DESC_OR_NAME OBJ_DESC
57
#define OBJ_DESC_OR_NAME OBJ_NAME
64
void create(int i, void|object o) { id = i; obj = o; }
65
object this() { return obj; }
66
string get_identifier() { return obj->get_identifier(); }
67
function find_function(string f) { return obj->find_function(f); }
72
mixed def; // the default value
75
mixed cast(string castto) {
85
mixed this() { return val; }
88
OBJECT THIS = OBJECT(ID_THIS);
89
OBJECT THIS_USER = OBJECT(ID_THIS_USER);
90
OBJECT CONV = OBJECT(0);
91
OBJECT LAST = OBJECT(0);
92
OBJECT ACTIVE = OBJECT(0);
93
OBJECT XSL = OBJECT(0);
94
OBJECT ENV = OBJECT(0);
99
object this() { return this_object(); }
102
static mapping activeThreadMap = ([ ]);
103
static mapping params = ([ ]);
105
KEYVALUE ENTRY = KEYVALUE();
108
mapping objXML = ([ CLASS_OBJECT: ([
109
"name": ({ THIS, "query_attribute", ({ OBJ_NAME }), show }),
110
"icon": ({ THIS, "get_icon", ({ }), show_object_ext }),
111
"environment": ({ THIS, "get_environment", ({ }), show }),
112
"id": ({ THIS, "get_object_id", ({ }), show }),
113
"last-modified": ({ CONV, "get_last_modified", ({ THIS, }), get_time }),
114
"modified-by": ({ THIS, "query_attribute", ({DOC_USER_MODIFIED }),show}),
115
"created": ({ THIS, "query_attribute",
116
({OBJ_CREATION_TIME }), get_time }),
117
"owner": ({ THIS, "get_creator", ({ }), show }),
118
"URL": ({ THIS, "get_identifier", ({ }), no_uml }),
119
"content": ({ CONV, "show_content", ({ THIS }), 0 }),
120
"annotated": ({ CONV, "show_annotations_size", ({ THIS }), 0 }),
124
mapping annotationXML = ([ CLASS_OBJECT: objXML[CLASS_OBJECT] +
125
([ "mime-headers": ({ THIS, "query_attribute", ({ MAIL_MIMEHEADERS }),
127
"description": ({ THIS, "query_attribute", ({OBJ_DESC_OR_NAME}), show })
130
mapping linkXML = ([ CLASS_LINK: ([
131
"link": ({ THIS, "get_link_object", ({ }), show_object_ext }),
132
"action": ({ THIS, "get_link_action", ({ }), show }),
135
mapping exitXML = ([ CLASS_EXIT: ([
136
"exit": ({ THIS, "get_exit", ({ }), show_exit }),
140
mapping userXML = ([ CLASS_USER: ([
141
"email": ({ THIS, "query_attribute", ({ USER_EMAIL }), show }),
142
"inventory": ({ THIS, "get_inventory", ({ }), show_size}),
143
"mailbox-size": ({ THIS, "get_annotations", ({ }), show_mailbox_size }),
144
"trail": ({ THIS, "query_attribute", ({ "trail" }), show_trail }),
145
"id": ({ THIS, "get_object_id", ({ }), show }),
146
"fullname": ({ THIS, "query_attribute", ({USER_FULLNAME}),show}),
147
"firstname": ({ THIS, "query_attribute", ({USER_FIRSTNAME}), show}),
148
"name": ({ THIS, "query_attribute", ({ OBJ_NAME }), 0 }),
149
"identifier": ({ THIS, "get_user_name", ({ }), show }),
150
"icon": ({ THIS, "query_attribute", ({ OBJ_ICON }), show }),
151
"environment": ({ THIS, "get_environment", ({ }), show }),
152
"description": ({ THIS, "query_attribute", ({ OBJ_DESC }), show }),
153
"carry": ({ CONV, "show_carry", ({ }), 0 }),
154
"admin": ({ (MODULE_GROUPS ? MODULE_GROUPS->lookup("admin") : 0),"is_member", ({ THIS }), show_truefalse }),
155
"active-group": ({ THIS, "get_active_group", ({ }), show }),
156
"status": ({ THIS, "get_status", ({ }), show_status }),
157
"language": ({ THIS, "query_attribute", ({ USER_LANGUAGE }), show }),
160
mapping userInvXML = ([ CLASS_USER: ([
161
"id": ({ THIS, "get_object_id", ({ }), show }),
162
"name": ({ THIS, "query_attribute", ({ OBJ_NAME }), 0 }),
163
"icon": ({ THIS, "query_attribute", ({ OBJ_ICON }), show }),
164
"status": ({ THIS, "get_status", ({ }), show_status }),
168
mapping annotationsXML = ([ CLASS_OBJECT: ([
169
"annotations": ({ THIS, "get_annotations_for", ({ THIS_USER }),
171
"active-content": ({ ACTIVE, "get_content", ({ }), show }),
174
mapping userDetailsXML = ([ CLASS_USER: ([
175
"groups": ({ THIS, "get_groups", ({ }), show }),
176
"access": ({ CONV, "get_basic_access", ({ THIS }), 0 }),
177
"user": ({ 0, this_user, ({ }), userXML }),
178
"attributes": ({ THIS, "get_attributes", ({ }), ([
179
"attribute": ({ CONV, "show_attribute", ({ ENTRY }),0})
181
]) + userXML[CLASS_USER], ]);
184
mapping containerXML = ([
186
"description": ({ THIS, "query_attribute", ({ OBJ_DESC }), show }),
187
"inventory": ({ THIS, "get_inventory", ({ }), show_size }),
192
mapping mailboxXML = ([
195
"path": ({ CONV, "get_path", ({ THIS }), 0 }),
196
"user": ({ 0, this_user, ({ }), userXML }),
197
])+objXML[CLASS_OBJECT],
200
"inventory": ({ THIS, "get_inventory", ({ }),
201
objXML+exitXML+linkXML+userInvXML+containerXML }),
205
mapping iconsXML = ([
207
([ "icons": ({ THIS, "get_icons", ({ }), show }),
208
"user": ({ 0, this_user, ({ }), userXML }),
209
])+objXML[CLASS_OBJECT], ]);
211
mapping contentXML = ([
214
"path": ({ CONV, "get_path", ({ THIS }), 0 }),
215
"user": ({ 0, this_user, ({ }), userXML }),
216
])+objXML[CLASS_OBJECT],
219
"inventory": ({ THIS, "get_inventory", ({ }),
220
objXML+exitXML+linkXML+userInvXML+containerXML}),
226
array(string) __sanction;
227
static mapping mXML = ([ ]);
228
static mapping mSelection = ([ ]);
229
static array(object) selection;
232
static mapping entities = ([
244
* Initialize the module, this function is called when the module is loaded.
246
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
248
static void load_module()
250
if ( objectp(_SECURITY) )
251
__sanction = _SECURITY->get_sanction_strings();
253
// if the state of an object changed, we have to update cache !
256
string no_uml(string str)
258
return httplib.no_uml(str);
264
* Exchange some entities to fix the html sources. Especially umlaute.
266
* @param string txt - the text where to exchange Umlaute, etc.
267
* @return the replaced text.
268
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
271
string htmlize(string txt)
273
string html = replace(txt, indices(entities), values(entities));
278
* Show function to bring a config mapping in xml format.
279
* It will have each configuration listed as config name='config-name'
280
* with the value as container data.
282
* @param mapping configs - the configuration mapping to bring to xml.
283
* @return the converted mapping.
284
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
286
string show_configs(mapping configs)
289
foreach(indices(configs), mixed index) {
290
if ( stringp(configs[index]) || intp(configs[index]) )
291
xml += "\t<config name=\""+index+"\">"+configs[index]+"</config>\n";
296
string show_ports(array ports)
299
foreach(ports, object port) {
300
xml += "<port nr='"+port->get_port()+"'>"+port->describe()+"</port>";
306
* Time function just calls time().
308
* @return the current timestamp (unix-time).
309
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
316
int cmp_names(object obj1, object obj2)
318
return lower_case(obj1->get_identifier())>lower_case(obj2->get_identifier());
321
int cmp_size(object obj1, object obj2)
323
if ( obj1->get_object_class() & CLASS_CONTAINER )
324
return sizeof(obj1->get_inventory()) > sizeof(obj2->get_inventory());
325
return obj1->get_content_size() > obj2->get_content_size();
328
int cmp_date(object obj1, object obj2)
330
return get_last_modified(obj1) >
331
get_last_modified(obj2);
334
int cmp_names_rev(object obj1, object obj2)
336
return lower_case(obj1->get_identifier())<lower_case(obj2->get_identifier());
339
int cmp_size_rev(object obj1, object obj2)
341
if ( obj1->get_object_class() & CLASS_CONTAINER )
342
return sizeof(obj1->get_inventory()) < sizeof(obj2->get_inventory());
343
return obj1->get_content_size() < obj2->get_content_size();
346
int cmp_date_rev(object obj1, object obj2)
348
return get_last_modified(obj1) <
349
get_last_modified(obj2);
353
* Get the inventory of a container, parameters have to include
354
* an object range, optionally the container can bhe sorted with
355
* "name", "reverse-name", "size", "reverse-size", "modified" or
356
* "reverse-modified".
358
* @param object cont - the container to show
359
* @param int from_obj - the start of the object range
360
* @param int to_obj - the end of the object range.
361
* @param string sort - sort option.
362
* @return (sorted) array of objects
365
get_cont_inventory(object cont, int from_obj, int to_obj, void|string sort)
367
array(object) inv = cont->get_inventory();
368
array(object) arr = ({ });
369
array(object) obj_arr = ({ });
370
array(object) cont_arr = ({ });
372
foreach( inv, object obj ) {
373
if ( obj->get_object_class() & CLASS_EXIT ||
374
obj->get_object_class() & CLASS_ROOM ||
375
obj->get_object_class() & CLASS_USER )
377
else if ( obj->get_object_class() & CLASS_CONTAINER )
378
cont_arr += ({ obj });
379
else if ( !(obj->get_object_class() & CLASS_DRAWING) )
380
obj_arr += ({ obj });
382
if ( !stringp(sort) || sort == "none" ) {
383
sort = cont->query_attribute("web:sort:objects");
384
if ( sort == "last-modified/time" )
388
// sort the array of objects
389
if ( stringp(sort) ) {
392
obj_arr = Array.sort_array(obj_arr, cmp_names);
393
cont_arr = Array.sort_array(cont_arr, cmp_names);
396
obj_arr = Array.sort_array(obj_arr, cmp_size);
397
cont_arr = Array.sort_array(cont_arr, cmp_size);
400
obj_arr = Array.sort_array(obj_arr, cmp_date);
401
cont_arr = Array.sort_array(cont_arr, cmp_date);
404
obj_arr = Array.sort_array(obj_arr, cmp_names_rev);
405
cont_arr = Array.sort_array(cont_arr, cmp_names_rev);
408
obj_arr = Array.sort_array(obj_arr, cmp_size_rev);
409
cont_arr = Array.sort_array(cont_arr, cmp_size_rev);
411
case "reverse-modified":
412
obj_arr = Array.sort_array(obj_arr, cmp_date_rev);
413
cont_arr = Array.sort_array(cont_arr, cmp_date_rev);
417
obj_arr = cont_arr + obj_arr;
418
if ( to_obj == 0 ) to_obj = sizeof(obj_arr);
420
return obj_arr[from_obj-1..to_obj-1] + arr;
423
string show_inventory_size(object cont)
426
int docs, conts, rooms, exits, sz, users;
429
// fixme: use this function ?
430
array(object) inv = cont->get_inventory();
431
foreach(inv, object o) {
432
if ( o->get_object_class() & CLASS_USER )
434
else if ( o->get_object_class() & CLASS_ROOM )
436
else if ( o->get_object_class() & CLASS_EXIT )
438
else if ( o->get_object_class() & CLASS_CONTAINER )
440
else if ( o->get_object_class() & CLASS_DOCUMENT )
451
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
454
int get_last_modified(object obj)
456
if ( obj->get_object_class() & CLASS_DOCUMENT )
457
return obj->query_attribute(DOC_LAST_MODIFIED);
458
else if ( obj->get_object_class() & CLASS_CONTAINER )
459
return obj->query_attribute(CONT_LAST_MODIFIED);
461
return obj->query_attribute(OBJ_LAST_CHANGED);
465
* Get the name for an object class. This function queries the factory
466
* of the object to get the name.
468
* @param int id - the class id
469
* @return the class-name string
470
* @author Thomas Bopp (astra@upb.de)
472
string class_id_to_name(int id)
474
if ( id & CLASS_SCRIPT )
477
object factory = _Server->get_factory(id);
478
if ( objectp(factory) )
479
return "\""+factory->get_class_name()+"\"";
485
* Show extended object information.
486
* <object type='Object'><name/><id/><path/><description/></object>
488
* @param object obj - the object to show.
489
* @return extended object information xml code.
491
string show_object_ext(object obj)
496
return "<object type="+class_id_to_name(obj->get_object_class())+
497
"><name><![CDATA["+obj->query_attribute(OBJ_NAME)+"]]></name>"+
498
"<id>"+obj->get_object_id()+"</id><path><![CDATA["+
499
(obj->get_object_class() & CLASS_DOCEXTERN ?
500
obj->query_attribute(DOC_EXTERN_URL):
501
replace_uml(_FILEPATH->object_to_filename(obj)))+
502
"]]></path><description><![CDATA["+
503
obj->query_attribute(OBJ_DESC)+"]]></description></object>";
507
string show_objects_ext(array(object) objs)
509
string xml = "<array>";
510
foreach(objs, object obj)
511
xml += show_object_ext(obj);
516
string show_trail(array(object) trail, int|void sz)
525
// try to detect loop in trail, only A,B,A,B
530
for ( i = sizeof(trail) - 1 - sz; i < sizeof(trail); i++ ) {
531
if ( i < 0 ) continue;
532
xml += show_object_ext(trail[i]);
541
* Show extended information for XSL objects in this converter.
543
* @param mixed s - the value to show in xml
544
* @return the value in xml
545
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
548
string compose_scalar(mixed s)
550
if ( objectp(s) && s->get_object_class() & CLASS_DOCXSL) {
551
return "<object><name>"+s->get_identifier()+"</name>"+
552
"<id>"+s->get_object_id()+"</id><path>"+
553
_FILEPATH->object_to_filename(s)+"</path></object>";
555
return ::compose_scalar(s);
563
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
566
array(object) get_filtered_inventory(object obj, mixed key, mixed val)
568
array inv = obj->get_inventory();
570
foreach ( inv, object o ) {
571
mixed v = o->query_attribute(key);
576
else if ( arrayp(v) && !arrayp(val) && search(v,val) >= 0 )
585
* Show an attribute. This is done without the basic conversion to
586
* xml with string|int, because for example the data type of
587
* name or id tags is already known.
589
* @param mixed val - the value to convert
590
* @return the converted value
592
string show(string|int|object|mapping|program|array val)
594
DEBUG_XML("show:"+sprintf("%O", val));
596
return "<![CDATA["+val+"]]>";
597
else if ( intp(val) )
599
else if ( objectp(val) && stringp(val->query_attribute(OBJ_NAME)) &&
600
!xml.utf8_check(val->query_attribute(OBJ_NAME)) )
601
return "<invalid_object_utf8>"+val->get_object_id()+"</invalid_object_utf8>";
606
* Show xml code for an exit - that is the destination.
608
* @param object exit - the exit to show.
609
* @return xml string representation.
612
string show_exit(object exit)
614
string p = _FILEPATH->object_to_filename(exit);
618
return "<object><id>"+exit->get_object_id()+"</id><path>"+p+"</path>"+
619
"<name>"+exit->get_identifier()+"</name></object>\n";
623
* Gives xml code for the creator of an object.
625
* @param object creator - the creator.
626
* @return xml code for creator object.
628
string show_creator(object creator)
631
return "<object type="+class_id_to_name(creator->get_object_class())+"><id>"+creator->get_object_id()+"</id>"+
632
"<name>"+creator->get_identifier()+"</name></object>\n";
637
* Show the status status in terms of CLIENT_FEATURES_*
639
* @param int status - the status to xmlize.
640
* @return the xml converted status.
641
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
643
string show_status(int status)
647
if ( status & CLIENT_FEATURES_CHAT )
648
xml += "<chat>true</chat>";
650
xml += "<chat>false</chat>";
652
if ( status & CLIENT_STATUS_CONNECTED )
653
xml += "<connected>true</connected>";
655
xml += "<connected>false</connected>";
660
* Return false for value 0 and otherwise true.
662
* @param mixed val - the value for true or false
663
* @return true or false as a string
664
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
666
string show_truefalse(mixed val)
674
* Show the size of an array or the inventory size of an container.
677
* @param object|array o - the array or container to show its size.
678
* @return size of container or array.
679
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
681
string show_size(object|array o)
684
return (string)sizeof(o);
685
else if ( objectp(o) && o->get_object_class() & CLASS_CONTAINER )
686
return (string)sizeof(o->get_inventory());
690
string show_size_unread(object|array o)
692
object trd = _Server->get_module("table:read-documents");
696
foreach(o, object obj) {
697
o += obj->get_annotations();
698
if ( objectp(trd) ) {
699
if ( !trd->is_reader(obj, this_user()) )
704
return"<unread>"+sz+"</unread><messages>"+msgs+"</messages>";
706
return "<unread>0</unread><messages>0</messages>";
709
string show_mailbox_size(object|array o)
711
return show_size_unread(o);
714
string show_annotations_size(object o)
716
if ( o->get_object_class() & CLASS_USER )
717
return "<unread>0</unread><messages>0</messages>";
718
return show_size_unread(o->get_annotations());
723
* Get the permission role for some access bit array or an object.
725
* @param int|object access - the access integer or access object
726
* @return string description of the objects access permissions.
727
* @author Thomas Bopp (astra@upb.de)
729
string get_role(int|object access)
731
if ( objectp(access) )
732
access = LAST->obj->query_sanction(access);
734
if ( (access & SANCTION_ALL)==SANCTION_ALL )
736
else if ( access & SANCTION_READ && access & SANCTION_WRITE )
738
else if ( (access & SANCTION_READ) && (access & SANCTION_ANNOTATE) )
740
else if ( access & (SANCTION_READ) )
746
* Check the access of an object for a given access bit.
748
* @param object obj - the object to check access.
749
* @param object caller - the calling object.
750
* @param int accBit - the access Bit to test.
751
* @return true or false.
752
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
754
bool check_access(object obj, object caller, int accBit)
756
return _SECURITY->check_user_access(obj, caller, accBit, accBit, false);
760
* Get the time string for a given timestamp 't'.
762
* @param int tt - timestamp to get a string description for.
763
* @return string description of timestamp in "month date year/time".
764
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
766
string get_time(int tt)
769
if ( intp(tt) ) t = tt;
770
string ti = ctime(t);
772
string date, hour, minute;
774
if (sscanf(ti,"%*s %s %s %s:%s:%*d %s\n",month,date,hour,minute,year) != 5)
775
sscanf(ti,"%*s %s %s %s:%s:%*d %s\n", month,date,hour,minute,year);
776
string gettime = month + "/"+ date + "/" + (year[2..3]) + "/" + hour +
778
return "<date>"+gettime+"</date><time>"+t+"</time>";
782
* Get the standard ctime output format. <date>ctime(t)</date><time>t</time>.
784
* @param int t - the timestamp (unix)
786
string get_ctime(int tt)
789
if ( intp(tt) ) t = tt;
790
return "<date>"+ctime(t)+"</date><time>"+t+"</time>";
794
* Get the content of an object.
796
* @param object obj - the object to get the content for.
797
* @return the content of the object.
800
get_obj_content(object obj)
804
if ( search(obj->query_attribute(DOC_MIME_TYPE), "txt") >= 0 ||
805
search(obj->query_attribute(DOC_MIME_TYPE), "text") >= 0 )
807
string content = obj->get_content();
808
if ( obj->query_attribute(DOC_MIME_TYPE) == "text/plain" )
809
content = text_to_html(content);
810
if ( !stringp(content) )
813
return "<![CDATA["+string_to_utf8(content)+"]]>";
818
string get_obj_content_detect(object obj)
822
if ( search(obj->query_attribute(DOC_MIME_TYPE), "txt") >= 0 ||
823
search(obj->query_attribute(DOC_MIME_TYPE), "text") >= 0 )
825
string content = obj->get_content();
826
string encoding = obj->query_attribute(DOC_ENCODING);
827
if ( !stringp(encoding) &&
828
search(obj->query_attribute(DOC_MIME_TYPE), "html") >= 0 )
829
encoding = detect_encoding(content);
831
if ( !stringp(content) )
834
if ( encoding != "utf-8" )
835
return "<![CDATA["+string_to_utf8(content)+"]]>";
837
return "<![CDATA["+content+"]]>";
843
get_obj_content_raw(object obj)
847
if ( search(obj->query_attribute(DOC_MIME_TYPE), "txt") >= 0 ||
848
search(obj->query_attribute(DOC_MIME_TYPE), "text") >= 0 )
850
string content = obj->get_content();
851
if ( !stringp(content) )
853
if ( obj->query_attribute(DOC_MIME_TYPE) == "text/plain" )
854
content = text_to_html(content);
856
if ( obj->query_attribute(DOC_ENCODING) == "iso-8859-1" )
857
content = string_to_utf8(content);
858
if ( !xml.utf8_check(content) )
859
content = string_to_utf8(content);
861
return "<![CDATA["+content+"]]>";
867
object get_object(string o) {
869
return find_object((int)o);
871
return find_object(o);
874
string execute(mapping vars) {
878
obj = get_object(vars->args->object);
880
return "<!-- xslt: no object found ("+vars->args->object+")-->";
881
xsl = get_object(vars->args->xsl);
883
return "<!-- xslt: no xsl Stylesheet found ("+
884
vars->args->xsl+")-->";
885
return run_xml(obj, xsl, vars);
888
int get_object_class() { return 0; }
892
* Get the content of a given object and parse all rxml tag
893
* inside the well formed html or text content.
895
* @param object obj - the object to get the content for.
896
* @return the resulting code
898
string get_obj_content_rxml(object obj)
903
return "<!-- this function is no longer available !-->";
905
if ( search(obj->query_attribute(DOC_MIME_TYPE), "txt") >= 0 ||
906
search(obj->query_attribute(DOC_MIME_TYPE), "text") >= 0 )
908
string content = obj->get_content();
909
mapping tags = ([ "xslt": xsltTag()->execute, ]);
912
result = htmllib.parse_rxml(string_to_utf8(content),
913
XSL->vars, tags, "utf-8");
916
werror("Got error upon get_obj_content_rxml:\n%O", err);
919
return "<![CDATA["+result+"]]>";
921
steam_error("Cannot parse rxml in non-text content !");
926
* Describe the params of an attribute. The function gets the attribute
927
* registration array which is available from the factory.
929
* @param array reg - the registered attribute data.
930
* @return string description of the registered type.
931
* @author Thomas Bopp (astra@upb.de)
933
string describe_params(mixed reg)
935
int type = reg[REGISTERED_TYPE];
937
if ( type == CMD_TYPE_ARRAY )
939
else if ( type == CMD_TYPE_FLOAT )
941
else if ( type == CMD_TYPE_MAPPING )
943
else if ( type == CMD_TYPE_STRING )
945
else if ( type == CMD_TYPE_TIME )
947
else if ( type == CMD_TYPE_INT )
949
else if ( type == CMD_TYPE_OBJECT )
955
_get_annotations_thread(object obj, object user , int d, int|void active_flag)
961
active_flag = activeThreadMap[obj];
964
_Server->get_module("table:read-documents")->get_readers(obj),
967
"<depth>"+d+"</depth>\n"+
968
"<subject><![CDATA["+obj->query_attribute(OBJ_DESC_OR_NAME) +"]]></subject>"+
969
"<accessed>"+obj->query_attribute(DOC_TIMES_READ)+"</accessed>\n"+
970
"<id>"+obj->get_object_id() + "</id>\n"+
971
"<created>"+get_time(obj->query_attribute(OBJ_CREATION_TIME))+"</created>\n"+
972
"<modified>"+get_time(obj->query_attribute(DOC_LAST_MODIFIED))+"</modified>\n"+
973
"<active-thread>"+active_flag+"</active-thread>\n"+
974
"<read>"+read+"</read>\n"+
975
"<author>"+compose_scalar(obj->get_creator())+"</author>\n";
977
array(object) annotations = obj->get_annotations_for(user);
978
if ( arrayp(annotations) ) {
979
foreach(annotations, object ann) {
980
if ( !objectp(ann) ) continue;
982
res = _get_annotations_thread(ann, user, d+1, active_flag);
984
read = (read || res[1]);
987
xml += "<read_thread>"+read+"</read_thread>\n";
988
xml += "</thread>\n";
989
return ({ xml, read });
993
* Convert an annotation thread into xml. This function is called
994
* recursively. Dont call this function directly, use show_annotations
997
* @param object obj - the current annotation object.
998
* @param object user - the user reading the annotations.
999
* @param int d - the current depth in the thread.
1000
* @return xml string representation of an annotation thread.
1001
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
1002
* @see show_annotations
1005
get_annotations_thread(object obj, object user, int d, int|void active_flag)
1007
return _get_annotations_thread(obj, user, d, active_flag)[0];
1011
* Recursively insert annotations in the annotation array. This just
1012
* builds an array which is used by show_annotations. The user object
1013
* parameter is used for calling the get_annotations_for() function.
1015
* @param object ann - the current annotation
1016
* @param object user - the user reading the anntotations.
1018
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
1019
* @see show_annotations
1021
array(object) insert_annotations(object ann, object user)
1023
array(object) annotations = ann->get_annotations_for(user);
1024
if ( arrayp(annotations) ) {
1025
foreach ( annotations, object a) {
1026
annotations += insert_annotations(a, user);
1036
* Bring the given array of annotation objects to XML.
1038
* @param array(object) annotations - array of annotation documents.
1039
* @return xml presentation of the annotations and their sub-annotations.
1040
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
1041
* @see insert_annotations
1042
* @see get_annotations_thread
1044
string show_annotations(array(object) annotations)
1047
for ( int i = 0; i < sizeof(annotations); i++ ) {
1048
if ( !objectp(annotations[i]) ) continue;
1049
xml += get_annotations_thread(annotations[i], this_user(), 0);
1051
foreach ( annotations, object ann ) {
1052
annotations += insert_annotations(ann, this_user());
1054
foreach(annotations, object annotation) {
1055
xml += serialize_xml_object(
1056
annotation, annotationXML, true);
1066
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
1069
string do_show_attribute(object obj, mixed key, mixed val, mixed attrReg)
1072
"\t\t\t<locked>"+(obj->is_locked(key) ? "true":"false")+"</locked>\n"+
1073
"\t\t\t<type>"+describe_params(attrReg)+"</type>\n"+
1074
"\t\t\t<key>"+compose(key) + "</key>\n"+
1075
"\t\t\t<acquire>"+describe_acquire(val[1])+ "</acquire>\n"+
1076
"\t\t\t<description>"+attrReg[REGISTERED_DESC]+"</description>\n"+
1077
"\t\t\t<data>"+compose(val[0])+"</data>\n";
1081
* Show the registered data of an attribute and its value. This is
1082
* used by attributes.xsl.
1084
* @param KEYVALUE k - key/value pair from a mapping.
1085
* @return xml presentation of the attribute data.
1086
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
1088
string show_attribute(KEYVALUE k)
1090
object obj = THIS->this();
1092
mixed attrReg = k->val;
1093
mixed val= ({ obj->query_attribute(key), obj->get_acquire_attribute(key) });
1094
return do_show_attribute(obj, key, val, attrReg);
1102
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
1105
string show_attribute_reg(KEYVALUE k)
1107
object obj = THIS->this();
1109
mixed attrReg = k->val;
1110
mixed val= obj->get_attribute_default(key);
1111
return do_show_attribute(obj, key, val, attrReg);
1115
* Show how many objects a user carries.
1117
* @return the size of the current user selection.
1118
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
1122
return (string)sizeof(selection);
1126
* Get the objects this() pointer, or 0 if its an invalid object.
1127
* This checks if there is a valid proxy.
1129
* @param object o - the object.
1130
* @return the proxy of the object
1131
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
1134
object get_local_object(object o)
1136
if ( objectp(o) && objectp(o->this()) )
1142
* Describe a sanction bit array as a number of 'permission' tags.
1144
* @param int saction - the permission bit array.
1145
* @return xml presentation of access permissions.
1146
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
1148
string show_access(int sanction)
1152
int sz = sizeof(__sanction);
1153
for ( int i = 0; i < sz; i++ ) {
1154
if ( __sanction[i] == "free" ) continue;
1156
if ( sanction & ((1<<i)<<16) )
1157
xml += "\t\t\t<permission type=\""+__sanction[i]+
1158
"\">2</permission>\n";
1159
else if ( sanction & (1<<i) )
1160
xml += "\t\t\t<permission type=\""+__sanction[i]+
1161
"\">1</permission>\n";
1163
xml += "\t\t\t<permission type=\""+__sanction[i]+
1164
"\">0</permission>\n";
1170
* Get basic access permissions for an object. Checks whether the
1171
* user can read,write,execute and annotate the object and if the
1172
* steam-group is able to read. Finally its checked if also everyone
1173
* can read the object.
1175
* @param objcet obj - the object to check.
1176
* @return the xml access string.
1177
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
1179
string get_basic_access(object obj)
1183
int access = _SECURITY->get_user_permissions(obj, this_user(), SANCTION_READ|SANCTION_WRITE|SANCTION_EXECUTE|SANCTION_ANNOTATE|SANCTION_INSERT);
1184
int gaccess = _SECURITY->get_user_permissions(obj, _WORLDUSER, SANCTION_READ|SANCTION_WRITE|SANCTION_EXECUTE|SANCTION_ANNOTATE|SANCTION_INSERT);
1185
int saccess = _SECURITY->get_user_permissions(obj, _STEAMUSER, SANCTION_READ);
1186
if ( obj == this_user() )
1187
access = saccess = SANCTION_ALL;
1190
if ( gaccess & SANCTION_READ )
1191
xml += "<readable guest=\"true\" user=\"true\" steam=\"true\"/>";
1193
xml += "\t<readable guest=\"false\" user=\""+
1194
((access & SANCTION_READ) ? "true":"false") + "\" steam=\""+
1195
((saccess&SANCTION_READ) ? "true":"false") + "\" />\n";
1196
if ( gaccess & SANCTION_WRITE )
1197
xml += "<writeable guest=\"true\" user=\"true\" steam=\"true\"/>";
1199
xml += "\t<writeable guest=\"false\" user=\""+
1200
((access&SANCTION_WRITE) ? "true":"false") + "\"/>\n";
1202
if ( gaccess & SANCTION_EXECUTE )
1203
xml += "<executeable guest=\"true\" user=\"true\" steam=\"true\"/>";
1205
xml += "\t<executeable guest=\"false\" user=\""+
1206
((access&SANCTION_EXECUTE)? "true":"false") + "\"/>\n";
1207
if ( gaccess & SANCTION_ANNOTATE )
1208
xml += "<annotateable guest=\"true\" user=\"true\" steam=\"true\"/>";
1210
xml += "\t<annotateable guest=\"false\" user=\""+
1211
((access&SANCTION_ANNOTATE) ? "true":"false") + "\"/>\n";
1212
if ( gaccess & SANCTION_INSERT )
1213
xml += "<insertable guest=\"true\" user=\"true\" steam=\"true\"/>";
1215
xml += "\t<insertable guest=\"false\" user=\""+
1216
((access&SANCTION_INSERT) ? "true":"false") + "\"/>\n";
1221
* Describe the acquired access of an object.
1223
* @param object obj - the object to describe its acquiring.
1224
* @return xml string about acquired access permission.
1225
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
1227
string get_acquired_access(object obj)
1233
//DEBUG_XML("get_acquired_access("+obj->get_identifier()+")");
1234
object|function acquire = obj->get_acquire();
1236
if ( functionp(acquire) )
1237
acquire = acquire();
1239
while ( acquire != 0 ) {
1240
mSanction = acquire->get_sanction();
1241
foreach(indices(mSanction), object sanctioned) {
1242
if ( !objectp(sanctioned) ) continue;
1243
xml += "\t\t\t<Object "+
1244
"type="+class_id_to_name(sanctioned->get_object_class())+
1246
xml += "\t\t\t\t<from>"+compose(acquire)+"</from>\n";
1247
xml += "\t\t\t\t<id>"+sanctioned->get_object_id() + "</id>\n"+
1248
"\t\t\t\t<name>"+sanctioned->get_identifier()+"</name>\n";
1249
sz = sizeof(__sanction);
1250
for ( int i = 0; i < sz; i++ ) {
1251
if ( __sanction[i] == "free" ) continue;
1253
if ( mSanction[sanctioned] & ((1<<i)<<16) )
1254
xml += "\t\t\t\t\t<permission type=\""+__sanction[i]+
1255
"\">2</permission>\n";
1256
else if ( mSanction[sanctioned] & (1<<i) )
1257
xml += "\t\t\t\t<permission type=\""+__sanction[i]+
1258
"\">1</permission>\n";
1260
xml += "\t\t\t\t<permission type=\""+__sanction[i]+
1261
"\">0</permission>\n";
1263
xml +="\t\t\t</Object>\n";
1265
acquire = acquire->get_acquire();
1266
if ( functionp(acquire) )
1267
acquire = acquire();
1273
* Describe the acquire situation of an object.
1275
* @param function|object acquire the acquire setting
1276
* @return xml description of the given function or object.
1277
* @author Thomas Bopp (astra@upb.de)
1279
string describe_acquire(function|object|int acquire)
1281
if ( functionp(acquire) && acquire == THIS->obj->get_environment )
1283
acquire = acquire();
1284
if ( objectp(acquire) )
1285
return "<function><name>get_environment</name><id>"+
1286
acquire->get_object_id()+ "</id></function>\n";
1288
else if ( intp(acquire) && acquire == REG_ACQ_ENVIRONMENT )
1289
return "<function><name>get_environment</name></function>";
1290
else if ( objectp(acquire) )
1291
return compose_scalar(acquire);
1292
return "<object><name/><id>0</id></object>";
1296
* Serialize an XML tag with serialization data 'data'.
1298
* @param string tag - the name of the tag to serialize.
1299
* @param array data - the data for the tag.
1300
* @return tag and data in XML.
1301
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
1303
string serialize_xml_tag(string tag, array data)
1310
DEBUG_XML("<"+tag+">");
1312
string xml = "<"+tag+">";
1314
if ( !arrayp(data) )
1315
return xml + "</"+tag+">";
1317
if ( functionp(data[ID_FUNC]) ) {
1321
o = get_local_object(data[ID_OBJECT]);
1323
f = o->find_function(data[ID_FUNC]);
1327
for ( int i = 0; i < sizeof(data[ID_PARAMS]); i++ ) {
1328
if ( objectp(data[ID_PARAMS][i]) )
1329
params += ({ data[ID_PARAMS][i]->this() });
1331
params += ({ data[ID_PARAMS][i] });
1336
if ( functionp(f) ) {
1344
if ( functionp(data[ID_CONV]) ) {
1346
xml += data[ID_CONV](v);
1349
FATAL("While serializing XML:\n"+err[0]+
1350
sprintf("%O", err[1]));
1353
else if ( mappingp(data[ID_CONV]) )
1356
foreach( v, object obj) {
1357
if ( data[ID_CONV]->name == "none" )
1358
xml += serialize_xml_object(obj, data[ID_CONV], false);
1360
xml += serialize_xml_object(obj, data[ID_CONV], true);
1363
else if ( mappingp(v) ) {
1364
foreach( indices(v), mixed ind ) {
1366
ENTRY->val = v[ind];
1367
if ( objectp(ind) && intp(data[ID_CONV][0]) ) {
1368
LAST->obj = THIS->obj;
1369
if ( data[ID_CONV]->name == "none" )
1370
xml += serialize_xml_object(ind, data[ID_CONV], false);
1372
xml += serialize_xml_object(ind, data[ID_CONV], true);
1376
foreach(indices(data[ID_CONV]), mixed idx) {
1377
xml += serialize_xml_tag(idx, data[ID_CONV][idx]);
1382
else if ( objectp(v) ) {
1383
LAST->obj = THIS->obj;
1384
xml += serialize_xml_object(v, data[ID_CONV], false);
1387
else if ( objectp(v) ) {
1390
else if ( stringp(v) || intp(v) )
1393
xml += "</"+tag+">\n";
1394
DEBUG_XML("</"+tag+">");
1400
* Serialize an object to XML using the xml description mapping 'mXML'.
1401
* The mapping defines what the xml code for the object should look like.
1403
* @param object obj - the object to serialize.
1404
* @param mapping mXML - xml description mapping.
1405
* @return xml code for object 'obj'.
1406
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
1407
* @see serialize_xml_tag
1410
serialize_xml_object(object obj, mapping mXML, bool|void obj_tag )
1412
object xml = String.Buffer();
1414
if ( !objectp(obj) )
1415
return "<!-- Null Object cannot be serialized -->";
1417
if ( !mappingp(mXML) )
1420
if (obj->status()<PSTAT_DISK) // broken instance already loaded
1421
return "<!-- Unable to load broken instance from DB -->";
1423
if (!functionp(obj->this)) // broken instance on first load
1426
THIS->obj = obj->this();
1427
ENV->obj = obj->get_environment();
1429
DEBUG_XML("serialize_xml_object(THIS="+THIS->obj->get_identifier()+",LAST="+
1430
(objectp(LAST->obj) ? LAST->obj->get_identifier():"NULL")+")");
1432
string tagname = mXML->name;
1433
if ( !stringp(tagname) )
1436
xml->add("<"+tagname+" type="+
1437
class_id_to_name(obj->get_object_class())+
1439
" selected=\"true\"":" selected=\"false\"")+
1442
for ( int i = 31; i >= 0; i-- ) {
1444
if ( (idx & obj->get_object_class()) && mappingp(mXML[idx]) )
1446
foreach(indices(mXML[idx]), string tag) {
1447
THIS->obj = obj->this();
1448
xml->add(serialize_xml_tag(tag, mXML[idx][tag]));
1453
xml->add("</"+tagname+">\n");
1458
* Show the content description of an object 'p'. For Documents it
1459
* will list the size and the mime-type. For Containers it lists the
1460
* html:index atribute for the containers index file.
1462
* @param object p - the content object
1463
* @return content description for the object.
1464
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
1466
string show_content(object p)
1468
if ( p->get_object_class() & CLASS_DOCUMENT )
1469
return "<size>"+p->get_content_size()+"</size>"+
1470
"<mime-type>"+p->query_attribute(DOC_MIME_TYPE) + "</mime-type>";
1471
if ( p->get_object_class() & CLASS_CONTAINER )
1472
return "<index>"+p->query_attribute("html:index") + "</index>";
1478
* show a simple mapping in compact form
1479
* each key is a tag, and the value its content
1481
* @param mapping of strings
1482
* @return xml form of the mapping
1483
* @author Martin B�hr
1485
string show_mapping(mapping(string:string) data)
1489
foreach(data; string key; string value)
1490
foreach(value/"\0";; string part)
1491
xml += sprintf("<%s><![CDATA[%s]]></%s>\n", key, part, key);
1496
* Get a path as a series of object tags in XML.
1498
* @param object p - the object to get the path for.
1499
* @return xml path description for the object.
1500
* @author <a href="mailto:astra@upb.de">Thomas Bopp</a>)
1502
string get_path(object p)
1504
object xml = String.Buffer();
1506
array(object|string) paths = ({ });
1509
while ( p != null ) {
1510
if ( stringp(s=_FILEPATH->check_tilde(p)) ) {
1511
paths = ({ p, s }) + paths;
1515
paths = ({ p, p->get_identifier() }) + paths;
1516
p = p->get_environment();
1519
for ( int i = 0; i < sizeof(paths)-2; i+=2 ) {
1520
xml->add("<object><id>");
1521
xml->add((string)paths[i]->get_object_id());
1522
xml->add("</id><name><![CDATA[");
1523
xml->add(paths[i+1]);
1524
xml->add("]]></name>");
1525
path += paths[i+1] + "/";
1526
xml->add("<path>"+no_uml(path)+"</path></object>");
1528
if ( paths[-2]->get_object_class() & CLASS_CONTAINER )
1529
path += paths[-1] + "/";
1533
xml += "<path>"+no_uml(path)+"</path>\n";
1538
* Get a path as a series of object tags in XML.
1540
* XML Description of returned value
1541
* <!Element path (object*)> <!-- sequence of objects in path -->
1542
* <!Element object (name, description, relpath)> <!-- data per object -->
1543
* <!Element name (#cdata)> <!-- attribute OBJ_NAME -->
1544
* <!Element description (#cdata)> <!-- attribute OBJ_DESC -->
1545
* <!Element relpath (#cdata)> <!-- relative path to object p -->
1547
* @param object p - the object to get the path for.
1548
* @return xml path description for the object.
1549
* @author <a href="mailto:balduin@upb.de">Ludger Merkens</a>)
1551
string get_rel_path(object p, void|int fsname)
1553
object xml = String.Buffer();
1555
array(object|string) paths = ({ });
1558
while ( p != null ) {
1559
if ( stringp(s=_FILEPATH->check_tilde(p)) ) {
1560
paths = ({ p, s }) + paths;
1566
p->query_attribute("fs_name") : p->get_identifier())
1568
p = p->get_environment();
1571
for ( int i = 0; i < sizeof(paths)-2; i+=2 ) {
1572
xml->add("<object><id>");
1573
xml->add((string)paths[i]->get_object_id());
1574
xml->add("</id><name><![CDATA[");
1575
xml->add(paths[i+1]);
1576
xml->add("]]></name><description><![CDATA[");
1577
xml->add(paths[i]->query_attribute(OBJ_DESC));
1578
xml->add("]]></description><relpath>");
1579
xml->add("../"*((sizeof(paths)-i)/2)+paths[i+1]);
1580
xml->add("</relpath></object>");
1581
path += paths[i+1] + "/";
1583
if ( paths[-2]->get_object_class() & CLASS_CONTAINER )
1584
path += paths[-1] + "/";
1588
xml += "<path>"+no_uml(path)+"</path>\n";
1593
* Get the neighbours of an object.
1594
* This function returns a XML part containing the left and right neighbours of
1595
* the object. The optional argument filterclass allows to find the neighbours
1596
* of the same objectclass only. (previous/next image, container)
1598
* XML Description of returned value
1599
* <!Element left (object*)> <!-- left neighbour -->
1600
* <!Element right (object*)> <!-- right neighbour -->
1601
* <!Element object (id, name, description)> <!-- information per object -->
1602
* <!Element id (#cdata)> <!-- decimal object id -->
1603
* <!Element name (#cdata)> <!-- attribute OBJ_NAME -->
1604
* <!Element description (#cdata)> <!-- attribute OBJ_DESC -->
1606
* @param object o - The object to calculate the neighbours for.
1607
* @param void|int filterclass - (bool)
1608
* @caveats This function doesn't regard the currently active sorting option of
1609
* the user but uses unsorted inventory always.
1611
* @author <a href="mailto:balduin@upb.de">Ludger Merkens</a>)
1613
string get_neighbours(object p, void|int filterclass, void|int fsname)
1615
DEBUG_XML(sprintf("get_neighbours %O, %d\n", p, filterclass));
1616
object env = p->get_environment();
1619
inv = env->get_inventory();
1622
inv = env->get_inventory_by_class(p->get_object_class());
1623
DEBUG_XML(sprintf("inv is %O\n", inv));
1625
int i = search(inv, p);
1626
object xml = String.Buffer();
1629
if (i>0) left = inv[i-1];
1630
if ((i!=-1) && (i<sizeof(inv)-1)) right = inv[i+1];
1635
xml->add("<object><id>");
1636
xml->add((string)left->get_object_id());
1637
xml->add("</id><name><![CDATA[");
1638
xml->add((string)left->get_identifier());
1639
xml->add("]]></name>");
1642
xml->add("<fsname>");
1643
xml->add((string)left->query_attribute("fs_name"));
1644
xml->add("</fsname>");
1646
xml->add("<description><![CDATA[");
1647
xml->add(left->query_attribute(OBJ_DESC));
1648
xml->add("]]></description></object>");
1650
xml->add("</left><right>");
1653
xml->add("<object><id>");
1654
xml->add((string)right->get_object_id());
1655
xml->add("</id><name><![CDATA[");
1656
xml->add((string)right->get_identifier());
1657
xml->add("]]></name>");
1660
xml->add("<fsname>");
1661
xml->add((string)right->query_attribute("fs_name"));
1662
xml->add("</fsname>");
1664
xml->add("<description><![CDATA[");
1665
xml->add(right->query_attribute(OBJ_DESC));
1666
xml->add("]]></description></object>");
1668
xml->add("</right>");
1674
void xml_describe(object node, int selected, int depth, string url,
1678
object o = node->get_object();
1679
function qa = o->query_attribute;
1682
xml->add((string)o->get_object_id());
1683
xml->add("</id>\n<name><![CDATA[");
1684
xml->add((string)o->get_identifier());
1685
xml->add("]]></name>\n");
1686
if (fsname = qa("fs_name"))
1688
xml->add("<fsname>");
1690
xml->add("</fsname>\n");
1692
xml->add("<description><![CDATA[");
1693
xml->add(qa(OBJ_DESC));
1694
xml->add("]]></description>\n<selected>");
1699
xml->add("</selected>\n<depth>");
1700
xml->add((string)depth);
1701
xml->add("</depth>\n<url><![CDATA[");
1703
xml->add("]]></url>\n");
1707
void xml_recurse(object root, int depth, int level, string url, int filter,
1710
xml->add("<object>\n");
1711
xml_describe(root, 0, level, url, xml);
1712
array(object) inv = root->get_inventory_by_class(filter);
1713
foreach(inv, object node)
1716
xml->add("<object>\n");
1717
xml_describe(node, 0, level,
1718
url + "/" + root->query_attribute(OBJ_NAME),
1720
xml->add("</object>\n");
1723
xml_recurse(node, depth-1, level+1,
1724
url + "/" + root->query_attribute(OBJ_NAME),
1727
xml->add("</object>\n");
1731
void xml_subtree(array(object) path, String.Buffer xml,
1732
int depth, int level, string url, int filter)
1734
object root = path[0];
1737
xml->add("<object>\n");
1738
xml_describe(root, 1, level, url, xml);
1740
object nextnode = sizeof(path) ? path[0] : 0;
1741
array(object) inv = root->get_inventory_by_class(filter);
1742
foreach(inv, object node)
1744
if (node == nextnode)
1745
xml_subtree(path, xml, depth-1, level+1,
1746
url+"/"+node->query_attribute(OBJ_NAME), filter);
1749
xml->add("<object>\n");
1750
xml_describe(node, 0, level+1,
1751
url + "/" + node->query_attribute(OBJ_NAME),
1753
xml->add("</object>\n");
1756
xml_recurse(node, depth-1 , level+1,
1757
url + "/" + node->query_attribute(OBJ_NAME),
1760
xml->add("</object>\n");
1763
string get_rel_tree(object root, object leaf, int depth, int filter)
1765
array(object) path = ({ leaf });
1768
while (node && node!=root)
1770
node = node->get_environment();
1772
path = ({ node }) + path;
1775
return "<relpath></relpath>";
1777
object xml = String.Buffer();
1778
xml_subtree(path, xml, depth, 0, "", filter);
1785
* Get the public path of an object.
1786
* This calculation uses the public "url" of its closest published parent and
1787
* combines this with the relative path from this object to its published parent.
1789
* @param object o - The object to get the path for.
1790
* @return (string) The public path of the object
1791
* @author <a href="mailto:balduin@upb.de">Ludger Merkens</a>)
1793
string get_public_name(object o)
1799
sPublicPath = o->get_identifier();
1800
while ((x=x->get_environment()) && !(sPublicRoot = x->query_attribute("url")))
1803
sPublicPath = x->get_identifier() + "/" + sPublicPath;
1807
return combine_path(sPublicRoot, sPublicPath);
1814
* Get the XML representation of this object. To speed up things, the
1815
* type selects which part of the data should be xmlified.
1817
* @param obj - the object to convert
1818
* @param type - the type of the object
1819
* @return the xml data
1820
* @author Thomas Bopp (astra@upb.de)
1822
string get_xml(object obj, object xsl, void|mapping vars, mixed|void active)
1824
object xml = String.Buffer(32468);
1831
if ( mappingp(vars) && vars->this_user > 0 )
1832
user = find_object(vars->this_user);
1836
if ( !objectp(user) )
1839
object pike = xsl->query_attribute(DOC_XSL_PIKE);
1840
if ( objectp(xsl) && objectp(pike) ) {
1843
object inst = pike->get_instance();
1844
if ( objectp(inst) ) {
1845
err = catch(res=inst->xmlify(obj, vars));
1847
mixed errerr = catch {
1848
array lines = pike->get_content() / "\n";
1851
string outp = sprintf("%O", err[1][-1]);
1852
sscanf(outp, "%*s.pike:%d, %s,%*s", line, func);
1853
err[0] += (lines[line-3..line+3]*"\n");
1856
FATAL("Error modifying error in xml_converter.pike: %O",
1867
selection = user->query_attribute(USER_SELECTION);
1868
if ( !arrayp(selection) )
1870
mSelection = mkmapping(selection, selection);
1878
"path": ({ CONV, "get_path", ({ THIS }), 0 }),
1879
"user": ({ 0, this_user, ({ }), userXML }),
1880
])+objXML[CLASS_OBJECT],
1883
"inventory": ({ THIS, "get_inventory", ({ }),
1884
objXML+exitXML+linkXML+userXML+containerXML}),
1888
if ( objectp(xsl) && mappingp(xsl->get_xml_structure()) ) {
1889
mXML = xsl->get_xml_structure();
1890
if ( equal(mXML, ([ ])) ) {
1891
xsl->load_xml_structure();
1892
mXML = xsl->get_xml_structure();
1895
if ( equal(mXML, ([ ])) )
1896
THROW("No XML Description found for Stylesheet !", E_ERROR);
1898
THIS_USER->obj = user;
1903
if (!mappingp(vars))
1908
foreach(indices(params), string p) {
1911
sscanf(vars[p], "%d", d);
1912
if ( (string)d == vars[p] ) {
1913
if ( objectp(params[p]->val) )
1914
params[p]->val = find_object(d);
1919
params[p]->val = vars[p];
1922
params[p]->val = params[p]->def;
1926
if ( intp(active) && active > 0 ) {
1927
ACTIVE->obj = find_object(active);
1930
if ( vars->type == "annotations" ||
1931
obj->get_object_class() & CLASS_MESSAGEBOARD )
1933
object from_obj = get_var("from_obj", 1);
1934
array annotations = obj->get_annotations_for(
1936
(int)get_var("from_obj", 1)->val,
1937
(int)get_var("to_obj", 20)->val);
1938
if ( sizeof(annotations) > 0 )
1939
ACTIVE->obj = annotations[0];
1943
if ( objectp(ACTIVE->obj) ) {
1944
activeThreadMap = ([ ACTIVE->obj: 1, ]);
1945
object ann = ACTIVE->obj->get_annotating();
1946
while ( objectp(ann) ) {
1947
activeThreadMap[ann] = 1;
1948
ann = ann->get_annotating();
1952
DEBUG_XML("XML:Convertor - Using\n"+sprintf("%O", mXML));
1954
xml->add( "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
1955
xml->add( serialize_xml_object(obj, mXML, true) );
1957
string result = xml->get();
1961
bool check_swap() { return false; }
1962
string get_identifier() { return "Converter:XML"; }
1963
function find_function(string f) { return this_object()[f]; }
1965
object get_var(string name, mixed val)
1967
object param = params[name];
1968
if ( !objectp(param) ) {
1971
if ( !stringp(val) ) {
1976
sscanf(val, "%d", v);
1977
if ( (string)v == val ) {
1987
params[name] = param;
1994
// try images folder...
1995
object images = find_object("/images");
1996
if ( !objectp(images) )
2001
inv = get_cont_inventory(images, 1, 15);
2002
if ( sizeof(inv) != 15 ) // no rooms in image container
2003
error("Test failed - from 1 to 15 are not 15 objects");
2005
foreach(inv, object obj) {
2006
if ( !(obj->get_object_class() & CLASS_CONTAINER) )
2008
if ( !containers && obj->get_object_class() & CLASS_CONTAINER )
2009
error("Containers not correctly sorted");
2012
object rxml = get_factory(CLASS_DOCUMENT)->execute(
2013
([ "name": "rxml.html", ]));
2014
rxml->set_content("<html><body><xslt object='/home/sTeam/bugs' "+
2015
"xsl='/stylesheets/annotations.xsl'/></body></html>");
2016
XSL->vars = ([ "__internal": ([ ]), ]);
2017
return get_obj_content_rxml(rxml);