/* * SPL - The SPL Programming Language * Copyright (C) 2004, 2005 Clifford Wolf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * splcms.webspl: SPLCMS Editing Backend */ #define ENABLE_DEBUG 0 load "wsf"; load "wsf_display"; load "wsf_action"; load "xml"; load "encode_xml"; load "file"; load "system"; load "uuidgen"; if (ENABLE_DEBUG) load "webdebug"; var tree_initialized; var tree_opened_hash; var current_edit; var copy_buffer_xml; var copy_buffer_name; function do_render() { #file-as-code render.spl } function tree() { var classes = xml_parse(file_read("classes.xml")); var data = xml_parse(file_read("data.xml")); var html = "\n
"; var action_id = 0; if (not tree_initialized) { tree_opened_hash[data["/*/@uuid"]] = 1; tree_initialized = 1; } function worker(node, depth) { var clsname = data[node].name; var clsdecl = classes["/classes/class[@name='$clsname']"].node; var title = clsdecl["title"].innerxml =~ e/{(.*?)}/Rg node[$1]; var uuid = node["@uuid"]; if (uuid ~== current_edit) title = "$title"; for (var i=0; i "; action("action${action_id++}", function() { if (declared tree_opened_hash[uuid]) delete tree_opened_hash[uuid]; else tree_opened_hash[uuid] = 1; }); } else html ~= " "; html ~= "$title
\n"; action("action${action_id++}", function() { current_edit = uuid; page.root.child_set("edit", new WsfAction(edit, uuid: uuid)); }); if (declared tree_opened_hash[uuid]) { foreach[] child (node["*"].nodes) { var childname = data[child].name; if (defined clsdecl["child[@name='$childname']"].node) worker(child, depth+1); } } } worker(data["/*"].node, 0); html ~= <:> :

:   : (Re-)Render the HTML files
:   : View the webpage
:

: ; action("action${action_id++}", function() { do_render(); }); return html; } function edit() { var uuid = template_options.uuid; var classes = xml_parse(file_read("classes.xml")); var data = xml_parse(file_read("data.xml")); var node = data["//*[@uuid = '$uuid']"].node; var clsname = node["."].name; var clsdecl = classes["/classes/class[@name='$clsname']"].node; var pclsname = node[".."].name; var pclsdecl = classes["/classes/class[@name='$pclsname']"].node; var possible_i, possible_a; foreach[] p (clsdecl["child"].nodes) { var name = p["@name"]; possible_i[name] = 1; } if (defined pclsdecl) { foreach[] p (pclsdecl["child"].nodes) { var name = p["@name"]; possible_a[name] = 1; } } var title = clsdecl["title"].innerxml =~ e/{(.*?)}/Rg node[$1]; var html = <:> : :
:

$title

:
: : ; foreach[] p (clsdecl["param"].nodes) { var type = p["@type"]; var name = p["@name"]; var desc = p["@desc"]; var widget = p["@widget"]; var value = p["."]; var whtml; if (type ~== "attribute") value = node["@$name"]; if (type ~== "element" and name ~== "") value = node["."]; if (type ~== "element" and name ~!= "") value = node[name]; if (widget =~ /^line$/) whtml = <:> : ; if (widget =~ /^line:(\d+)$/) whtml = <:> : ; if (widget =~ /^area:(\d+)$/) whtml = <:> : ; if (widget =~ /^select$/) whtml = <:> : ; if (widget =~ /^file$/) whtml = <:> :
: ; html ~= <:> : : : : ; } var enable_delete = defined pclsdecl; var enable_paste_i = defined copy_buffer_xml && declared possible_i[copy_buffer_name]; var enable_paste_a = defined copy_buffer_xml && declared possible_a[copy_buffer_name]; html ~= <:> :
${xml::desc}:$whtml
: : : : : : : : : : : ; var create_sep = "
"; if (defined (next possible_i, undef)) { html ~= <:> :
:$create_sep :
: :Create new object in this object:
: : ; create_sep = ""; } if (defined (next possible_a, undef)) { html ~= <:> :
:$create_sep :
: :Create new object after this object:
: : ; create_sep = ""; } html ~= <:> :
: ; action("save", function() { var data = xml_parse(file_read("data.xml")); var newxml = "<$clsname uuid=\"$uuid\""; function get_param(name) { var value = cgi.param["param_$name"]; if (declared cgi.param["file_$name"]) { var file_uuid = uuidgen(); var file_name = cgi.param["file_$name"]; file_name =~ s/^\./_/; file_name =~ s/[^a-zA-Z0-9_\.-]/_/g; if (file_name ~!= "") { system("mkdir -p files/$file_uuid"); value = "files/$file_uuid/$file_name"; cgi_userfile_save("file_$name", value); } } return value; } foreach[] p (clsdecl["param[@type = 'attribute']"].nodes) { var name = p["@name"]; var value = get_param(name); newxml ~= " $name=\"${xml::value}\""; } newxml ~= ">"; foreach[] p (clsdecl["param[@type = 'element']"].nodes) { var name = p["@name"]; var value = get_param(name); if (name ~== "") newxml ~= xml::value; else newxml ~= "<$name>${xml::value}"; } foreach[] child (data["//*[@uuid = '$uuid']/*"].nodes) { var childname = child["."].name; if (defined clsdecl["child[@name='$childname']"].node) newxml ~= child["."].xml; } newxml ~= ""; data["//*[@uuid = '$uuid']"].xml = newxml; file_write("data.xml", xml_dump(data, format: 1)); page.root.tree.dirty = 1; }); action("copy", function() { copy_buffer_xml = node["."].xml; copy_buffer_name = node["."].name; }); if (enable_delete) action("delete", function() { var data = xml_parse(file_read("data.xml")); var node = data["//*[@uuid = '$uuid']"].node; copy_buffer_xml = node["."].xml; copy_buffer_name = node["."].name; delete node["."]; file_write("data.xml", xml_dump(data, format: 1)); current_edit = undef; page.root.child_set("edit", new WsfComponent()); page.root.tree.dirty = 1; }); function uuid_rewrite(node) { foreach[] n (node[".//@uuid"].nodes) n["."] = uuidgen(); } if (enable_paste_i) action("paste_i", function() { var data = xml_parse(file_read("data.xml")); var node = data["//*[@uuid = '$uuid']"].node; data[node].add_xml_top = copy_buffer_xml; uuid_rewrite(node["*[1]"].node); file_write("data.xml", xml_dump(data, format: 1)); current_edit = node["*[1]/@uuid"]; page.root.child_set("edit", new WsfAction(edit, uuid: current_edit)); tree_opened_hash[uuid] = 1; page.root.tree.dirty = 1; }); if (enable_paste_a) action("paste_a", function() { var data = xml_parse(file_read("data.xml")); var node = data["//*[@uuid = '$uuid']"].node; data[node].add_xml_after = copy_buffer_xml; uuid_rewrite(node["following::*[1]"].node); file_write("data.xml", xml_dump(data, format: 1)); current_edit = node["following::*[1]/@uuid"]; page.root.child_set("edit", new WsfAction(edit, uuid: current_edit)); page.root.tree.dirty = 1; }); function create_object(clsname) { var clsdecl = classes["/classes/class[@name='$clsname']"].node; var newxml = "<$clsname uuid=\"${uuidgen()}\""; foreach[] p (clsdecl["param[@type = 'attribute']"].nodes) { var name = p["@name"]; var value = p["."]; newxml ~= " $name=\"${xml::value}\""; } newxml ~= ">"; foreach[] p (clsdecl["param[@type = 'element']"].nodes) { var name = p["@name"], value = p["."]; newxml ~= name ~== "" ? xml::value : "<$name>${xml::value}"; } newxml ~= ""; return newxml; } action("create_i", function() { var data = xml_parse(file_read("data.xml")); var node = data["//*[@uuid = '$uuid']"].node; node["."].add_xml_top = create_object(cgi.param.create_i); file_write("data.xml", xml_dump(data, format: 1)); current_edit = node["*[1]/@uuid"]; page.root.child_set("edit", new WsfAction(edit, uuid: current_edit)); tree_opened_hash[uuid] = 1; page.root.tree.dirty = 1; }); action("create_a", function() { var data = xml_parse(file_read("data.xml")); var node = data["//*[@uuid = '$uuid']"].node; node["."].add_xml_after = create_object(cgi.param.create_a); file_write("data.xml", xml_dump(data, format: 1)); current_edit = node["following::*[1]/@uuid"]; page.root.child_set("edit", new WsfAction(edit, uuid: current_edit)); page.root.tree.dirty = 1; }); return html; } var page = new WsfDocument(); page.title = "SPLCMS - Editor Backend"; page.html_head = <:> : : ; page.root = new WsfComponent(); page.root.child_set("banner", new WsfDisplay(<:> : )); page.root.child_set("tree", new WsfAction(tree)); page.main();