summaryrefslogtreecommitdiffstats
path: root/www
diff options
context:
space:
mode:
authorNatanael Copa <natanael.copa@gmail.com>2007-07-27 12:53:38 +0000
committerNatanael Copa <natanael.copa@gmail.com>2007-07-27 12:53:38 +0000
commitdc53423183a0c459284ebd139022b707f01af006 (patch)
tree8a67a2904ec991028bddd429d57eec114b05baab /www
parent275c80281ba2e84b8d810bdb1c2b7f8c9a4333d9 (diff)
downloadacf-core-dc53423183a0c459284ebd139022b707f01af006.tar.bz2
acf-core-dc53423183a0c459284ebd139022b707f01af006.tar.xz
moved core files to new dir structurev2.0_alpha1
git-svn-id: svn://svn.alpinelinux.org/acf/core/trunk@219 ab2d0c66-481e-0410-8bed-d214d4d58bed
Diffstat (limited to 'www')
-rw-r--r--www/Makefile50
-rwxr-xr-xwww/cgi-bin/acf19
-rwxr-xr-xwww/cgi-bin/mvc.lua278
-rw-r--r--www/index.html12
-rw-r--r--www/sample.html102
-rw-r--r--www/static/alpine.gifbin0 -> 17876 bytes
-rw-r--r--www/static/alpine.pngbin0 -> 43938 bytes
-rw-r--r--www/static/arctic-back.pngbin0 -> 213 bytes
-rw-r--r--www/static/arctic-upleft.pngbin0 -> 300 bytes
-rw-r--r--www/static/greypx.gifbin0 -> 38 bytes
-rw-r--r--www/static/selected.gifbin0 -> 1095 bytes
-rw-r--r--www/static/submenu.css52
-rw-r--r--www/static/unselected.gifbin0 -> 945 bytes
-rw-r--r--www/static/webconf-purple.css313
-rw-r--r--www/static/webconf.css367
15 files changed, 1193 insertions, 0 deletions
diff --git a/www/Makefile b/www/Makefile
new file mode 100644
index 0000000..e208bdf
--- /dev/null
+++ b/www/Makefile
@@ -0,0 +1,50 @@
+include ../config.mk
+
+WWW_DIST=cgi-bin/acf\
+ cgi-bin/mvc.lua\
+ static/alpine.gif\
+ static/alpine.png\
+ static/arctic-back.png\
+ static/arctic-upleft.png\
+ static/greypx.gif\
+ static/selected.gif\
+ static/submenu.css\
+ static/unselected.gif\
+ static/webconf-purple.css\
+ static/webconf.css\
+ index.html\
+ sample.html
+
+EXTRA_DIST=Makefile
+DISTFILES=$(WWW_DIST) $(EXTRA_DIST)
+
+install_dir=$(DESTDIR)/$(wwwdir)
+dist_dir=$(DISTDIR)/$(notdir $(PWD))
+
+phony+=all
+all:
+
+phony+=clean
+clean:
+
+phony+=distdir
+distdir: $(DISTFILES)
+ mkdir -p "$(dist_dir)"
+ for i in $(DISTFILES); do\
+ dest=`dirname "$(dist_dir)/$$i"`;\
+ mkdir -p "$$dest";\
+ cp "$$i" "$$dest";\
+ done
+
+phony+=install
+install:
+ mkdir -p $(install_dir)
+ for i in $(WWW_DIST); do\
+ dest=`dirname "$(install_dir)/$$i"`;\
+ mkdir -p "$$dest";\
+ cp "$$i" "$$dest";\
+ done
+ chmod +x $(install_dir)/cgi-bin/acf
+
+
+.PHONY: $(phony)
diff --git a/www/cgi-bin/acf b/www/cgi-bin/acf
new file mode 100755
index 0000000..b52f9e7
--- /dev/null
+++ b/www/cgi-bin/acf
@@ -0,0 +1,19 @@
+#!/usr/bin/haserl --shell=lua -a
+<?
+require("mvc")
+
+-- create a new container
+FRAMEWORK=mvc:new()
+
+-- set the configuration parameters
+-- This loads the container with the config info
+-- but does not load the application worker/model
+FRAMEWORK:read_config("acf")
+
+-- Create an application container -
+-- loads the application controller/model code
+APP=FRAMEWORK:new("acf_www")
+
+-- Dispatch the application
+APP:dispatch()
+?>
diff --git a/www/cgi-bin/mvc.lua b/www/cgi-bin/mvc.lua
new file mode 100755
index 0000000..b677d3b
--- /dev/null
+++ b/www/cgi-bin/mvc.lua
@@ -0,0 +1,278 @@
+--[[ Basic MVC framework
+ Written for Alpine Configuration Framework (ACF) -- see www.alpinelinux.org
+ Copyright (C) 2007 Nathan Angelacos
+ Licensed under the terms of GPL2
+ ]]--
+module(..., package.seeall)
+
+-- the constructor
+--[[ Builds a new MVC object. If "module" is given, then tries to load
+ self.conf.appdir .. module "-controller.lua" in c.worker and
+ self.conf.appdir .. module "-model.lua" in c.model
+
+ The returned .conf table is guaranteed to have the following
+ appdir - where the application lives
+ confdir - where the configuration file is
+ sessiondir - where session data and other temporary stuff goes
+ appname - the name of the application
+ ]]
+
+new = function (self, modname)
+ local c = {}
+ c.worker = {}
+ c.model = {}
+
+ -- make defaults if the parent doesn't have them
+ if self.conf == nil then
+ c.conf = { appdir = "", confdir = "", tempdir = "", appname = "" }
+ end
+
+ -- If no clientdata, then clientdata is a null table
+ if self.clientdata == nil then
+ c.clientdata = {}
+ end
+
+ -- If we don't have an application name, use the modname
+ if (self.conf == nil ) or (self.conf.appname == nil) then
+ c.conf.appname = modname
+ end
+
+ -- load the module code here
+ if (modname) then
+ c.worker = self:soft_require( modname .. "-controller") or {}
+ c.model = self:soft_require( modname .. "-model" ) or {}
+ end
+
+ -- The magic that makes all the metatables point in the correct
+ -- direction. c.model -> c.worker -> parent -> parent.worker ->
+ -- grandparent -> grandparent -> worker (and so on)
+
+ -- The model looks in worker for missing
+ setmetatable (c.model, c.model )
+ c.model.__index = c.worker
+
+ -- the worker looks in the main table for missing
+ setmetatable (c.worker, c.worker)
+ c.worker.__index = c
+
+ -- the table looks in the parent worker for missing
+ setmetatable (c, c)
+
+ -- ensure an "mvc" table exists, even if empty
+ if (type(rawget(c.worker, "mvc")) ~= "table") then
+ c.worker.mvc = {}
+ end
+
+ setmetatable (c.worker.mvc, c.worker.mvc)
+ -- If creating a new parent container, then
+ -- we are the top of the chain.
+ if (modname) then
+ c.__index = self.worker
+ c.worker.mvc.__index = self.worker.mvc
+ else
+ c.__index = self
+ c.worker.mvc.__index = self.mvc
+ end
+
+
+ -- run the worker on_load code
+ if type(rawget(c.worker.mvc, "on_load")) == "function" then
+ c.worker.mvc.on_load(c, self)
+ c.worker.mvc.on_load = nil
+ end
+
+ return c
+end
+
+-- This is a sample front controller/dispatch.
+dispatch = function (self)
+ local controller
+ local success, err = xpcall ( function ()
+
+ self:parse_path_info(ENV["PATH_INFO"])
+
+ -- If they didn't provide a controller, and a default was specified
+ -- use it
+ if self.conf.controller == "" and self.conf.default_controller then
+ self.conf.controller = self.conf.default_controller
+ end
+
+ controller = self:new(self.conf.prefix .. self.conf.controller)
+
+ local action = controller.conf.action
+
+ -- Because of the inheritance, normally the
+ -- controller.worker.action will flow up, so that EVERY
+ -- worker has an "exception_handler" action. We use rawget to
+ -- make sure that only controller defined actions are used.
+ -- If the controller or action are missing, raise an error
+ if ( type(rawget(controller.worker, action)) ~= "function") then
+ self.conf.type = "dispatch"
+ error (self.conf)
+ end
+
+ -- run the pre_exec code
+--- if type(rawget(controller.worker.mvc, "pre_exec")) == "function" then
+ if type(controller.worker.mvc.pre_exec) == "function" then
+ controller.worker.mvc.pre_exec ( controller )
+ end
+
+ -- run the action
+ local viewtable = controller.worker[action](controller)
+
+
+ -- run the post_exec code
+ if type(controller.worker.mvc.post_exec) == "function" then
+ -- if type(controller.worker.mvc, "post_exec") == "function" then
+ controller.worker.mvc.post_exec ( controller )
+ end
+
+
+ local viewfunc = controller:view_resolver(viewtable)
+
+ viewfunc (viewtable)
+ end,
+ self:soft_traceback(message)
+ )
+
+ if not success then
+ local handler
+ if controller then
+ handler = controller.worker or controller
+ end
+ handler = handler or self.worker or mvc
+ handler:exception_handler(err)
+ end
+end
+
+
+-- Tries to see if name exists in the self.conf.appdir, and if so, it loads it.
+-- otherwise, returns nil, but no error
+soft_require = function (self, name )
+ local filename, file
+ filename = self.conf.appdir .. name .. ".lua"
+ file = io.open(filename)
+ if file then
+ file:close()
+ local PATH=package.path
+ -- FIXME - this should really try to open the lua file, and if it doesnt exist-
+ -- then silently fail -- This version allows things from /usr/local/lua/5.1 to
+ -- be loaded - but that's because a module might require another module
+ package.path = self.conf.appdir .. "?" .. ".lua;" .. package.path
+ local t = require(name)
+ package.path = PATH
+ return t
+ end
+ return nil
+end
+
+-- see man basename.1
+basename = function (string, suffix)
+ string = string or ""
+ local basename = string.gsub (string, "[^/]*/", "")
+ if suffix then
+ basename = string.gsub ( basename, suffix, "" )
+ end
+ return basename
+end
+
+-- see man dirname.1
+dirname = function ( string)
+ string = string or ""
+ -- strip trailing / first
+ string = string.gsub (string, "/$", "")
+ local basename = basename ( string)
+ string = string.sub(string, 1, #string - #basename - 1)
+ return(string)
+end
+
+-- look in various places for a config file, and store it in self.conf
+read_config = function( self, appname )
+ appname = appname or self.conf.appname
+ self.conf.appname = self.conf.appname or appname
+
+ local confs = { (ENV["HOME"] or ENV["PWD"] or "") .. "/." .. appname .. "/" .. appname .. ".conf",
+ ( ENV["HOME"] or ENV["PWD"] or "") .. "/" .. appname .. ".conf",
+ -- dirname(ENV["SCRIPT_FILENAME"] or "") .. appname .. ".conf",
+ ENV["ROOT"] or "" .. "/etc/" .. appname .. "/" .. appname .. ".conf",
+ ENV["ROOT"] or "" .. "/etc/" .. appname .. ".conf"
+ }
+ for i, filename in ipairs (confs) do
+ local file = io.open (filename)
+ if (file) then
+ self.conf.confdir = dirname(filename) .. "/"
+ for line in file:lines() do
+ key, value = string.match(line, "([^[=]*)=[ \t]*(.*)")
+ if key then -- ugly way of finding blank spots between key and =
+ repeat
+ local space = string.find ( key, "%s", -1)
+ if space then key=string.sub(key,1,space-1) end
+ until space == nil
+ self.conf[key] = value
+ end
+ end
+ file:close()
+ break
+ end
+ end
+end
+
+-- parse a "URI" like string into a prefix, controller and action
+-- store them (or blanks) in self.conf
+parse_path_info = function( self, string )
+ string = string or ""
+ -- If it ends in a /, then add another to force
+ -- a blank action (the user gave a controller without action)
+ if string.match (string, "[^/]/$" ) then
+ string = string .. "/"
+ end
+ self.conf.action = basename(string)
+ local temp = dirname(string)
+ self.conf.controller = basename(temp)
+ self.conf.prefix = dirname(temp) .. "/"
+ return self.conf.prefix, self.conf.controller, self.conf.action
+
+end
+
+-- The View resolver of last resort.
+view_resolver = function(self)
+ return function()
+ if ENV["PATH_INFO"] then
+ io.write ("Content-type: text/plain\n\n")
+ end
+ io.write ("Your controller and application did not specify a view resolver.\n")
+ io.write ("The MVC framework has no view available. sorry.\n")
+ return
+ end
+end
+
+-- Generates a debug.traceback if called with no arguments
+soft_traceback = function (self, message )
+ if message then
+ return message
+ else
+ return debug.traceback
+ end
+end
+
+-- The exception hander of last resort
+exception_handler = function (self, message )
+ if ENV["PATH_INFO"] then
+ print ("Content-Type: text/html\n\n<pre>")
+ end
+ print ("The following unhandled application error occured:\n\n")
+
+ if (type(message) == "table" ) then
+ if (message.type == "dispatch") then
+ print ('controller: "' .. message.controller .. '" does not have a "' ..
+ message.action .. '" action.')
+ else
+ print ("An error of type: '" .. (tostring(message.type) or "nil") .. "' was raised." )
+ end
+ else
+ print (tostring(message))
+ end
+ if ENV["PATH_INFO"] then
+ print ("</pre>")
+ end
+end
diff --git a/www/index.html b/www/index.html
new file mode 100644
index 0000000..8db9a9d
--- /dev/null
+++ b/www/index.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns='http://www.w3.org/1999/xhtml'>
+<head>
+<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
+<meta http-equiv='Cache-Control' content='no-cache' />
+<Meta http-equiv='Pragma' content='no-cache' />
+<meta http-equiv='refresh' content='0; url=/cgi-bin/acf'>
+</head>
+
+<body>
+</body>
diff --git a/www/sample.html b/www/sample.html
new file mode 100644
index 0000000..665334d
--- /dev/null
+++ b/www/sample.html
@@ -0,0 +1,102 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//ddD HTML 4.01 Transitional//EN">
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Alpine</title>
+<link rel="stylesheet" type="text/css" href="static/webconf.css">
+<meta http-equiv="Refresh" content="5; url=sample.html">
+</head>
+<body>
+
+
+
+
+<div id=head>
+<h1>Alpine</h1>
+<p>Host: <em>Inside</em></p>
+</div>
+
+
+<div id="mainmenu">
+<h3>Networking</h3>
+<ul><a href="foo"><li>Interfaces</li></a>
+<li id="selected"><a href="bar">Routes</a></li>
+<li><a href="bar">DNS Cache</a></li>
+<li><a href="bar">DNS Server</a></li>
+<li><a href="bar">Firewall</a></li>
+</ul>
+<h3>VPN</h3>
+<ul>
+<li><a href="foo">IPSec</a></li>
+<li><a href="bar">OpenVPN</a></li>
+<li><a href="bar">Tinc</a></li>
+</ul>
+<h3>Application Proxy</h3>
+<ul>
+<li><a href="foo">DNS Proxy</a></li>
+<li><a href="bar">Fetchmail</a></li>
+<li><a href="bar">Squid</a></li>
+</ul>
+</div>
+
+
+<div id="submenu">
+<h2>Networking > Routes</h2>
+<ul><li><a href="foo">Status</a></li>
+<li id="selected">Interfaces</li>
+<li><a href="fee">Expert</a></li>
+</ul>
+</div>
+
+
+
+<div id="content">
+<h1>Errors</h1>
+<p class="error">This is error text. As if you didn't know that. Just check the errors below.</p>
+
+<p>This is a page with a <a href="foo">link</a> in it.</p>
+
+<h1>Networking - Status</h1>
+<p>This is the networking page. This is a very long paragraph in that page, talking about
+all the good things on this page. This is not the real page, its just a standin page for
+the page you want. Evenutally, you'll see the page you want. But not quite yet.</p>
+
+<h2>Status</h2>
+<p>The service is running</p>
+<form>
+<dl>
+<dt>bozo</dt>
+<dd><input class=error type=text value="Baz" name=bozo size=3>This is error text</dd>
+
+<dt>foo</dt><dd>
+<input type=text value="foo" name=foo size=40>
+</dd>
+
+<dt>Command</dt>
+<dd>
+<input type=submit value="Start" name="cmd">
+<input type=submit value="Stop" name="cmd">
+<input type=submit value="Restart" name="cmd">
+</dd>
+
+<dt>Textbox</dt>
+<dd><textarea cols=80 rows=10 name="textbox">fooo</textarea>
+</dd>
+
+
+<dt>A Tag with no form element</dt>
+<dd>This is just some text</dd>
+
+</dl>
+</form>
+
+<h2>Configure</h2>
+<p>Bring Service Down</p>
+<p>Bring Service Up</p>
+</div>
+
+<div id="footer">
+<p><center>Made with care by webconf</center></p>
+</div>
+</body>
+</html>
diff --git a/www/static/alpine.gif b/www/static/alpine.gif
new file mode 100644
index 0000000..2605afe
--- /dev/null
+++ b/www/static/alpine.gif
Binary files differ
diff --git a/www/static/alpine.png b/www/static/alpine.png
new file mode 100644
index 0000000..11802e0
--- /dev/null
+++ b/www/static/alpine.png
Binary files differ
diff --git a/www/static/arctic-back.png b/www/static/arctic-back.png
new file mode 100644
index 0000000..0719f28
--- /dev/null
+++ b/www/static/arctic-back.png
Binary files differ
diff --git a/www/static/arctic-upleft.png b/www/static/arctic-upleft.png
new file mode 100644
index 0000000..9b6c926
--- /dev/null
+++ b/www/static/arctic-upleft.png
Binary files differ
diff --git a/www/static/greypx.gif b/www/static/greypx.gif
new file mode 100644
index 0000000..b13cb90
--- /dev/null
+++ b/www/static/greypx.gif
Binary files differ
diff --git a/www/static/selected.gif b/www/static/selected.gif
new file mode 100644
index 0000000..b2c2951
--- /dev/null
+++ b/www/static/selected.gif
Binary files differ
diff --git a/www/static/submenu.css b/www/static/submenu.css
new file mode 100644
index 0000000..b759020
--- /dev/null
+++ b/www/static/submenu.css
@@ -0,0 +1,52 @@
+/*----------------------------------------------------------------------------------
+ * Submenu ( Horizontal Tabs)
+ *----------------------------------------------------------------------------------
+ */
+#submenu {
+ width: 75%;
+ font-size: 90%;
+// font-weight: Bold;
+// display: inline;
+ float: right;
+ margin: 0em 2em 0em 0em;
+ background: #fff url(/static/greypx.gif) repeat-x bottom left;
+ }
+
+#submenu p {
+ display: inline;
+ color: #22c;
+ font-size: 161%;
+ font-weight: light;
+ margin: 2em 0em -2em 0em;
+ }
+
+#submenu ul {
+ list-style: none;
+ display: inline;
+ margin: 0em 1em 0em 1em;
+ padding: 0em 3em .6em 2em;
+ float: right;
+ }
+
+#submenu li {
+ display: inline;
+ border: 1px solid #ccc;
+ padding: .5em 1em .5em 1em;
+ margin: 0em 0em 0em 0em;
+ border-bottom: none;
+ background: #f8f8f8;
+ background: transparent url("/static/unselected.gif") repeat-x top left;
+ }
+
+#submenu #selected {
+ // background: #fff url("/static/selected.gif") repeat-x top left;
+ background: #fff;
+ }
+
+#submenu a {
+ }
+
+#submenu a:hover {
+ color: #c22;
+ }
+
diff --git a/www/static/unselected.gif b/www/static/unselected.gif
new file mode 100644
index 0000000..f26d430
--- /dev/null
+++ b/www/static/unselected.gif
Binary files differ
diff --git a/www/static/webconf-purple.css b/www/static/webconf-purple.css
new file mode 100644
index 0000000..57538cd
--- /dev/null
+++ b/www/static/webconf-purple.css
@@ -0,0 +1,313 @@
+/* webconf.css - For Alpine webconf
+ */
+
+/* Default definitions */
+body {
+ background: url(arctic-back.png) repeat-y 20% 0;
+ // background-color: #DAE0EE;
+ font-family: Geneva, Arial, Helvetica, San-Serif;
+ margin: 0em;
+ padding: 0em;
+ // padding: 1em 0em 0em 1em;
+ font-size: 80%;
+ }
+
+p {
+ margin: 0em 0em 0em 0em;
+ }
+
+a {
+ text-decoration: none;
+ color: #333;
+ }
+
+a:link {
+ }
+
+a:visited {
+ }
+
+a:hover {
+ // font-weight: bold;
+ // text-decoration: underline;
+ }
+
+a:active {
+ }
+/*----------------------------------------------------------------------------------
+ * Header
+ *----------------------------------------------------------------------------------
+ */
+#head {
+ padding: 1em 1em 1em 0em;
+ background: #dde url(alpine.png) no-repeat 50% 0;
+ color: #333;
+ // margin: -1em 0em 0em 0em;
+ padding: 1em;
+ }
+
+#head h1 {
+ font-size: 300%;
+ color: #226;
+ font-family: Palatino, Times-Roman, Serif;
+ font-weight: bold;
+ margin: 0em 0em 0em 0em;
+ //float: left;
+ width: 49%;
+ }
+
+#head h2 {
+ margin: 0em 0em 0em 0em;
+ font-size: 100%;
+ font-weight: light;
+ float: right;
+ width: 30%;
+ }
+
+#head h3 {
+ float: right;
+ font-size: 90%;
+ color: #222;
+ }
+
+#head p {
+ // border: 1px inset #ccc;
+ // border-top: 1px solid #ccc;
+ // border-bottom: 1px solid #ccc;
+ }
+
+/*----------------------------------------------------------------------------------
+ * Left (Main) Menu
+ *----------------------------------------------------------------------------------
+ */
+#mainmenu {
+ display: block;
+ background-color: #dde;
+ width: 20%;
+ float: left;
+ margin: 2em 0em 0em 0em;
+ padding: 0em -1em 0em 1em;
+ }
+
+#mainmenu p {
+ background-color: #448;
+ color: #fc4;
+ padding: 0em 0em 0em 1em;
+ font-size: 110%;
+ font-weight: bold;
+ // margin: 0em 0em 0em 0em;
+ }
+
+#mainmenu ul {
+ padding: 0em 0em 0em 2em;
+ margin: 0;
+ list-style-type: none;
+ }
+#mainmenu li {
+ background-color: inherit;
+ }
+
+#mainmenu a:hover {
+ display: block;
+ background-color: #eec;
+ }
+
+#mainmenu #selected {
+ // border: 1px solid #666;
+ //border-right: 1px solid #ffd;
+ background-color: #ffe;
+ }
+
+
+/*----------------------------------------------------------------------------------
+ * Submenu ( Horizontal Tabs)
+ *----------------------------------------------------------------------------------
+ */
+#submenu {
+ // display: none;
+ width: 80%;
+ // clear: both;
+ display: inline;
+ float: right;
+ margin: 0em 0em 0em 0em;
+ background-color: #dde;
+ }
+
+#submenu p {
+ display: none;
+ }
+
+#submenu ul {
+ float: left;
+ list-style: none;
+ display: inline;
+ margin: 0 1em 0 1em;
+ padding: 0 1em 0 1em;
+ }
+
+#submenu li {
+ display: inline;
+ background-color: #ccd;
+ border: 1px solid #666;
+ border-bottom: none;
+ }
+
+#submenu #selected {
+ border: 1px solid #666;
+ background: #ffe;
+ border-bottom: none;
+ // 2px solid #ffd;
+ // font-weight: bold;
+ }
+
+#submenu a {
+ padding: .1em .2em;
+ }
+
+#submenu a:hover {
+ display: inline;
+ background: #eec;
+ padding: 0em .2em;
+ }
+
+/*----------------------------------------------------------------------------------
+ * Content
+ *----------------------------------------------------------------------------------
+ */
+#content {
+ float:left;
+ width: 70%;
+ color: #333;
+ // background-color: #DAE0EE;
+ background: url(arctic-upleft.png) no-repeat;
+ padding: 2em 0em 3em 3em;
+ }
+
+#content h1 {
+ font-size: 120%;
+ // width: 100%;
+ background-color: #eec;
+ border-bottom: 2px solid #aa9;
+ margin: 1em 0em 1em 0em;
+ clear: both;
+ }
+
+#content h2 {
+ font-size: 100%;
+ // width: 100%;
+ background-color: #eec;
+ border-bottom: 1px solid #aa9;
+ // margin: 1em 1em 0em 1em;
+ clear: both;
+ }
+
+#content p {
+ // margin: 1em 1em 0em 1em;
+ clear: both;
+ padding: .5em 0em .5em 0em;
+ }
+
+#content p.error {
+ // border: 2px solid #c00;
+ // margin: 1em 2em;
+ // padding: 1em 0em;
+ font-size: 120%;
+ font-weight: bold;
+ // background-color: #faa;
+ color: #c00;
+ }
+
+#content p.warn {
+ // border: 2px solid #cc0;
+ // margin: 1em 2em;
+ // padding: 1em;
+ background-color: #ffa;
+ }
+
+#content p.ok {
+ font-size: 120%;
+ font-weight: bold;
+ // border: 2px solid #0c0;
+ // margin: 1em 2em;
+ // padding: 1em 0em;
+ color: #090;
+ }
+
+
+#content input, textarea {
+ float: left;
+ font-size: 90%;
+ // font-family: courier-new, courier, sans;
+ background-color: #eec;
+ margin-top: -0.3em;
+ }
+
+
+#content input.error {
+ background-color: #faa;
+ // border: 2px solid #c00;
+ // margin: .5em 1em .5em 0em;
+ }
+
+#content input.button {
+ font-family: Geneva, Arial, Helvetica, Serif;
+ font-size: 100%;
+ font-weight: bold;
+ color: #228;
+ }
+
+#content dt {
+ font-size: 110%;
+ font-weight: bold;
+ color: #228;
+ margin: .7em 1em .5em 0em;
+ float: left;
+ border-top: 1px dotted #ccc;
+ border-bottom: 1px dotted #ccc;
+ width: 20%;
+ clear: both;
+ }
+
+#content a {
+ text-decoration: underline;
+ color: #449;
+ }
+
+#content form {
+ padding: 1em 0em;
+ }
+
+#content dl {
+ margin: 0em;
+ }
+
+#content dd {
+ color: #c00;
+ float: left;
+ margin: 1em 0em .5em 0em;
+ // font-size: 90%;
+ font-weight: light;
+ // margin: .5em 1em .5em 0em;
+ // border-top: 1px dotted #ccc;
+ // border-bottom: 1px dotted #ccc;
+ }
+
+
+
+/*----------------------------------------------------------------------------------
+ * footer
+ *----------------------------------------------------------------------------------
+ */
+
+#footer {
+ float: right;
+ clear: both;
+ text-align: center;
+ font-size: 80%;
+ width: 70%;
+ color: #666;
+ margin: 1em 3em 1em 2em;
+ padding: 1em 0em 1em;
+ border-top: 1px dotted #ccc;
+ border-bottom: 1px dotted #ccc;
+ }
diff --git a/www/static/webconf.css b/www/static/webconf.css
new file mode 100644
index 0000000..2c09494
--- /dev/null
+++ b/www/static/webconf.css
@@ -0,0 +1,367 @@
+/* webconf.css - For Alpine webconf
+ */
+
+/* Default definitions */
+body {
+ background: #fff url("/static/alpine.gif") no-repeat top center;
+ font-family: Geneva, Arial, Helvetica, San-Serif;
+ margin: 0em;
+ padding: 0em;
+ font-size: small;
+ }
+
+p {
+ margin: 0em 0em 0em 0em;
+ }
+
+a {
+ text-decoration: none;
+ color: #333;
+ }
+
+a:link { color: #226;
+ }
+
+a:visited {
+ color: #226;
+ }
+
+a:hover {
+ color: #44C;
+ }
+
+a:active {
+ }
+
+pre.code {
+ border: 1px solid #666;
+ background: #f8f8f8;
+ padding: .5em;
+}
+/*----------------------------------------------------------------------------------
+ * Header
+ *----------------------------------------------------------------------------------
+ */
+#head {
+ padding: 1em 1em 1em 0em;
+ color: #333;
+ // margin: -1em 0em 0em 0em;
+ padding: 1em;
+ }
+
+#head h1 {
+ font-size: 259%;
+ color: #33A;
+ // font-family: Palatino, Times-Roman, Serif;
+ font-weight: bold;
+ margin: 0em 0em 0em 0em;
+ //float: left;
+ // width: 49%;
+ }
+
+#head h2 {
+ margin: 0em 0em 0em 0em;
+ font-size: 100%;
+ font-weight: light;
+ float: right;
+ width: 30%;
+ }
+
+#head h3 {
+ float: right;
+ font-size: 90%;
+ color: #222;
+ }
+
+#head p {
+ // border: 1px inset #ccc;
+ // border-top: 1px solid #ccc;
+ // border-bottom: 1px solid #ccc;
+ }
+
+/*----------------------------------------------------------------------------------
+ * Left (Main) Menu
+ *----------------------------------------------------------------------------------
+ */
+#mainmenu {
+ display: block;
+ background: #eee;
+ // border: 1px #222 solid;
+ width: 19%;
+ float: left;
+ margin: 5em 0em 0em 1em;
+ padding: 0em 0em 0em .5em;
+ // border-right: 1px #ccc solid;
+ }
+
+#mainmenu h3 {
+ // background-color: #eee;
+ color: #448;
+ padding: .25em 0em 0em .25em;
+ font-weight: normal;
+ font-size: 138%;
+ margin: 0em 0em .1em 0em;
+ }
+
+#mainmenu ul {
+ padding: .2em 0em .6em 1em;
+ margin: 0;
+ list-style-type: none;
+ }
+#mainmenu li {
+ background-color: inherit;
+ padding: .1em 0em .1em 1em;
+ }
+
+#mainmenu a:hover {
+ display: block;
+// background: transparent url("/static/unselected.gif") repeat top left;
+// background-color: #f8f8f8;
+// color: #669;
+ text-decoration: underline;
+ }
+
+#mainmenu #selected {
+ background-color: #fff;
+ // border: 1px solid #666;
+ //border-right: 1px solid #ffd;
+ }
+
+
+/*----------------------------------------------------------------------------------
+ * Submenu ( Horizontal Tabs)
+ *----------------------------------------------------------------------------------
+ */
+#submenu {
+ width: 75%;
+ margin: 0 1em 0 0;
+// font-weight: Bold;
+ background: transparent url(/static/greypx.gif) repeat-x bottom left;
+ float: right;
+ }
+
+#submenu p {
+ display: none;
+ }
+
+#submenu h2 {
+ font-weight: normal;
+ font-size: 161%;
+ color: #228;
+ float: left;
+ margin: 0em;
+ margin-top: .2em;
+ }
+
+#submenu ul {
+ margin: 0em 2em 0em 0em;
+ list-style: none;
+ padding: 0em 2em 0em 2em;
+ float: right;
+ background: transparent;
+ }
+
+#submenu li {
+ // display: block;
+ // float: left;
+ // border: 1px solid #666;
+ // padding: .5em 1em .6em 1em;
+ // margin: 0em .5em 0em .5em;
+ // border-bottom: none;
+ color: #33A;
+ background: transparent url("/static/unselected.gif") repeat-x top left;
+ float: left;
+ margin: 0;
+ padding: 0;
+ }
+
+#submenu #selected {
+ // background: #fff url("/static/selected.gif") repeat-x top left;
+ background: #fff;
+ display: block;
+ float: left;
+ margin: 0em;
+ padding: .75em 1em;
+ border: 1px solid #ccc;
+ border-bottom: none;
+ }
+
+
+#submenu a {
+ display: block;
+ float: left;
+ margin: 0em;
+ padding: .75em 1em;
+ border: 1px solid #ccc;
+ border-bottom: none;
+ // background: #eee;
+ }
+
+#submenu a:hover {
+ // color: #226;
+// background: #eee;
+ text-decoration: underline;
+ }
+
+/*----------------------------------------------------------------------------------
+ * Content
+ *----------------------------------------------------------------------------------
+ */
+#content {
+ display: block;
+ float:left;
+ width: 70%;
+ color: #333;
+ padding: 2em 0em 3em 3em;
+ // border-left: #ccc 1px solid;
+ }
+
+#content h1 {
+ font-size: 120%;
+ // width: 100%;
+ background-color: #eee;
+ border-bottom: 2px solid #aaa;
+ margin: 1em 0em 1em 0em;
+ clear: both;
+ }
+
+#content h2 {
+ font-size: 100%;
+ // width: 100%;
+ background-color: #eee;
+ border-bottom: 1px solid #aaa;
+ // margin: 1em 1em 0em 1em;
+ clear: both;
+ }
+
+#content h3 {
+ font-size: 100%;
+ // width: 100%;
+ background-color: #fff;
+ border-bottom: 0px solid #eee;
+ margin: 0em 0em 0em 0em;
+ clear: both;
+ }
+
+#content p {
+ // margin: 1em 1em 0em 1em;
+ clear: both;
+ padding: .5em 0em .5em 0em;
+ }
+
+#content p.error {
+ // border: 2px solid #c00;
+ // margin: 1em 2em;
+ // padding: 1em 0em;
+ font-size: 120%;
+ font-weight: bold;
+ background-color: #eee;
+ color: #f44;
+ }
+
+#content p.warn {
+ // border: 2px solid #cc0;
+ // margin: 1em 2em;
+ // padding: 1em;
+ background-color: #cc4;
+ }
+
+#content p.ok {
+ font-size: 120%;
+ font-weight: bold;
+ // border: 2px solid #0c0;
+ // margin: 1em 2em;
+ // padding: 1em 0em;
+ color: #090;
+ }
+
+
+#content input, textarea {
+ float: left;
+ background-color: #eee;
+ margin-top: -0.3em;
+ }
+
+
+#content input.error {
+ /* yellow snow - bad */
+ background-color: #ffa;
+ }
+
+#content input.button {
+ font-family: Geneva, Arial, Helvetica, Serif;
+ font-size: 100%;
+ font-weight: bold;
+ color: #228;
+ }
+
+#content dt {
+ font-size: 110%;
+ // font-weight: bold;
+ color: #228;
+ margin: .7em 1em .5em 0em;
+ float: left;
+ border-top: 1px dotted #ccf;
+ border-bottom: 1px dotted #ccf;
+ // background-color: #eef;
+ width: 20%;
+ clear: both;
+ }
+
+#content th {
+ font-weight: inherit;
+ color: #228;
+ background: #eef;
+ }
+
+#content a {
+ text-decoration: underline;
+ color: #449;
+ }
+
+#content form {
+ padding: 1em 0em;
+ }
+
+#content dl {
+ margin: 0em;
+ }
+
+#content dd {
+ color: #444;
+ float: left;
+ margin: 1em 0em .5em 0em;
+ // font-size: 90%;
+ font-weight: light;
+ // margin: .5em 1em .5em 0em;
+ // border-top: 1px dotted #ccc;
+ // border-bottom: 1px dotted #ccc;
+ }
+
+#content .grey {
+ background-color: #eee;
+ }
+
+
+#content form {
+ display: inline;
+ }
+
+
+/*----------------------------------------------------------------------------------
+ * footer
+ *----------------------------------------------------------------------------------
+ */
+
+#footer {
+ float: right;
+ clear: both;
+ text-align: center;
+ font-size: 80%;
+ width: 70%;
+ color: #666;
+ margin: 1em 3em 1em 2em;
+ padding: 1em 0em 1em;
+ border-top: 1px dotted #ccc;
+ border-bottom: 1px dotted #ccc;
+ }