diff options
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | prototypejsdemo-controller.lua | 80 | ||||
-rw-r--r-- | prototypejsdemo-html.lsp | 164 | ||||
-rw-r--r-- | prototypejsdemo-model.lua | 284 | ||||
-rw-r--r-- | prototypejsdemo.menu | 1 |
5 files changed, 534 insertions, 1 deletions
@@ -16,7 +16,11 @@ APP_DIST=\ privdemo-controller.lua \ privdemo-model.lua \ privdemo-html.lsp \ - privdemo.menu + privdemo.menu \ + prototypejsdemo-controller.lua \ + prototypejsdemo-model.lua \ + prototypejsdemo-html.lsp \ + prototypejsdemo.menu EXTRA_DIST=Makefile config.mk diff --git a/prototypejsdemo-controller.lua b/prototypejsdemo-controller.lua new file mode 100644 index 0000000..547b91c --- /dev/null +++ b/prototypejsdemo-controller.lua @@ -0,0 +1,80 @@ +-- ipsec controller + +module(..., package.seeall) + +--require("posix") +require("json") +require("validator") + +function test(self) + local a = {} + return a +end + +-- quick and dirty json resolver. could be done with viewtype? +-- anyway... the file would be a oneliner anyway... +local function json_resolver(self) + io.write("\n\n"..json.encode(self).."\n") +end + +local function text_resolver(self) + io.write("content-type: application/json\n\n"..tostring(self).."\n"); +end + +function submit(self) + -- overwrite resolver. quick and dirty... + view_resolver = function(self) + return json_resolver + end + + local ret = {} + + -- only validation here is we test if mask is 'aaa' + if self.clientdata.mask == "aaa" then + ret.success = false + ret.errors = { mask = "'aaa' is a netmask...?" } + else + ret.success = true + end + + return ret +end + +function load(self) + -- overwrite resolver. quick and dirty... + view_resolver = function(self) + return json_resolver + end + + local status, t = self.model.get_iface_by_name(self.clientdata.ifname) + local ret = {} + if status then + ret = { + ifenable = "true", + iftype = t.method.value, + address = t.address.value, + mask = t.netmask.value, + gateway = t.gateway.value + } + else + ret.ifenable = "false"; + end + return ret +end + +function check_ipv4(self) + -- overload resolver quick'n dirty + view_resolver = function(self) + return text_resolver + end + + local ip = self.clientdata.address + local valid, msg = validator.is_ipv4(ip) + + if valid or ip == "" or ip == nil then + return "" + else + return msg + end +end + diff --git a/prototypejsdemo-html.lsp b/prototypejsdemo-html.lsp new file mode 100644 index 0000000..c9c1ee2 --- /dev/null +++ b/prototypejsdemo-html.lsp @@ -0,0 +1,164 @@ +<? local ctl = ... ?> + +<script type="text/javascript" src="/static/prototype.js"> +</script> + +<script type="text/javascript"> + +function check_ip(event) +{ + var el = event.element(); + var url = 'check_ipv4'; + var params = 'address='+el.value; + var ajax = new Ajax.Updater({ + success: el.id + '_status' + }, url, { + method: 'post', + parameters: params, + onFailure: report_error + }); +} + +function report_error(request) +{ + $F('address_result') = "Error"; +} + +function enable_disable_if() +{ + if ($('ifenable').checked) { + $('interface_form').enable(); + } else { + $('interface_form').disable(); + } +} + +function submit_form(event) +{ + var el = event.element(); + var f = $('interface_form'); + var params = f.serialize(); + alert('TODO: submitting ' + params); +/* var ajax = new Ajax.Updater('interface_form', 'write', { + parameters: params + }); +*/ +} + +function loadform(interface) +{ + var url = 'load'; /* the action in controller.lua */ + var ajax = new Ajax.Request(url, { + parameters: 'ifname=' + interface, + method: 'post', + onSuccess: function(transport) { + var resp = transport.responseText; + var json = resp.evalJSON(true); + $('ifname').update(interface); + $('ifenable').checked = json.ifenable; + $('iftype').value = json.iftype; + $('address').value = json.address; + $('mask').value = json.mask; + $('gateway').value = json.gateway; + $('msg') = resp; + } + }); +} + +/* event handler for 'iface' select box */ +function select_iface(event) +{ + var el = event.element(); + $('msg').update('Loading interface '+el.value); + loadform(el.value); +} + +/* event handler for 'iface' select box */ +function select_iface_type(event) +{ + var el = event.element(); + if (el.value == 'static') { + $('address').enable(); + $('mask').enable(); + $('gateway').enable(); + } else { + $('address').disable(); + $('mask').disable(); + $('gateway').disable(); + } +} + + +// the 'ifenable' element does not exist until page is loaded +Event.observe(window, 'load', function() { + $('ifenable').observe('click', enable_disable_if); + + $('address').observe('keypress', check_ip); + $('mask').observe('keypress', check_ip); + $('gateway').observe('keypress', check_ip); + $('applybutton').observe('click', submit_form); + $('iface').observe('click', select_iface); + $('iftype').observe('click', select_iface_type); + + loadform('eth0'); + + enable_disable_if(); +}); + +</script> + +<h1>PrototypeJS Demo</h1> + +<div id="interface-example"> + +<h2 id="ifname"></h2> + + +<dl> + <!-- this should be generated --> + <dt><label for="iface">Select Interface:</label></dt> + <dd><select name="iface" id="iface"> + <option value="eth0">eth0</option> + <option value="dummy0">dummy0</option> + <option value="lo">lo</option> + </select></dd> + + <dt><label for="ifenable">Enable:</label></dt> + <dd><input type="checkbox" name="ifenable" id="ifenable"/> + + </dd> +</dl> + +<form id="interface_form" action="write"> + +<dl> + <dt><label for="iftype">Type:</label></dt> + <dd><select name="iftype" id="iftype"> + <option value="none"> -- Please select interface type --</option> + <option value="dhcp">DHCP</option> + <option value="static">Static IP Address</option> + </select> + </dd> + + <dt><label for="address">Adress:</label></dt> + <dd><input type="text" name="address" id="address"/> + <span id="address_status"></span></dd> + + <dt><label for="mask">Netmask:</label></dt> + <dd><input type="text" name="mask" id="mask"/> + <span id="mask_status"></span></dd> + + <dt><label for="gateway">Gateway:</label></dt> + <dd><input type="text" name="gateway" id="gateway"/> + <span id="gateway_status"></span></dd> + + <dt> </dt> + <dd> + <input type="button" id="applybutton" name="applybutton" value="Apply"/> + </dd> + +</dl> +</form> +</div> + +<div id="msg"></div> diff --git a/prototypejsdemo-model.lua b/prototypejsdemo-model.lua new file mode 100644 index 0000000..b0d3b05 --- /dev/null +++ b/prototypejsdemo-model.lua @@ -0,0 +1,284 @@ +-- acf model for /etc/network/interfaces +-- Copyright(c) 2007 N. Angelacos - Licensed under terms of GPL2 +module (..., package.seeall) + +-- iface is a local (private) table with private methods for managing +-- the interfaces file. All low-level stuff is done here. It exposes +-- the iface.tags, file(raw), and array (parsed), as well as a number +-- of functions for managing the interface file. These are in a local +-- table because nobody outside the model should know anything about +-- the interfaces file (not even where it is - it could be in an LDAP +-- directory for all we know) The public module functions are defined +-- further below + +local iface = { tags = { "name", "comment", "method", "address", + "netmask", "gateway", "hostname", "provider", + "pre-up", "up", "down", "post-down" }, + methods = { "dhcp", "static", "ppp", "loopback", "manual" }, + -- lowlevel functions will insert file and array here + } + + +-- Lowlevel functions - they do things directly to iface. +iface.read_file = function () + local filename = "/etc/network/interfaces" + iface.file = cfe { name=filename, filename=filename } + local file = io.open(filename) + local rc = false + if file then + iface.file.value = file:read("*a") + -- make sure it has a terminating \n + iface.file.value = string.gsub (iface.file.value, "([^\n])$", "%1\n") + file:close() + rc = true + end + return rc +end + +iface.write_file = function () + local rc = false + local file = io.open ( iface.file.name, "w") + if file then + file:write ( iface.file.value ) + file:close() + rc = true + end + return rc + end + +function iface.iface_type ( ) + local f = {} + for k,v in pairs(iface.tags) do + f[v] = cfe { name = v } + end + + + for k,v in pairs ({"comment", "pre-up", "up", "down", "post-down"}) do + f[v].type ="longtext" + end + + f.method.type = "select" + f.method.option = iface.methods + return (f) +end + +-- return true or false + the index of iface.array matching "name" +function iface.index (name) + if name== nil or #name == 0 then + return true, 0 + end + + if iface.array == nil then + iface.unpack_interfaces () + end + + for k,v in ipairs(iface.array) do + if name == v.name.value then + return true, k + end + end + + return false, 0 +end + + +function iface.append ( self, value, prefix ) + self = self or "" + -- if we already have some values, then append a newline + if #self > 0 then self = self .. "\n" end + -- strip the prefix + local str = string.gsub(value, "^" .. ( prefix or "" ), "") + -- and append + return self .. str +end + +function iface.expand ( self, prefix ) + if #self == 0 then + return "" + end + -- force the string to end in a single linefeed + self = string.gsub (self, "\r", "") + self = string.gsub (self, "[\n]*$", "\n") + local str = "" + for line in string.gmatch ( self, ".-\n") do + if #line > 0 then + str = str .. prefix .. " " .. line + end + end + return str +end + +function iface.unpack_interfaces () + if iface.array == nil then + iface.read_file() + iface.array = {} + end + + -- call it array so we don't have to call it iface.array everywhere + local array = iface.array + local count = 0 + + array[count] = iface.iface_type() + + for line in string.gmatch ( iface.file.value, ".-\n") do + -- strip leading spaces, tabs + line = string.gsub (line, "^[%s]*", "") + line = string.gsub (line, "\n*$", "") + -- it can be #, auto, iface, or a parameter + if string.match(line, "^#") then + array[count].comment.value = + iface.append(array[count].comment.value, line , "#%s*" ) + elseif string.match(line, "^auto") then + -- do nothing + elseif string.match(line, "^iface") then + count = count + 1 + array[count] = iface.iface_type() + -- iface <name> [inet | ipx] <method> -- we assume inet + array[count].name.value, + array[count].method.value = + string.match(line, "%w+%s+(%w+)%s+%w+%s+(%w+)") + else -- it must be some kind of parameter + local param, val = + string.match(line, "(%S+)%s*(.*)$") + if (param) then + array[count][param].value = + iface.append (array[count][param].value, val) + end + end + end + + -- now move the comments to go with the interface + for n = count,1,-1 do + array[n].comment.value = array[n-1].comment.value + end + + return array +end + +function iface.pack_interfaces() + local str = "" + for n = 1,#iface.array,1 do + local me = iface.array[n] + for k,v in pairs (iface.tags) do + if v == "comment" then + str = str .. "\n" .. iface.expand ( me[v].value, "#") + elseif v == "method" then + str = str .. string.format ("\nauto %s\niface %s inet %s\n", + me.name.value, me.name.value, + me.method.value) + elseif v == "name" then + -- nothing + else + str = str .. iface.expand( me[v].value, "\t" .. v) + end + end + end + return str +end + +function iface.commit() + iface.file.value = iface.pack_interfaces() + return iface.write_file() +end + + +function iface.add_after ( name, def ) + -- if the new if.name is already in the table, then fail + local rc, idx = iface.index(def.name.value) + if idx > 0 then + def.name.errtxt = "This interface is already defined" + return false, def + end + + -- if the name to insert after doesn't exist, just fail + rc, idx = iface.index(name) + if rc == false then + return false, def + end + + rc, def = iface.validate (def) + if rc == false then + return rc, def + end + + table.insert( iface.array, idx+1, def ) + return iface.commit() , def +end + +function iface.read ( name ) + -- if the name is blank, then return an empty def + local rc, idx = iface.index(name or "") + if name == nil or #name == 0 or rc == false then + return rc, iface.iface_type() + end + return iface.commit(), iface.array[idx] +end + + +function iface.update ( def) + -- if the def by that name doesn't exist, fail + local rc, idx = iface.index(def.name.value or "" ) + if idx == 0 then + def.name.errtxt = "This is an invalid interface name" + return false, def + end + + rc, def = iface.validate ( def ) + if rc == false then + return rc, def + end + + iface.array[idx] = def + return iface.commit(), def +end + +function iface.delete (name ) + local rc, idx = iface.index(name or "" ) + if idx == 0 then + rc = false + else + table.remove (iface.array, idx ) + end + return iface.commit() +end + + +iface.validate = function ( def ) + if #def.name.value == 0 then + iface.name.errtxt = "The interface must have a name" + end + def.method.errtxt = "Method specified is invalid" + for k,v in pairs (iface.methods) do + if def.method.value == v then + def.method.errtxt = "" + end + end + -- More validation tests go here --- + -- + local rc = true + for k,v in pairs(def) do + if #def[k].errtxt > 0 then result = false end + end + + return result, def +end + +------------------------------------------------------------------------------- +-- Public Methods +------------------------------------------------------------------------------- + +get_all_interfaces = iface.unpack_interfaces + +get_iface_by_name = iface.read + +create_iface_by_name = iface.add_after + +update_iface_by_name = function (def, name ) + -- make sure name we think we are updating is name we are updating + def.name.value = name + return iface.update (def) +end + +delete_iface_by_name = iface.delete + + diff --git a/prototypejsdemo.menu b/prototypejsdemo.menu new file mode 100644 index 0000000..47bd456 --- /dev/null +++ b/prototypejsdemo.menu @@ -0,0 +1 @@ +Test PrototypeJS_Demo Define test |