object $root var $root manager $root var $root owners [$core] var $root writable [$root] var $root readable ['parameters, 'methods, 'code] var $root trusted [] var $root owned [] var $root child_index 0 var $root fertile 0 var $root inited 0 var $root info ["The root object is the ultimate parent of all objects. It defines beahvior of all objects. It controls initialization, deinitialization, creation, destruction, and identification of objects, as well as permission checking, and ownership."] var $root quota 75000 var $root dbref 'root method init_root (> .perms(caller(), $root) <); child_index = 0; fertile = 0; // for now set all the ownership stuff as this(), it can be reset later. manager = this(); owned = [this()]; owners = [this()]; writable = []; readable = ['parameters, 'methods, 'code]; . method uninit_root var obj, x, objs; (> .perms(caller(), $root) <); objs = []; catch any { for obj in (owned) { if (obj == this()) continue; catch any { if ((obj.manager()) == this()) { for x in (obj.owners()) { if (valid(x) && (x != this())) objs = [@objs, x]; } obj.chown([$reaper, @objs]); obj.set_manager($reaper); } } with handler { // this is getting redundant, but there is a reason for it. (| obj.chown([$reaper]) |); (| obj.del_owner(this()) |); $reaper_log.log(("$root.uninit_root(): Unable to give " + (obj.dbref())) + " an owner."); } } for obj in (owners) (| obj.del_owned_obj(this()) |); } with handler { $brandon.tell("Traceback from $root.uninit_root()"); $brandon.tell_traceback(traceback()); } . method initialize disallow_overrides; var ancestors, ancestor, method_name, pos; if ((caller() != $sys) && (sender() != this())) throw(~perm, "Caller is not $sys and sender is not this."); if (inited) throw(~perm, "Already initialized."); ancestors = ancestors(); for pos in [0 .. listlen(ancestors) - 1] { ancestor = ancestors[listlen(ancestors) - pos]; method_name = tosym("init_" + tostr(ancestor.dbref('symbol))); catch ~methodnf { if (find_method(method_name) != ancestor) throw(~perm, ((("Initialization method for " + (ancestor.namef('ref))) + " in wrong place. Found on ") + (find_method(method_name).namef('ref))) + "."); .(method_name)(); } } inited = 1; . method uninitialize disallow_overrides; var ancestor, owner, obj; .perms(caller(), $root, $sys); for ancestor in (ancestors()) (| .(tosym("uninit_" + tostr(ancestor.dbref('symbol))))() |); . method perms disallow_overrides; arg what, [args]; var obj, flag, second; if (type(what) == 'dbref) what = [what]; if (!args) args = ['writer]; if (type(args[1]) == 'symbol) { for flag in (args) { switch (flag) { case 'this: for obj in (what) { if ((obj != this()) && (!($sys.is_system(obj)))) throw(~perm, ("Permission Denied: " + (obj.dbref())) + " is not this.", obj); } case 'system: for obj in (what) { if (!($sys.is_system(obj))) throw(~perm, ("Permission Denied: " + (obj.dbref())) + " is not of the system.", obj); } case 'manager: for obj in (what) { if (((.manager()) != obj) && (!($sys.is_system(obj)))) throw(~perm, ("Permission Denied: " + (obj.dbref())) + " is not the manager.", obj); } case 'trusts: for obj in (what) { if (!(.trusts(obj))) throw(~perm, ("Permission Denied: " + (obj.dbref())) + " is not a trustee.", obj); } case 'parser: // This should be removed sometime. for obj in (what) { if ((!(obj.has_ancestor($user_parsers))) && (obj != this())) throw(~perm, ("Permission Denied: " + (obj.dbref())) + " is not a parser.", obj); } default: for obj in (what) { if (!(.is_writable_by(obj))) throw(~perm, ("Permission Denied: " + (obj.dbref())) + " is not a writer.", obj); } } } } else { for obj in (what) { if (!(obj in args)) throw(~perm, ((obj.dbref()) + " is not one of: ") + ($list.to_english($list.map(args, 'namef, 'ref))), obj); } } . method _change_parents disallow_overrides; arg parents; var old, init, uninit, ancestor, pos; (> .perms(caller(), $root) <); if (!parents) throw(~noparents, "Objects must have at least 1 parent"); // Perform the actual change. old = ancestors(); (> $sys.change_sender_parents(parents) <); // Figure out new ancestors to initialize, and old ones to uninitialize. init = []; uninit = old; for ancestor in (ancestors()) { uninit = setremove(uninit, ancestor); if (!(ancestor in old)) init = [@init, ancestor]; } // Initialize the new ancestors. catch any { for ancestor in (init) { catch ~methodnf { .(tosym("init_" + tostr(ancestor.dbref('symbol))))(); } } } with handler { // Initialization error; deinitialize parents we initialized, and fall // back to old parents. pos = ancestor in init; for ancestor in (sublist(init, 1, pos)) (| .(tosym("uninit_" + tostr(ancestor.dbref('symbol))))() |); $sys.change_sender_parents(old); throw(~init, "Failed to initialize new ancestors."); } // Uninitialize the old ancestors. $sys.change_sender_parents(setremove(old, this())); for ancestor in (uninit) (| .(tosym("uninit_" + tostr(ancestor.dbref('symbol))))() |); $sys.change_sender_parents(parents); . method chparents arg parents; var parent; if (!(| .perms(sender(), 'manager) |)) (> .perms(caller(), $root, $sys) <); if (!parents) throw(~noparents, "There must be at least 1 parent for each object."); // Notify parents of impending change. for parent in (parents) (> parent.will_inherit(sender()) <); // Everything's okay, go ahead and try it. ._change_parents(parents); . method will_inherit arg obj; // Throw an error if it's not okay for obj to inherit from us. if ((!fertile) && ((!(.trusts(obj))) && (!(obj.has_ancestor(this()))))) throw(~perm, "Refuse to be parent of prospective child."); . method manager disallow_overrides; return manager; . method owners disallow_overrides; return owners; . method writers disallow_overrides; return writable + [manager, this()]; . method trusted return (trusted ? trusted | []) + [this()]; . method is_writable_by disallow_overrides; arg obj; return (| obj in (.writers()) |) || ($sys.is_system(obj)); . method is_readable_by disallow_overrides; arg obj; // will eventually get this working with lock frobs, for now // ,readable is a simple list of what everyone can read: // 'methods, 'parameters, 'code if (.trusts(obj)) return ['methods, 'parameters, 'code]; else return readable; . method trusts arg obj; return (| obj in (.trusted()) |) || ((.is_writable_by(obj)) || ($sys.is_system(obj))); . method fertile disallow_overrides; return fertile; . method set_fertile arg val; (> .perms(sender(), 'manager) <); fertile = val ? 1 | 0; . method set_manager disallow_overrides; arg obj; (> .perms(sender(), 'manager) <); if (type(obj) != 'dbref) throw(~type, "Managers must be given as a single dbref."); manager = obj; . method set_writable disallow_overrides; arg what; .perms(sender(), 'manager); writable = what; . method add_writer disallow_overrides; arg what; (> .perms(sender(), 'manager) <); writable = [@writable, what]; . method del_writer disallow_overrides; arg what; (> .perms(sender(), 'manager) <); writable = setremove(writable, what); . method set_readable disallow_overrides; arg what; (> .perms(sender(), 'manager) <); readable = what; . method set_trusted disallow_overrides; arg what; (> .perms(sender(), 'manager) <); trusted = what; . method add_trusted disallow_overrides; arg what; (> .perms(sender(), 'manager) <); trusted = [@trusted, what]; . method del_trusted disallow_overrides; arg what; (> .perms(sender(), 'manager) <); trusted = setremove(trusted, what); . method as_this_run arg obj, method, [args]; // run with this()'s perms -- unless they have changed .trusts, // it should just check against writers. if (!(.trusts(sender()))) throw(~perm, "Sender not allowed to gain access to object perms."); return (> obj.(method)(@args) <); . method add_parent arg parent; (> .perms(sender(), 'manager) <); if (parent in (.parents())) throw(~parent, (((.dbref()) + " already has ") + (parent.namef('ref))) + " as a parent"); if (!valid(parent)) throw(~type, "Not a valid parent, must send a dbref or pointer"); .chparents((.parents()) + [parent]); . method del_parent arg parent; var parents; (> .perms(sender(), 'manager) <); if (!valid(parent)) throw(~type, "Not a valid parent, must send a dbref or pointer"); parents = .parents(); if (!(parent in parents)) throw(~parentnf, "No such parent as " + ($data.unparse(parent))); parents = setremove(parents, parent); (> .chparents(parents) <); . method spawn arg [suffix]; var obj, tmp, dbref, owner, mngr, na; // will later adjust this for .is_readable_by() // use this rather than $string.non_alphanumeric because it doesn't // have '_' na = "!@#$%^&*()+-=~`'{}[]|/?\"\\,.<>;: "; if ((!fertile) && (((.is_readable_by(sender())) != ['methods, 'parameters, 'code]) && (!($sys.is_system(sender()))))) throw(~perm, "Not fertile or readable."); owner = sender(); // Figure out the suffix from the arguments and child index. if (!(owner.quota_valid())) throw(~quota, "Sender does not have the available quota"); if (suffix) { suffix = suffix[1]; // so they dont confuse child_index: if ($string.is_numeric(suffix)) throw(~perm, "Can't specify a numeric suffix."); // so we get correct symbols & it is always lowercase: suffix = $string.strip(suffix, na); } else { // make sure it doesn't exist already: dbref = tostr(.dbref('symbol)); tmp = .dbref('symbol); while ((| get_objnum(tmp) |)) { child_index = child_index + 1; tmp = tosym((dbref + "_") + tostr(child_index)); } suffix = tostr(child_index); } // Ask the system object for a child. obj = $sys.spawn_sender(suffix, owner); return obj; . method destroy disallow_overrides; // This doesn't actually destroy us immediately, but we will go away when // nothing is holding onto us any more. (> .perms(sender(), 'manager) <); (| .uninitialize() |); $sys.destroy_sender(); . method add_parameter arg name, [args]; var tmp, kid; // .add_parameter('name[, default-value, 'inherit]) // Add the given parameter to this object. // if 'default-value' is included, initialize the variable to that value // if 'inherit is given the value is initialized on all descendents (> .perms(sender()) <); (> add_parameter(name) <); // The following code is a kludge as we can't send a default value to the // primitive. if (args) { tmp = tosym((("__set_" + tostr(name)) + "_") + tostr(random(1000))); catch any { compile([((tostr(name) + " = ") + toliteral(args[1])) + ";"], tmp); .(tmp)(); if ((listlen(args) > 1) && ((args[2]) == 'inherit)) { for kid in (.descendants()) kid.(tmp)(); } del_method(tmp); } with handler { del_method(tmp); rethrow(error()); } } . method parameters (> .perms(sender(), 'this) <); return parameters(); . method del_parameter arg name; (> .perms(sender()) <); (> del_parameter(name) <); . method del_method arg name; (> .perms(sender()) <); (> del_method(name) <); . method methods disallow_overrides; if (!('methods in (.is_readable_by(sender())))) throw(~perm, ((sender().dbref()) + " doesn't have permission to find methods on ") + (.dbref())); return methods(); . method parents disallow_overrides; return parents(); . method children disallow_overrides; return children(); . method ancestors disallow_overrides; return ancestors(); . method find_method disallow_overrides; arg name; if (!('methods in (.is_readable_by(sender())))) throw(~perm, ((sender().dbref()) + " doesn't have permission to find methods on ") + (.dbref())); return (> find_method(name) <); . method find_next_method disallow_overrides; arg name, after; if (!('methods in (.is_readable_by(sender())))) throw(~perm, ((sender().dbref()) + " doesn't have permission to find methods on ") + (.dbref())); return (> find_next_method(name, after) <); . method list_method arg [args]; if (!('code in (.is_readable_by(sender())))) throw(~perm, (("Method code on " + (.namef('ref))) + " is not readable by ") + (sender().namef('ref))); return (> list_method(@args) <); . method compile arg code, name; // allow overrides -- may be a problem... (> .perms(sender()) <); return compile(code, name); . method show disallow_overrides; var output, actor, data, parent, readable, m, p, x, line; actor = sender(); readable = .is_readable_by(actor); data = $sys.sender_data(); // the beginning. output = ((("Object: " + (.namef('ref))) + " [") + tostr(.size())) + " bytes]"; output = [output, "Parents: " + ($data.unparse(parents()))]; // Methods if ('methods in readable) { output = output + ["Methods:"]; for m in (.method_info()) { output = output + [(((" " + tostr(m[2])) + "(") + (m[3])) + ")"]; pause(); } } else { output = output + [" ** No permission to list Methods **"]; } // Parameters if ('parameters in readable) { for parent in (data) { if (valid(parent[1])) { output = output + [((parent[1]).namef('xref)) + " Parameters:"]; if ('parameters in ((parent[1]).is_readable_by(actor))) { for p in (parent[2]) { line = ((" " + tostr(p[1])) + ": ") + ($data.unparse(p[2])); output = output + [line]; } } else { output = output + [" ** Permission Denied **"]; } } else { output = output + [toliteral(parent[1]) + " Parameters:"]; for p in (parent[2]) { line = ((" " + tostr(p[1])) + ": ") + ($data.unparse(p[2])); output = output + [line]; } } pause(); } } else { output = output + [" ** No permission to list Parameters **"]; } // Return what we've got. return output; . method has_ancestor disallow_overrides; arg obj; return has_ancestor(obj); . method eval disallow_overrides; arg code, [dest]; var errors, result; dest = dest ? dest[1] | this(); (> .perms(sender()) <); // Compile the code. errors = .compile(code, 'tmp_eval); if (errors) return ['errors, errors, 0, 0]; // Evaluate the expression. Be sure to remove it afterwards, so that no // one else can call it. catch any { result = dest.tmp_eval(); } with handler { del_method('tmp_eval); rethrow(~methoderr); } del_method('tmp_eval); return ['result, result]; . method method_info arg [args]; var filter, maxp, anc, ancs, method, methods_found; // lists methods on objects which are ancestors of this and parents of args[1] // method info items are of the form: // [$definer, 'method, "args", "flags", "first comment/return value"] if (!('methods in (.is_readable_by(sender())))) throw(~perm, (("Method code on " + (.namef('ref))) + " is not readable by ") + (sender().namef('ref))); if (args) { maxp = args[1]; args = delete(args, 1); } if (listlen(args) >= 2) { filter = sublist(args, 1, 2); args = delete(delete(args, 1), 1); } else { filter = [$misc, '_null_method_filter]; } methods_found = []; ancs = .ancestors(); if (!(maxp in ancs)) { maxp = this(); ancs = [this()]; } for anc in (ancs) { if (anc.has_ancestor(maxp)) { for method in (anc.methods()) { if ((filter[1]).(filter[2])(anc, method, @args)) methods_found = [@methods_found, ._get_method_info(anc, method)]; } } } return methods_found; . method parameter_info arg [args]; var data, pattern, max_parent, pparams, param; // data() reformated as // [[$parent,'param,val],...] if (!('parameters in (.is_readable_by(sender())))) throw(~perm, (("Parameters on " + (.dbref())) + " are not readable by ") + (sender().dbref())); max_parent = [@args, this()][1]; data = []; for pparams in ($list.reverse($sys.sender_data())) { if (valid(pparams[1]) && ((pparams[1]).has_ancestor(max_parent))) { for param in (pparams[2]) data = [@data, [pparams[1], @param]]; } } return data; . method data disallow_overrides; var par, data, out; if (!('parameters in (.is_readable_by(sender())))) throw(~perm, ((sender().namef('ref)) + " is not allowed to read parameters on ") + (.namef('ref))); data = $sys.sender_data(); out = #[]; for par in (data) { // if the parent doesn't exist anymore, just let them see the data. if ((!valid(par[1])) || ('parameters in ((par[1]).is_readable_by(sender())))) out = dict_add(out, par[1], par[2]); else out = dict_add(out, par[1], ["*** Permission Denied ***"]); } return out; . method size disallow_overrides; arg [args]; args = [@args, 'int][1]; switch (args) { case 'string: return tostr(size()); case 'english: return $int.to_english(size()); default: return size(); } . method descendants disallow_overrides; var kid, kids; // .descendants() // -> Recursive list of all children of this object -- try not to use kids = children(); for kid in (kids) kids = union(kids, kid.descendants()); return kids; . method get_quota disallow_overrides; return quota; . method owned disallow_overrides; return owned; . method quota_valid disallow_overrides; // if (!.has_ancestor($user) && !$sys.is_admin(this())) // return 0; // will put quota checking in here return 1; . method del_owned_obj disallow_overrides; arg obj; (> .perms(caller(), $root) <); owned = setremove(owned, obj); . method add_owned_obj disallow_overrides; arg obj; (> .perms(caller(), $root, $sys) <); if (obj in owned) throw(~addowned, ((.namef('ref)) + " already owns ") + (obj.namef('ref))); owned = [@owned, obj]; . method match_children arg string; var children, child_names, c; children = .children(); child_names = $list.map(children, 'namef); // direct matches first. for c in (child_names) { if (c == string) return children[c in child_names]; } // ok, try partial matches for c in (child_names) { if (match_begin(c, string)) return children[c in child_names]; } return 0; . method set_info arg text; (> .perms(sender(), 'manager) <); info = text; . method info return info; . method _display_descendants arg space, checked, base; var space, checked, c, anc, biguglylist, id, perms; perms = ""; if (fertile) perms = "F"; for c in (.readable()) perms = perms + (tostr(c)[1]); id = (space + (.namef('xref))) + (perms ? (" [" + perms) + "]" | perms); for anc in (checked) { if (.has_ancestor(anc)) return [id + " (above)"]; } if (listlen(.parents()) > 1) id = id + " (MI)"; else id = id + ""; biguglylist = [id]; space = space + " "; // check children if ((!base) || (base != this())) { for c in (.children()) { biguglylist = biguglylist + (c._display_descendants(space, checked, base)); checked = setadd(checked, c); pause(); } } return biguglylist; . method _display_ancestors arg [args]; var space, checked, c, anc, biguglylist, id, perms; space = args ? args[1] | ""; checked = (listlen(args) > 1) ? args[2] | []; perms = ""; if (fertile) perms = "F"; for c in (.readable()) perms = perms + (tostr(c)[1]); id = (space + (.namef('ref))) + (perms ? (" [" + perms) + "]" | perms); for anc in (checked) { if (.has_ancestor(anc)) return [id + " (above)"]; } if (listlen(.parents()) > 1) id = id + " (MI)"; else id = id + ""; biguglylist = [id]; space = space + " "; // check children for c in (.parents()) { biguglylist = biguglylist + (c._display_ancestors(space, checked)); checked = setadd(checked, c); pause(); } return biguglylist; . method _get_method_info disallow_overrides; arg anc, method; var code, lines, dis_flag, meth_args, first_comment; code = anc.list_method(method); lines = listlen(code); if (lines > 5) code = sublist(code, 1, 5); dis_flag = 0; if (code) { if ("disallow_overrides;" == (code[1])) { dis_flag = 1; code = delete(code, 1); } if (code && ((code[1]) && (((code[1])[1]) == "a"))) { meth_args = match_pattern("arg *;", code[1])[1]; code = delete(code, 1); } else { meth_args = ""; } if (code && ((!(code[1])) || (((code[1])[1]) == "v"))) code = delete(code, 1); if (code && ((!(code[1])) || (((code[1])[1]) == "v"))) code = delete(code, 1); first_comment = code ? (code[1]) + " " | " "; first_comment = (((first_comment[1]) == "/") || ((first_comment[1]) == "r")) ? first_comment | ""; } else { meth_args = ""; first_comment = ""; } return [anc, method, meth_args, dis_flag, lines, first_comment]; . method namef arg [args]; var output, type, part; if (!args) args = [['dbref]]; if (((args[1]) == 'ref) || ((args[1]) == 'xref)) args = [['dbref]]; // the actual switch, punctuation is treated oddly (parens specifically) output = ""; for part in (args) { type = type(part); if (type == 'list) output = output + ((| .(part[1])(@sublist(part, 2)) |) || ""); else if (type == 'string) output = output + part; } return output; . method match_descendants arg string; var match, child; match = .match_children(string); if (match) return match; for child in (.children()) { match = child.match_descendants(string); if (match) return match; } return 0; . method readable return readable; . method chown disallow_overrides; arg new_owners; var old_owners, obj, sofar, this; // must be called to add/del/change any ownership. (> .perms(sender(), .manager(), @$sys.system()) <); // make sure the new owners list is legit. if (type(new_owners) != 'list) throw(~type, "New owners must be given as a list of objects"); if (!($sys.is_system(sender()))) { for obj in (new_owners) { if (!(obj.has_ancestor($user))) throw(~perm, (obj.namef('ref)) + " is not a user object."); } } // few basic (re)settings old_owners = $list.flatten(owners); new_owners = $list.flatten(new_owners); owners = []; this = this(); sofar = []; // first make it so nobody owns it. for obj in (old_owners) (| obj.del_owned_obj(this) |); // set all the new owners for obj in (new_owners) { catch any { obj.add_owned_obj(this); } with handler { if (error() == ~addowned) continue; // didn't work out, set it back the way it was. for obj in (sofar) (| obj.del_owned_obj(this) |); for obj in (old_owners) { if ((| obj.add_owned_obj(this) |)) owners = [@owners, obj]; } throw(~chown, "Unable to add %O as an owner, chown unsuccessful.", obj); } sofar = [@sofar, obj]; } owners = new_owners; . method debug arg [stuff]; var x, line, mngr; line = (sender().dbref()) + " debug:"; for x in (stuff) line = (line + " ") + ((type(x) == 'string) ? x | ($data.unparse(x))); (| (.manager()).tell(line) |); . method set_quota arg value; (> .perms(caller(), $user, @$sys.system(), $root) <); quota = value; . method dbref arg [args]; args = [@args, 'string][1]; switch (args) { case 'string: return "$" + tostr(dbref); case 'symbol: return dbref; default: throw(~type, "args must be 'string or 'symbol."); } . method set_dbref arg new_dbref; var old_dbref; // Only accept calls from owners or admins. if (!(.is_writable_by(sender()))) throw(~perm, "Sender not an owner."); // Make sure first argument is a symbol. if (type(new_dbref) != 'symbol) throw(~type, "New dbref is not a symbol."); // Make sure everything is lowercase. new_dbref = tosym(lowercase(tostr(new_dbref))); // Do nothing if new_dbref isn't different. if (new_dbref == dbref) return; // Grab the new dbref (> $sys.assign_dbref(new_dbref) <); old_dbref = dbref; dbref = new_dbref; // If we already had a dbref, get rid of the old one. if (old_dbref) (> $sys.deassign_dbref(old_dbref) <); . method name arg [args]; return .dbref(); . method del_owner disallow_overrides; arg owner; (> .perms(caller(), $root) <); if (listlen(owners) != 1) owners = setremove(owners, owner); else .chown([$no_one]); . method add_owner disallow_overrides; arg owner; (> .perms(caller(), $root) <); owners = [@owners, owner]; . method generate_html arg [args]; var actor, readable, name, out, line, obj, col, colx, objs, x; actor = sender(); readable = .is_readable_by(actor); name = .namef('ref); out = ["<head>", ("<title>" + name) + "</title>", "<center>"]; out = [@out, ("<h1>" + name) + "</h1>", "</center>"]; out = [@out, "<hr width=50% align=middle>", "<body>"]; line = ("<a href=\"/bin/show?" + tostr(.dbref('symbol))) + "\">"; out = [@out, ("<center>" + line) + "show this object.</a></center>"]; line = []; for obj in (.parents()) line = [@line, $http.make_href_string(obj)]; out = [@out, "<P>Parent(s): " + ($list.to_english(line)), "<pre>"]; // duplicate the $code.generate_family_listing code because we // want to put in hrefs. objs = .children(); if (objs) { out = [@out, "Children:"]; col = ((| sender().linelen() |) || 79) / 8; colx = col * 3; line = pad("Name", colx + 2) + pad(" Perms", col - 2); out = [@out, (line + pad("Size ", -col)) + "Manager"]; for obj in (objs) { name = obj.namef('xref); line = $http.make_href_string(obj, pad(name, colx + 2)); line = line + pad($object.see_perms(obj), col - 2); line = line + pad(tostr(obj.size()) + " ", -col); x = obj.manager(); if (!valid(x)) name = pad(("** invalid object *(" + tostr(x)) + ") **", colx); else name = $http.make_href_string(x, pad(x.namef('xref), colx)); line = line + name; out = [@out, line]; } } out = [@out, "</pre>"]; if (info) { if (type(info) == 'frob) out = [@out, info.translate_to("text/html")]; else out = [@out, "<hr width=50% align=middle>", @info]; } return out; . method show_in_html disallow_overrides; var out, actor, data, parent, readable, m, p, x, line; // duplicating code in .show because I want it to be htmlified actor = sender(); readable = .is_readable_by(actor); data = $sys.sender_data(); // the beginning. out = "Object: " + ($http.make_object_href(this(), .namef('ref))); out = ((out + " [") + tostr(.size())) + " bytes]"; line = []; for x in (.parents()) line = [@line, $http.make_object_href(x)]; out = [out, "Parent(s): " + ($list.to_english(line)), "<pre>"]; // Methods if ('methods in readable) { out = out + ["Methods:"]; for m in (.method_info()) out = out + [" " + ($http.make_method_href(m))]; } else { out = out + [" ** No permission to list Methods **"]; } // Parameters if ('parameters in readable) { for parent in (data) { // because the server is FKD we have to make sure your params // all have valid parents: if (valid(parent[1])) { out = out + [((parent[1]).namef('xref)) + " Parameters:"]; if ('parameters in ((parent[1]).is_readable_by(actor))) { for p in (parent[2]) { line = ((" " + tostr(p[1])) + ": ") + (($http.filter_text([$data.unparse(p[2])]))[1]); out = out + [line]; } } else { out = out + [" ** Permission Denied **"]; } } else { out = out + ["(Invalid parent-object You cannot reference because it's broke) Parameters:"]; for p in (parent[2]) { line = ((" " + tostr(p[1])) + ": ") + (($http.filter_text([$data.unparse(p[2])]))[1]); out = out + [line]; } } } } else { out = out + [" ** No permission to list Parameters **"]; } // Return what we've got. return out; . method quota return quota; . method quota_byte_usage var total, obj; // perm checking goes here for obj in (.owned()) total = total + (obj.size()); return total; . method __docore owned = [this()]; .