Squashed commit of the following:
authorSteven Barth <steven@midlink.org>
Wed, 28 May 2008 15:28:13 +0000 (15:28 +0000)
committerSteven Barth <steven@midlink.org>
Wed, 28 May 2008 15:28:13 +0000 (15:28 +0000)
commit d45d1757d24d8214f730af1a3401dd2bef4a434f
Author: Steven <steven@cyrus.homeunix.org>
Date:   Wed May 28 17:23:27 2008 +0200

    * libs/core: Removed dummymode checks in sys
    * libs/sgi-webuci: Fixes

commit b870e8d345bc8912fd8ab61d463b9d68b924a6f4
Author: Felix Fietkau <nbd@openwrt.org>
Date:   Wed May 28 15:40:10 2008 +0200

    fix path to theme

commit e3732926bd98db4cc38de6eb8018cd4e55176699
Author: Felix Fietkau <nbd@openwrt.org>
Date:   Wed May 28 14:56:03 2008 +0200

    set the proper path to the config in dummy mode

commit a75aecf46f037c98bd6e49b9e48adb735d76d150
Author: Felix Fietkau <nbd@openwrt.org>
Date:   Wed May 28 14:50:42 2008 +0200

    add some dummy mode support

commit 12bb39ef606bca6b403cc982213a6597b76dc1b3
Author: Felix Fietkau <nbd@openwrt.org>
Date:   Wed May 28 14:41:56 2008 +0200

    normalize paths

commit 7aaad1103fd2bdc75aca158baa6ef191f9a961c6
Author: Felix Fietkau <nbd@openwrt.org>
Date:   Wed May 28 14:27:26 2008 +0200

    add missing require statement

commit 5766274bd2511b00c42b474aeeeb3efaca6ded9b
Author: Felix Fietkau <nbd@openwrt.org>
Date:   Wed May 28 14:19:54 2008 +0200

    add optional luaposix package (patched for darwin support)

commit 9e257a76d03722fc0ce8312aa9952641b21424bd
Author: Felix Fietkau <nbd@openwrt.org>
Date:   Tue May 27 20:21:59 2008 +0200

    add missing files, more integration for the boa plugin, fix path to lua modules

commit dacc1a98ec946975fcb19f87076dfa7db865fca6
Author: Felix Fietkau <nbd@openwrt.org>
Date:   Tue May 27 19:42:37 2008 +0200

    use "compile" instead of "source" and rename the old version of compile to "compile-all"

commit eb14777c4fee1eb5740aba1e5603e481320da7b1
Author: Felix Fietkau <nbd@openwrt.org>
Date:   Tue May 27 19:41:59 2008 +0200

    more boa integration

commit df0afb965bf0a987b653e9d0acadf3151179a596
Author: Felix Fietkau <nbd@openwrt.org>
Date:   Tue May 27 18:33:42 2008 +0200

    build boa and the webuci.so plugin along with sgi-webuci

commit 878161dabf32066631103d199e2cbaf3f5a7fb07
Author: Felix Fietkau <nbd@openwrt.org>
Date:   Tue May 27 18:03:16 2008 +0200

    add .gitignore

24 files changed:
.gitignore [new file with mode: 0644]
Makefile
build/config.mk
build/module.mk
contrib/luaposix/.gitignore [new file with mode: 0644]
contrib/luaposix/Makefile [new file with mode: 0644]
contrib/luaposix/patches/100-darwin_compile.patch [new file with mode: 0644]
libs/core/luasrc/sys.lua
libs/sgi-webuci/.gitignore [new file with mode: 0644]
libs/sgi-webuci/Makefile
libs/sgi-webuci/boa-patches/100-no_tz.patch [new file with mode: 0644]
libs/sgi-webuci/boa-patches/200-plugin_api.patch [new file with mode: 0644]
libs/sgi-webuci/luasrc/sgi/webuci.lua
libs/sgi-webuci/root/etc/boa/boa.conf [new file with mode: 0644]
libs/sgi-webuci/root/etc/mime.types [new file with mode: 0644]
libs/sgi-webuci/root/lib/webuci/main.lua [deleted file]
libs/sgi-webuci/root/usr/lib/boa/luci.lua [new file with mode: 0644]
libs/sgi-webuci/src/cgi.c [new file with mode: 0644]
libs/sgi-webuci/src/luci.c [new file with mode: 0644]
libs/web/root/etc/config/luci
themes/fledermaus/root/www/luci-static/fledermaus/cascade.css [new file with mode: 0644]
themes/fledermaus/root/www/luci-static/fledermaus/logo.png [new file with mode: 0644]
themes/fledermaus/root/www/luci/fledermaus/cascade.css [deleted file]
themes/fledermaus/root/www/luci/fledermaus/logo.png [deleted file]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..bf9420c
--- /dev/null
@@ -0,0 +1,2 @@
+dist/
+/host
index 4b3fb64f4b7bc8712f650be789212fa83a4b9055..d76be9a2de8b0b8b5838a7a4d4a738fca348bed0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,12 @@
 include build/config.mk
 
 MODULES = applications/* libs/* modules/* themes/* i18n/*
-LUA_TARGET = source
-
+LUA_TARGET = compile
+OS:=$(shell uname)
+export OS
+ifeq ($(OS),Darwin)
+  MODULES += contrib/luaposix
+endif
 
 .PHONY: all build clean host hostclean
 
index 66585289b9453bca577f01e20e34710fa885c1a7..9db99cd6ba1f47ab6fa18677b0e72de4a28373fe 100644 (file)
@@ -1,3 +1,28 @@
+OS ?= $(shell uname)
+
 LUAC = luac
 LUAC_OPTIONS = -s
-LUCI_INSTALLDIR = /usr/lib/lua/luci
\ No newline at end of file
+LUCI_INSTALLDIR = /usr/lib/lua/luci
+LUA_SHLIBS = $(shell pkg-config --silence-errors --libs lua5.1)
+LUA_LIBS = $(if $(LUA_SHLIBS),$(LUA_SHLIBS),$(firstword $(wildcard /usr/lib/liblua.a /usr/local/lib/liblua.a /opt/local/lib/liblua.a)))
+LUA_CFLAGS = $(shell pkg-config --silence-errors --cflags lua5.1)
+ifeq ($(LUA_LIBS),)
+  $(error LUA installation not found)
+endif
+
+CC = gcc
+AR = ar
+RANLIB = ranlib
+CFLAGS = -O2
+FPIC = -fPIC
+EXTRA_CFLAGS = --std=gnu99
+WFLAGS = -Wall -Werror -pedantic
+CPPFLAGS =
+COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) $(WFLAGS)
+ifeq ($(OS),Darwin)
+  SHLIB_FLAGS = -bundle -undefined dynamic_lookup
+else
+  SHLIB_FLAGS = -shared
+endif
+LINK = $(CC)
+
index 28731469642ce3b61afbcfcba3d5cd6e0ee57e29..923caad70c4ac86a7d10712b468d85c45fd989cd 100644 (file)
@@ -1,7 +1,8 @@
 .PHONY: all compile compile-module source source-module clean clean-module
 
 all: compile
-compile: compile-module
+compile: source-module
+compile-all: compile-module
 clean: clean-module
 source: source-module
 
diff --git a/contrib/luaposix/.gitignore b/contrib/luaposix/.gitignore
new file mode 100644 (file)
index 0000000..c900421
--- /dev/null
@@ -0,0 +1,2 @@
+luaposix-*
+patches/series
diff --git a/contrib/luaposix/Makefile b/contrib/luaposix/Makefile
new file mode 100644 (file)
index 0000000..4f16b53
--- /dev/null
@@ -0,0 +1,43 @@
+include ../../build/config.mk
+
+LUAPOSIX_VERSION = 5.1.2
+LUAPOSIX_SITE = http://luaforge.net/frs/download.php/3063/
+LUAPOSIX_DIR = luaposix-$(LUAPOSIX_VERSION)
+LUAPOSIX_FILE = $(LUAPOSIX_DIR).tar.gz
+LUAPOSIX_URL = $(LUAPOSIX_SITE)/$(LUAPOSIX_FILE)
+LUAPOSIX_PATCHDIR = patches
+
+all: compile
+
+$(LUAPOSIX_FILE):
+       wget -O $@ $(LUAPOSIX_URL) || rm -f $@
+
+$(LUAPOSIX_PATCHDIR)/series:
+       (cd $(LUAPOSIX_PATCHDIR); ls *.patch | sort > series)
+
+$(LUAPOSIX_DIR)/.prepared: $(LUAPOSIX_FILE)
+       rm -rf $(LUAPOSIX_DIR)
+       tar xvfz $(LUAPOSIX_FILE)
+       ln -s ../$(LUAPOSIX_PATCHDIR) $(LUAPOSIX_DIR)/patches
+       touch $@
+
+$(LUAPOSIX_DIR)/.patched: $(LUAPOSIX_DIR)/.prepared $(LUAPOSIX_PATCHDIR)/series
+       (cd $(LUAPOSIX_DIR); \
+               if [ -x "$$(which quilt 2>/dev/null)" ]; then \
+                       quilt push -a; \
+               else \
+                       cat patches/*.patch | patch -p1; \
+               fi; \
+       )
+       touch $@
+
+compile: $(LUAPOSIX_DIR)/.patched
+       $(MAKE) -C $(LUAPOSIX_DIR) CC=$(CC) CFLAGS="$(CFLAGS)" OS="$(OS)"
+       mkdir -p dist/usr/lib/lua
+       cp $(LUAPOSIX_DIR)/posix.so dist/usr/lib/lua/
+
+compile-all: compile
+
+clean:
+       rm -rf $(LUAPOSIX_DIR) $(LUAPOSIX_FILE)
+       rm -f $(LUAPOSIX_PATCHDIR)/series
diff --git a/contrib/luaposix/patches/100-darwin_compile.patch b/contrib/luaposix/patches/100-darwin_compile.patch
new file mode 100644 (file)
index 0000000..07943ac
--- /dev/null
@@ -0,0 +1,27 @@
+Index: luaposix-5.1.2/Makefile
+===================================================================
+--- luaposix-5.1.2.orig/Makefile       2008-01-29 14:49:27.000000000 +0100
++++ luaposix-5.1.2/Makefile    2008-05-28 14:15:30.000000000 +0200
+@@ -34,6 +34,13 @@
+ T=            $(MYLIB).so
++OS=$(shell uname)
++ifeq ($(OS),Darwin)
++  LDFLAGS_SHARED=-bundle -undefined dynamic_lookup
++else
++  LDFLAGS_SHARED=-shared
++endif
++
+ # targets
+ phony += all
+ all:  $T
+@@ -43,7 +50,7 @@
+       $(LUA) test.lua
+ $T:   $(OBJS)
+-      $(CC) $(LDFLAGS) -o $@ -shared $(OBJS)
++      $(CC) $(LDFLAGS) -o $@ $(LDFLAGS_SHARED) $(OBJS)
+ $(OBJS): modemuncher.c
index 0399d0e5f0a972fb362e6a75136673dec179ba25..6d03f59dbcf017b92f457104ae0ce044fce2c6bb 100644 (file)
@@ -368,4 +368,4 @@ function _parse_mixed_record(cnt)
        end
                
     return data
-end
\ No newline at end of file
+end
diff --git a/libs/sgi-webuci/.gitignore b/libs/sgi-webuci/.gitignore
new file mode 100644 (file)
index 0000000..e6f1e58
--- /dev/null
@@ -0,0 +1,4 @@
+boa-patches/series
+boa-*.*
+*.o
+*.so
index 81a96f6a83ab4f206d7f63a674b53af6312a7d94..9efe0fe14e6d5c1af1d3cea2bece750021dbdc41 100644 (file)
@@ -1,2 +1,51 @@
 include ../../build/config.mk
-include ../../build/module.mk
\ No newline at end of file
+include ../../build/module.mk
+
+BOA_VERSION = 0.94.13
+BOA_SITE = http://www.boa.org
+BOA_DIR = boa-$(BOA_VERSION)
+BOA_FILE = $(BOA_DIR).tar.gz
+BOA_URL = $(BOA_SITE)/$(BOA_FILE)
+BOA_PATCHDIR = boa-patches
+
+$(BOA_FILE):
+       wget -O $@ $(BOA_URL) || rm -f $@
+
+$(BOA_PATCHDIR)/series:
+       (cd $(BOA_PATCHDIR); ls *.patch | sort > series)
+
+$(BOA_DIR)/.prepared: $(BOA_FILE)
+       rm -rf $(BOA_DIR)
+       tar xvfz $(BOA_FILE)
+       ln -s ../$(BOA_PATCHDIR) $(BOA_DIR)/patches
+       touch $@
+
+$(BOA_DIR)/.patched: $(BOA_DIR)/.prepared $(BOA_PATCHDIR)/series
+       (cd $(BOA_DIR); \
+               if [ -x "$$(which quilt 2>/dev/null)" ]; then \
+                       quilt push -a; \
+               else \
+                       cat patches/*.patch | patch -p1; \
+               fi; \
+       )
+       touch $@
+
+$(BOA_DIR)/.configured: $(BOA_DIR)/.patched
+       (cd $(BOA_DIR)/src; ./configure --disable-debug) 
+       touch $@
+
+boa-compile: $(BOA_DIR)/.configured
+       $(MAKE) -C $(BOA_DIR)/src CC=$(CC) CFLAGS="$(CFLAGS)"
+
+%.o: %.c
+       $(COMPILE) $(LUA_CFLAGS) -I$(BOA_DIR)/src $(FPIC) -c -o $@ $< 
+
+compile: boa-compile src/luci.o src/cgi.o
+       mkdir -p dist/usr/bin dist/usr/lib/boa
+       cp $(BOA_DIR)/src/boa $(BOA_DIR)/src/boa_indexer dist/usr/bin
+       $(LINK) $(SHLIB_FLAGS) $(LUA_SHLIBS) -o dist/usr/lib/boa/luci.so src/luci.o src/cgi.o $(LUA_LIBS)
+
+clean:
+       rm -rf $(BOA_DIR) $(BOA_FILE)
+       rm -f boa-patches/series
+       rm -f src/*.o
diff --git a/libs/sgi-webuci/boa-patches/100-no_tz.patch b/libs/sgi-webuci/boa-patches/100-no_tz.patch
new file mode 100644 (file)
index 0000000..639677e
--- /dev/null
@@ -0,0 +1,22 @@
+diff -urN boa-0.94.13/src/util.c boa/src/util.c
+--- boa-0.94.13/src/util.c     2002-07-08 01:22:18.000000000 +0200
++++ boa/src/util.c     2008-04-25 21:56:20.000000000 +0200
+@@ -95,14 +95,9 @@
+     static char buf[30];
+     int time_offset;
+-    if (use_localtime) {
+-        t = localtime(&current_time);
+-        time_offset = TIMEZONE_OFFSET(t);
+-    } else {
+-        t = gmtime(&current_time);
+-        time_offset = 0;
+-    }
+-
++      t = gmtime(&current_time);
++    time_offset = 0;
++    
+     p = buf + 29;
+     *p-- = '\0';
+     *p-- = ' ';
+
diff --git a/libs/sgi-webuci/boa-patches/200-plugin_api.patch b/libs/sgi-webuci/boa-patches/200-plugin_api.patch
new file mode 100644 (file)
index 0000000..de79991
--- /dev/null
@@ -0,0 +1,1089 @@
+Index: boa-0.94.13/src/list.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ boa-0.94.13/src/list.h     2008-05-27 19:28:21.000000000 +0200
+@@ -0,0 +1,601 @@
++#ifndef _LINUX_LIST_H
++#define _LINUX_LIST_H
++
++#include <stddef.h>
++/**
++ * container_of - cast a member of a structure out to the containing structure
++ * @ptr:      the pointer to the member.
++ * @type:     the type of the container struct this is embedded in.
++ * @member:   the name of the member within the struct.
++ *
++ */
++#ifndef container_of
++#define container_of(ptr, type, member) (                     \
++      (type *)( (char *)ptr - offsetof(type,member) ))
++#endif
++
++
++/*
++ * Simple doubly linked list implementation.
++ *
++ * Some of the internal functions ("__xxx") are useful when
++ * manipulating whole lists rather than single entries, as
++ * sometimes we already know the next/prev entries and we can
++ * generate better code by using them directly rather than
++ * using the generic single-entry routines.
++ */
++
++struct list_head {
++      struct list_head *next, *prev;
++};
++
++#define LIST_HEAD_INIT(name) { &(name), &(name) }
++
++#define LIST_HEAD(name) \
++      struct list_head name = LIST_HEAD_INIT(name)
++
++static inline void INIT_LIST_HEAD(struct list_head *list)
++{
++      list->next = list;
++      list->prev = list;
++}
++
++/*
++ * Insert a new entry between two known consecutive entries.
++ *
++ * This is only for internal list manipulation where we know
++ * the prev/next entries already!
++ */
++static inline void __list_add(struct list_head *new,
++                            struct list_head *prev,
++                            struct list_head *next)
++{
++      next->prev = new;
++      new->next = next;
++      new->prev = prev;
++      prev->next = new;
++}
++
++/**
++ * list_add - add a new entry
++ * @new: new entry to be added
++ * @head: list head to add it after
++ *
++ * Insert a new entry after the specified head.
++ * This is good for implementing stacks.
++ */
++static inline void list_add(struct list_head *new, struct list_head *head)
++{
++      __list_add(new, head, head->next);
++}
++
++
++/**
++ * list_add_tail - add a new entry
++ * @new: new entry to be added
++ * @head: list head to add it before
++ *
++ * Insert a new entry before the specified head.
++ * This is useful for implementing queues.
++ */
++static inline void list_add_tail(struct list_head *new, struct list_head *head)
++{
++      __list_add(new, head->prev, head);
++}
++
++
++/*
++ * Delete a list entry by making the prev/next entries
++ * point to each other.
++ *
++ * This is only for internal list manipulation where we know
++ * the prev/next entries already!
++ */
++static inline void __list_del(struct list_head * prev, struct list_head * next)
++{
++      next->prev = prev;
++      prev->next = next;
++}
++
++/**
++ * list_del - deletes entry from list.
++ * @entry: the element to delete from the list.
++ * Note: list_empty() on entry does not return true after this, the entry is
++ * in an undefined state.
++ */
++static inline void list_del(struct list_head *entry)
++{
++      __list_del(entry->prev, entry->next);
++      entry->next = NULL;
++      entry->prev = NULL;
++}
++
++/**
++ * list_replace - replace old entry by new one
++ * @old : the element to be replaced
++ * @new : the new element to insert
++ *
++ * If @old was empty, it will be overwritten.
++ */
++static inline void list_replace(struct list_head *old,
++                              struct list_head *new)
++{
++      new->next = old->next;
++      new->next->prev = new;
++      new->prev = old->prev;
++      new->prev->next = new;
++}
++
++static inline void list_replace_init(struct list_head *old,
++                                      struct list_head *new)
++{
++      list_replace(old, new);
++      INIT_LIST_HEAD(old);
++}
++
++/**
++ * list_del_init - deletes entry from list and reinitialize it.
++ * @entry: the element to delete from the list.
++ */
++static inline void list_del_init(struct list_head *entry)
++{
++      __list_del(entry->prev, entry->next);
++      INIT_LIST_HEAD(entry);
++}
++
++/**
++ * list_move - delete from one list and add as another's head
++ * @list: the entry to move
++ * @head: the head that will precede our entry
++ */
++static inline void list_move(struct list_head *list, struct list_head *head)
++{
++      __list_del(list->prev, list->next);
++      list_add(list, head);
++}
++
++/**
++ * list_move_tail - delete from one list and add as another's tail
++ * @list: the entry to move
++ * @head: the head that will follow our entry
++ */
++static inline void list_move_tail(struct list_head *list,
++                                struct list_head *head)
++{
++      __list_del(list->prev, list->next);
++      list_add_tail(list, head);
++}
++
++/**
++ * list_is_last - tests whether @list is the last entry in list @head
++ * @list: the entry to test
++ * @head: the head of the list
++ */
++static inline int list_is_last(const struct list_head *list,
++                              const struct list_head *head)
++{
++      return list->next == head;
++}
++
++/**
++ * list_empty - tests whether a list is empty
++ * @head: the list to test.
++ */
++static inline int list_empty(const struct list_head *head)
++{
++      return head->next == head;
++}
++
++/**
++ * list_empty_careful - tests whether a list is empty and not being modified
++ * @head: the list to test
++ *
++ * Description:
++ * tests whether a list is empty _and_ checks that no other CPU might be
++ * in the process of modifying either member (next or prev)
++ *
++ * NOTE: using list_empty_careful() without synchronization
++ * can only be safe if the only activity that can happen
++ * to the list entry is list_del_init(). Eg. it cannot be used
++ * if another CPU could re-list_add() it.
++ */
++static inline int list_empty_careful(const struct list_head *head)
++{
++      struct list_head *next = head->next;
++      return (next == head) && (next == head->prev);
++}
++
++static inline void __list_splice(struct list_head *list,
++                               struct list_head *head)
++{
++      struct list_head *first = list->next;
++      struct list_head *last = list->prev;
++      struct list_head *at = head->next;
++
++      first->prev = head;
++      head->next = first;
++
++      last->next = at;
++      at->prev = last;
++}
++
++/**
++ * list_splice - join two lists
++ * @list: the new list to add.
++ * @head: the place to add it in the first list.
++ */
++static inline void list_splice(struct list_head *list, struct list_head *head)
++{
++      if (!list_empty(list))
++              __list_splice(list, head);
++}
++
++/**
++ * list_splice_init - join two lists and reinitialise the emptied list.
++ * @list: the new list to add.
++ * @head: the place to add it in the first list.
++ *
++ * The list at @list is reinitialised
++ */
++static inline void list_splice_init(struct list_head *list,
++                                  struct list_head *head)
++{
++      if (!list_empty(list)) {
++              __list_splice(list, head);
++              INIT_LIST_HEAD(list);
++      }
++}
++
++/**
++ * list_entry - get the struct for this entry
++ * @ptr:      the &struct list_head pointer.
++ * @type:     the type of the struct this is embedded in.
++ * @member:   the name of the list_struct within the struct.
++ */
++#define list_entry(ptr, type, member) \
++      container_of(ptr, type, member)
++
++/**
++ * list_first_entry - get the first element from a list
++ * @ptr:      the list head to take the element from.
++ * @type:     the type of the struct this is embedded in.
++ * @member:   the name of the list_struct within the struct.
++ *
++ * Note, that list is expected to be not empty.
++ */
++#define list_first_entry(ptr, type, member) \
++      list_entry((ptr)->next, type, member)
++
++/**
++ * list_for_each      -       iterate over a list
++ * @pos:      the &struct list_head to use as a loop cursor.
++ * @head:     the head for your list.
++ */
++#define list_for_each(pos, head) \
++      for (pos = (head)->next; pos != (head); \
++              pos = pos->next)
++
++/**
++ * __list_for_each    -       iterate over a list
++ * @pos:      the &struct list_head to use as a loop cursor.
++ * @head:     the head for your list.
++ *
++ * This variant differs from list_for_each() in that it's the
++ * simplest possible list iteration code, no prefetching is done.
++ * Use this for code that knows the list to be very short (empty
++ * or 1 entry) most of the time.
++ */
++#define __list_for_each(pos, head) \
++      for (pos = (head)->next; pos != (head); pos = pos->next)
++
++/**
++ * list_for_each_prev -       iterate over a list backwards
++ * @pos:      the &struct list_head to use as a loop cursor.
++ * @head:     the head for your list.
++ */
++#define list_for_each_prev(pos, head) \
++      for (pos = (head)->prev; pos != (head); \
++              pos = pos->prev)
++
++/**
++ * list_for_each_safe - iterate over a list safe against removal of list entry
++ * @pos:      the &struct list_head to use as a loop cursor.
++ * @n:                another &struct list_head to use as temporary storage
++ * @head:     the head for your list.
++ */
++#define list_for_each_safe(pos, n, head) \
++      for (pos = (head)->next, n = pos->next; pos != (head); \
++              pos = n, n = pos->next)
++
++/**
++ * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
++ * @pos:      the &struct list_head to use as a loop cursor.
++ * @n:                another &struct list_head to use as temporary storage
++ * @head:     the head for your list.
++ */
++#define list_for_each_prev_safe(pos, n, head) \
++      for (pos = (head)->prev, n = pos->prev; \
++           pos != (head); \
++           pos = n, n = pos->prev)
++
++/**
++ * list_for_each_entry        -       iterate over list of given type
++ * @pos:      the type * to use as a loop cursor.
++ * @head:     the head for your list.
++ * @member:   the name of the list_struct within the struct.
++ */
++#define list_for_each_entry(pos, head, member)                                \
++      for (pos = list_entry((head)->next, typeof(*pos), member);      \
++           &pos->member != (head);    \
++           pos = list_entry(pos->member.next, typeof(*pos), member))
++
++/**
++ * list_for_each_entry_reverse - iterate backwards over list of given type.
++ * @pos:      the type * to use as a loop cursor.
++ * @head:     the head for your list.
++ * @member:   the name of the list_struct within the struct.
++ */
++#define list_for_each_entry_reverse(pos, head, member)                        \
++      for (pos = list_entry((head)->prev, typeof(*pos), member);      \
++           &pos->member != (head);    \
++           pos = list_entry(pos->member.prev, typeof(*pos), member))
++
++/**
++ * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
++ * @pos:      the type * to use as a start point
++ * @head:     the head of the list
++ * @member:   the name of the list_struct within the struct.
++ *
++ * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
++ */
++#define list_prepare_entry(pos, head, member) \
++      ((pos) ? : list_entry(head, typeof(*pos), member))
++
++/**
++ * list_for_each_entry_continue - continue iteration over list of given type
++ * @pos:      the type * to use as a loop cursor.
++ * @head:     the head for your list.
++ * @member:   the name of the list_struct within the struct.
++ *
++ * Continue to iterate over list of given type, continuing after
++ * the current position.
++ */
++#define list_for_each_entry_continue(pos, head, member)               \
++      for (pos = list_entry(pos->member.next, typeof(*pos), member);  \
++           &pos->member != (head);    \
++           pos = list_entry(pos->member.next, typeof(*pos), member))
++
++/**
++ * list_for_each_entry_continue_reverse - iterate backwards from the given point
++ * @pos:      the type * to use as a loop cursor.
++ * @head:     the head for your list.
++ * @member:   the name of the list_struct within the struct.
++ *
++ * Start to iterate over list of given type backwards, continuing after
++ * the current position.
++ */
++#define list_for_each_entry_continue_reverse(pos, head, member)               \
++      for (pos = list_entry(pos->member.prev, typeof(*pos), member);  \
++           &pos->member != (head);    \
++           pos = list_entry(pos->member.prev, typeof(*pos), member))
++
++/**
++ * list_for_each_entry_from - iterate over list of given type from the current point
++ * @pos:      the type * to use as a loop cursor.
++ * @head:     the head for your list.
++ * @member:   the name of the list_struct within the struct.
++ *
++ * Iterate over list of given type, continuing from current position.
++ */
++#define list_for_each_entry_from(pos, head, member)                   \
++      for (; &pos->member != (head);  \
++           pos = list_entry(pos->member.next, typeof(*pos), member))
++
++/**
++ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
++ * @pos:      the type * to use as a loop cursor.
++ * @n:                another type * to use as temporary storage
++ * @head:     the head for your list.
++ * @member:   the name of the list_struct within the struct.
++ */
++#define list_for_each_entry_safe(pos, n, head, member)                        \
++      for (pos = list_entry((head)->next, typeof(*pos), member),      \
++              n = list_entry(pos->member.next, typeof(*pos), member); \
++           &pos->member != (head);                                    \
++           pos = n, n = list_entry(n->member.next, typeof(*n), member))
++
++/**
++ * list_for_each_entry_safe_continue
++ * @pos:      the type * to use as a loop cursor.
++ * @n:                another type * to use as temporary storage
++ * @head:     the head for your list.
++ * @member:   the name of the list_struct within the struct.
++ *
++ * Iterate over list of given type, continuing after current point,
++ * safe against removal of list entry.
++ */
++#define list_for_each_entry_safe_continue(pos, n, head, member)               \
++      for (pos = list_entry(pos->member.next, typeof(*pos), member),          \
++              n = list_entry(pos->member.next, typeof(*pos), member);         \
++           &pos->member != (head);                                            \
++           pos = n, n = list_entry(n->member.next, typeof(*n), member))
++
++/**
++ * list_for_each_entry_safe_from
++ * @pos:      the type * to use as a loop cursor.
++ * @n:                another type * to use as temporary storage
++ * @head:     the head for your list.
++ * @member:   the name of the list_struct within the struct.
++ *
++ * Iterate over list of given type from current point, safe against
++ * removal of list entry.
++ */
++#define list_for_each_entry_safe_from(pos, n, head, member)                   \
++      for (n = list_entry(pos->member.next, typeof(*pos), member);            \
++           &pos->member != (head);                                            \
++           pos = n, n = list_entry(n->member.next, typeof(*n), member))
++
++/**
++ * list_for_each_entry_safe_reverse
++ * @pos:      the type * to use as a loop cursor.
++ * @n:                another type * to use as temporary storage
++ * @head:     the head for your list.
++ * @member:   the name of the list_struct within the struct.
++ *
++ * Iterate backwards over list of given type, safe against removal
++ * of list entry.
++ */
++#define list_for_each_entry_safe_reverse(pos, n, head, member)                \
++      for (pos = list_entry((head)->prev, typeof(*pos), member),      \
++              n = list_entry(pos->member.prev, typeof(*pos), member); \
++           &pos->member != (head);                                    \
++           pos = n, n = list_entry(n->member.prev, typeof(*n), member))
++
++/*
++ * Double linked lists with a single pointer list head.
++ * Mostly useful for hash tables where the two pointer list head is
++ * too wasteful.
++ * You lose the ability to access the tail in O(1).
++ */
++
++struct hlist_head {
++      struct hlist_node *first;
++};
++
++struct hlist_node {
++      struct hlist_node *next, **pprev;
++};
++
++#define HLIST_HEAD_INIT { .first = NULL }
++#define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
++#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
++static inline void INIT_HLIST_NODE(struct hlist_node *h)
++{
++      h->next = NULL;
++      h->pprev = NULL;
++}
++
++static inline int hlist_unhashed(const struct hlist_node *h)
++{
++      return !h->pprev;
++}
++
++static inline int hlist_empty(const struct hlist_head *h)
++{
++      return !h->first;
++}
++
++static inline void __hlist_del(struct hlist_node *n)
++{
++      struct hlist_node *next = n->next;
++      struct hlist_node **pprev = n->pprev;
++      *pprev = next;
++      if (next)
++              next->pprev = pprev;
++}
++
++static inline void hlist_del(struct hlist_node *n)
++{
++      __hlist_del(n);
++      n->next = NULL;
++      n->pprev = NULL;
++}
++
++static inline void hlist_del_init(struct hlist_node *n)
++{
++      if (!hlist_unhashed(n)) {
++              __hlist_del(n);
++              INIT_HLIST_NODE(n);
++      }
++}
++
++
++static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
++{
++      struct hlist_node *first = h->first;
++      n->next = first;
++      if (first)
++              first->pprev = &n->next;
++      h->first = n;
++      n->pprev = &h->first;
++}
++
++
++/* next must be != NULL */
++static inline void hlist_add_before(struct hlist_node *n,
++                                      struct hlist_node *next)
++{
++      n->pprev = next->pprev;
++      n->next = next;
++      next->pprev = &n->next;
++      *(n->pprev) = n;
++}
++
++static inline void hlist_add_after(struct hlist_node *n,
++                                      struct hlist_node *next)
++{
++      next->next = n->next;
++      n->next = next;
++      next->pprev = &n->next;
++
++      if(next->next)
++              next->next->pprev  = &next->next;
++}
++
++#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
++
++#define hlist_for_each(pos, head) \
++      for (pos = (head)->first; pos; pos = pos->next)
++
++#define hlist_for_each_safe(pos, n, head) \
++      for (pos = (head)->first; pos; pos = n)
++
++/**
++ * hlist_for_each_entry       - iterate over list of given type
++ * @tpos:     the type * to use as a loop cursor.
++ * @pos:      the &struct hlist_node to use as a loop cursor.
++ * @head:     the head for your list.
++ * @member:   the name of the hlist_node within the struct.
++ */
++#define hlist_for_each_entry(tpos, pos, head, member)                  \
++      for (pos = (head)->first; pos &&                                 \
++              ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
++           pos = pos->next)
++
++/**
++ * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
++ * @tpos:     the type * to use as a loop cursor.
++ * @pos:      the &struct hlist_node to use as a loop cursor.
++ * @member:   the name of the hlist_node within the struct.
++ */
++#define hlist_for_each_entry_continue(tpos, pos, member)              \
++      for (pos = (pos)->next; pos &&                                  \
++           ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;});   \
++           pos = pos->next)
++
++/**
++ * hlist_for_each_entry_from - iterate over a hlist continuing from current point
++ * @tpos:     the type * to use as a loop cursor.
++ * @pos:      the &struct hlist_node to use as a loop cursor.
++ * @member:   the name of the hlist_node within the struct.
++ */
++#define hlist_for_each_entry_from(tpos, pos, member)                   \
++      for (; pos &&                    \
++              ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
++           pos = pos->next)
++
++/**
++ * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
++ * @tpos:     the type * to use as a loop cursor.
++ * @pos:      the &struct hlist_node to use as a loop cursor.
++ * @n:                another &struct hlist_node to use as temporary storage
++ * @head:     the head for your list.
++ * @member:   the name of the hlist_node within the struct.
++ */
++#define hlist_for_each_entry_safe(tpos, pos, n, head, member)                  \
++      for (pos = (head)->first;                                        \
++           pos && ({ n = pos->next; 1; }) &&                           \
++              ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
++           pos = n)
++
++#endif
+Index: boa-0.94.13/src/plugin.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ boa-0.94.13/src/plugin.c   2008-05-27 19:28:21.000000000 +0200
+@@ -0,0 +1,189 @@
++/*
++ * Simple plugin API for boa
++ * Copyright (C) 2008 John Crispin <blogic@openwrt.org>
++ * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation.
++ *
++ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include "boa.h"
++#include "list.h"
++#include <dlfcn.h>
++#include <glob.h>
++
++static LIST_HEAD(plugins);
++
++struct httpd_plugin *plugin_lookup(request *req)
++{
++      struct list_head *l;
++      list_for_each(l, &plugins)
++      {
++              struct httpd_plugin *p =
++                      container_of(l, struct httpd_plugin, list);
++
++              if (!strncmp(req->request_uri, p->prefix, strlen(p->prefix)))
++                      return p;
++      }
++      return NULL;
++}
++
++static int plugin_run(request *req, struct httpd_plugin *p)
++{
++      struct http_context ctx;
++    int child_pid;
++
++      SQUASH_KA(req);
++
++      memset(&ctx, 0, sizeof(ctx));
++      ctx.uri = req->request_uri;
++      switch(req->method) {
++              case M_POST:
++                      ctx.request_method = "POST";
++                      break;
++              case M_HEAD:
++                      ctx.request_method = "HEAD";
++                      break;
++              case M_GET:
++                      ctx.request_method = "GET";
++                      break;
++      }
++      ctx.server_addr = req->local_ip_addr;
++      ctx.server_proto = req->http_version;
++      ctx.query_string = req->query_string;
++      ctx.remote_addr = req->remote_ip_addr;
++      ctx.remote_port = req->remote_port;
++      if (req->method == M_POST) {
++              if (req->content_type)
++                      ctx.content_type = req->content_type;
++              else
++                      ctx.content_type = default_type;
++              ctx.content_length = req->content_length;
++      }
++#ifdef ACCEPT_ON
++      if (req->accept[0])
++              ctx.http_accept = req->accept;
++#endif
++
++    p->prepare_req(p, &ctx);
++      child_pid = fork();
++
++      switch(child_pid) {
++    case -1:
++        log_error_time();
++        perror("fork");
++        send_r_error(req);
++        return 0;
++
++      case 0:
++        if (dup2(req->fd, STDOUT_FILENO) == -1) {
++            log_error_time();
++            perror("dup2 - fd");
++            _exit(1);
++        }
++        if (set_block_fd(req->fd) == -1) {
++            log_error_time();
++            perror("cgi-fcntl");
++            _exit(1);
++        }
++        if (req->method == M_POST) {
++            dup2(req->read_data_fd, STDIN_FILENO);
++            close(req->read_data_fd);
++            close(req->post_data_fd);
++                      set_block_fd(STDIN_FILENO);
++        }
++        close_access_log();
++
++        if (cgi_log_fd)
++            dup2(cgi_log_fd, STDERR_FILENO);
++
++          p->handle_req(p, &ctx);
++              exit(0);
++        break;
++    }
++
++    return 1;
++}
++
++int plugin_handle(request * req)
++{
++      struct httpd_plugin *p;
++
++      p = plugin_lookup(req);
++      if (!p)
++              return 0;
++
++      return plugin_run(req, p);
++}
++
++static void plugin_load(const char *p, const char *dir)
++{
++      struct httpd_plugin *plugin;
++      void *dl;
++
++      /* ignore directories */
++      if (p[strlen(p) - 1] == '/')
++              return;
++
++      dl = dlopen(p, RTLD_NOW);
++      if (!dl) {
++              fprintf(stderr, "Unable to load plugin '%s': %d\n", p, dlerror());
++              return;
++      }
++
++      plugin = dlsym(dl, "httpd_plugin");
++      if (!plugin)
++              goto error;
++
++      INIT_LIST_HEAD(&plugin->list);
++      plugin->dir = dir;
++
++      if (plugin->init(plugin) != 1)
++              goto error;
++
++      if (!plugin->prefix)
++              goto error_init;
++
++      list_add(&plugin->list, &plugins);
++      return;
++
++error_init:
++      plugin->done(plugin);
++error:
++      fprintf(stderr, "Plugin '%s' failed to initialize\n", p);
++      dlclose(dl);
++}
++
++#define WILDCARD_SUFFIX "/*.so"
++
++int plugin_init(char *path)
++{
++      int buflen = 128;
++      char *plugindir;
++      glob_t g;
++      char *s;
++      int i;
++
++      s = malloc(strlen(path) + sizeof(WILDCARD_SUFFIX) + 1);
++      strcpy(s, path);
++      strcat(s, WILDCARD_SUFFIX);
++      glob(s, GLOB_MARK, NULL, &g);
++      free(s);
++
++      for (i = 0; i < g.gl_pathc; i++)
++              plugin_load(g.gl_pathv[i], path);
++
++      globfree(&g);
++}
++
++
+Index: boa-0.94.13/src/request.c
+===================================================================
+--- boa-0.94.13.orig/src/request.c     2002-07-24 05:03:59.000000000 +0200
++++ boa-0.94.13/src/request.c  2008-05-27 19:28:21.000000000 +0200
+@@ -50,6 +50,7 @@
+         dequeue(&request_free, request_free); /* dequeue the head */
+     } else {
+         req = (request *) malloc(sizeof (request));
++              memset(req, 0, sizeof(request));
+         if (!req) {
+             log_error_time();
+             perror("malloc for new request");
+@@ -603,6 +604,8 @@
+ int process_header_end(request * req)
+ {
++      int ret;
++
+     if (!req->logline) {
+         send_r_error(req);
+         return 0;
+@@ -630,11 +633,26 @@
+     }
+     if (req->method == M_POST) {
+-        req->post_data_fd = create_temporary_file(1, NULL, 0);
+-        if (req->post_data_fd == 0)
+-            return(0);
+-        return(1); /* success */
+-    }
++              if (!req->plugin) {
++              req->post_data_fd = create_temporary_file(1, NULL, 0);
++              } else {
++                      int fd[2];
++                      if (pipe(&fd[0]) != -1) {
++                              req->post_data_fd = fd[1];
++                              req->read_data_fd = fd[0];
++                              set_nonblock_fd(req->post_data_fd);
++                      }
++              }
++              if (req->post_data_fd == 0) {
++                      return(0);
++              }
++              if (!req->plugin)
++              return(1); /* success */
++    }
++
++      ret = plugin_handle(req);
++      if (ret)
++              return ret;
+     if (req->is_cgi) {
+         return init_cgi(req);
+Index: boa-0.94.13/src/Makefile.in
+===================================================================
+--- boa-0.94.13.orig/src/Makefile.in   2002-03-24 23:20:19.000000000 +0100
++++ boa-0.94.13/src/Makefile.in        2008-05-27 19:28:21.000000000 +0200
+@@ -20,7 +20,7 @@
+ srcdir = @srcdir@
+ VPATH = @srcdir@:@srcdir@/../extras
+ LDFLAGS = @LDFLAGS@
+-LIBS = @LIBS@
++LIBS = @LIBS@ -ldl
+ CFLAGS = @CFLAGS@ -I.
+ # Change these if necessary
+@@ -32,7 +32,8 @@
+ SOURCES = alias.c boa.c buffer.c cgi.c cgi_header.c config.c escape.c \
+       get.c hash.c ip.c log.c mmap_cache.c pipe.c queue.c read.c \
+-      request.c response.c select.c signals.c util.c sublog.c
++      request.c response.c select.c signals.c util.c sublog.c \
++      plugin.c
+ OBJS = y.tab.o lex.yy.o $(SOURCES:.c=.o) timestamp.o @STRUTIL@
+Index: boa-0.94.13/src/boa.h
+===================================================================
+--- boa-0.94.13.orig/src/boa.h 2002-07-26 05:03:44.000000000 +0200
++++ boa-0.94.13/src/boa.h      2008-05-27 19:28:21.000000000 +0200
+@@ -37,6 +37,7 @@
+ #include <fcntl.h>
+ #include <limits.h>             /* OPEN_MAX */
+ #include <setjmp.h>
++#include <stdbool.h>
+ #include <netdb.h>
+ #include <netinet/in.h>
+@@ -50,6 +51,7 @@
+ #include "compat.h"             /* oh what fun is porting */
+ #include "defines.h"
+ #include "globals.h"
++#include "boa-plugin.h"
+ /* alias */
+ void add_alias(char *fakename, char *realname, int script);
+@@ -192,4 +194,9 @@
+ /* select */
+ void select_loop(int server_s);
++/* plugins */
++int plugin_init(char *path);
++int plugin_handle(request * req);
++struct httpd_plugin *plugin_lookup(request *req);
++
+ #endif
+Index: boa-0.94.13/src/config.c
+===================================================================
+--- boa-0.94.13.orig/src/config.c      2002-07-26 05:04:29.000000000 +0200
++++ boa-0.94.13/src/config.c   2008-05-27 19:28:21.000000000 +0200
+@@ -61,6 +61,7 @@
+ char *error_log_name;
+ char *access_log_name;
+ char *cgi_log_name;
++char *plugin_root = NULL;
+ int use_localtime;
+@@ -116,6 +117,7 @@
+     {"SinglePostLimit", S1A, c_set_int, &single_post_limit},
+     {"CGIPath", S1A, c_set_string, &cgi_path},
+     {"MaxConnections", S1A, c_set_int, &max_connections},
++    {"PluginRoot", S1A, c_set_string, &plugin_root},
+ };
+ static void c_set_user(char *v1, char *v2, void *t)
+@@ -323,6 +325,22 @@
+         free(dirmaker);
+         dirmaker = temp;
+     }
++      if (plugin_root) {
++              char *plugin_path = plugin_root;
++              char *next;
++
++              do {
++                      next = strchr(plugin_path, ':');
++                      if (next) {
++                              *next = 0;
++                              next++;
++                      }
++
++                      plugin_init(normalize_path(plugin_path));
++                      plugin_path = next;
++              } while (plugin_path);
++              free(plugin_root);
++      }
+ #if 0
+     if (mime_types) {
+Index: boa-0.94.13/src/alias.c
+===================================================================
+--- boa-0.94.13.orig/src/alias.c       2002-07-28 04:46:52.000000000 +0200
++++ boa-0.94.13/src/alias.c    2008-05-27 19:28:21.000000000 +0200
+@@ -213,6 +213,7 @@
+     uri_len = strlen(req->request_uri);
+     current = find_alias(req->request_uri, uri_len);
++      req->plugin = !!plugin_lookup(req);
+     if (current) {
+         if (current->type == SCRIPTALIAS) /* Script */
+@@ -237,7 +238,7 @@
+         }
+         if (current->type == REDIRECT) { /* Redirect */
+-            if (req->method == M_POST) { /* POST to non-script */
++            if ((req->method == M_POST) && !req->plugin) { /* POST to non-script */
+                 /* it's not a cgi, but we try to POST??? */
+                 send_r_bad_request(req);
+                 return 0;       /* not a script alias, therefore begin filling in data */
+@@ -361,7 +362,7 @@
+         else
+             req->is_cgi = CGI;
+         return 1;
+-    } else if (req->method == M_POST) { /* POST to non-script */
++    } else if ((req->method == M_POST) && !req->plugin) { /* POST to non-script */
+         /* it's not a cgi, but we try to POST??? */
+         send_r_bad_request(req);
+         return 0;
+Index: boa-0.94.13/src/globals.h
+===================================================================
+--- boa-0.94.13.orig/src/globals.h     2002-07-24 05:03:59.000000000 +0200
++++ boa-0.94.13/src/globals.h  2008-05-27 19:28:21.000000000 +0200
+@@ -47,6 +47,7 @@
+ struct request {                /* pending requests */
+     int fd;                     /* client's socket fd */
+     int status;                 /* see #defines.h */
++    bool plugin;
+     time_t time_last;           /* time of last succ. op. */
+     char *pathname;             /* pathname of requested file */
+     int simple;                 /* simple request? */
+@@ -92,6 +93,7 @@
+     char *header_referer;
+     int post_data_fd;           /* fd for post data tmpfile */
++    int read_data_fd;           /* fd for post data input (plugin) */
+     char *path_info;            /* env variable */
+     char *path_translated;      /* env variable */
+Index: boa-0.94.13/src/read.c
+===================================================================
+--- boa-0.94.13.orig/src/read.c        2002-03-18 02:53:48.000000000 +0100
++++ boa-0.94.13/src/read.c     2008-05-27 19:28:21.000000000 +0200
+@@ -338,8 +338,11 @@
+     if (bytes_to_write == 0) {  /* nothing left in buffer to write */
+         req->header_line = req->header_end = req->buffer;
+-        if (req->filepos >= req->filesize)
+-            return init_cgi(req);
++        if (req->filepos >= req->filesize) {
++                      if (req->post_data_fd > 0)
++                              close(req->post_data_fd);
++              return init_cgi(req);
++              }
+         /* if here, we can safely assume that there is more to read */
+         req->status = BODY_READ;
+         return 1;
+Index: boa-0.94.13/src/boa-plugin.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ boa-0.94.13/src/boa-plugin.h       2008-05-27 19:28:21.000000000 +0200
+@@ -0,0 +1,67 @@
++#ifndef _HTTPD_PLUGIN_H__
++#define _HTTPD_PLUGIN_H__
++
++#include "list.h"
++
++/*
++ * Definition for HTTP server plugins
++ *
++ * The context that the plugin is called with for
++ * a single http request. It gets allocated in the
++ * persistent context before prepare_req and freed
++ * there afterwards (still active in the forked
++ * context at handle_req time)
++ */
++struct http_context
++{
++      char *uri;
++      char *request_method;
++      char *server_addr;
++      char *server_proto;
++      char *query_string;
++      char *remote_addr;
++      unsigned int remote_port;
++      char *content_type;
++      char *content_length;
++      char *http_accept;
++
++      void *priv;
++};
++
++/*
++ * the main data structure of httpd plugins.
++ */
++struct httpd_plugin
++{
++      /* used by the web server */
++      struct list_head list;
++
++      /* only page requests matching 'prefix' are passed
++       * to prepare_req and handle_req */
++      const char *prefix;
++
++      /* directory that the plugin was found in */
++      const char *dir;
++
++      /* initialize the plugin, if the return value is nonzero,
++       * the plugin will not be used */
++      int (*init)(struct httpd_plugin *);
++
++      /* free all memory associated with the plugin */
++      void (*done)(struct httpd_plugin *);
++
++      /* prepare a page request. this is executed in the main context,
++       * so pay attention to memory usage. should not print any data
++       * to stdout */
++      int (*prepare_req)(struct httpd_plugin *, struct http_context *);
++
++      /* handle the request. can print output data to stdout */
++      int (*handle_req)(struct httpd_plugin *, struct http_context *);
++
++      /* pointer for private data structures of the plugin */
++      void *priv;
++};
++
++#define HTTPD_PLUGIN struct httpd_plugin httpd_plugin =
++
++#endif
index 498bca9214d58d0b3bcb3061f5b68f64f9ad44f3..2beff690711e5f6ea823a64c65e58b17780407b2 100644 (file)
@@ -28,8 +28,9 @@ module("luci.sgi.webuci", package.seeall)
 local status_set = false
 
 -- Initialize the environment
-function initenv(env)
+function initenv(env, vars)
        luci.http.env = env
+       luci.http.vars = vars
 end
 
 -- Returns the main dispatcher URL
@@ -44,7 +45,7 @@ end
 
 -- Returns a table of all COOKIE, GET and POST Parameters
 function luci.http.formvalues()
-       return webuci.vars
+       return luci.http.vars
 end
 
 -- Gets form value from key
diff --git a/libs/sgi-webuci/root/etc/boa/boa.conf b/libs/sgi-webuci/root/etc/boa/boa.conf
new file mode 100644 (file)
index 0000000..ce1dfb2
--- /dev/null
@@ -0,0 +1,16 @@
+Port 8080
+ErrorLog /dev/stderr
+AccessLog /dev/stderr
+DocumentRoot ../../www
+DirectoryMaker ../../usr/lib/boa/boa_indexer
+KeepAliveMax 1000
+KeepAliveTimeout 10
+MimeTypes ../mime.types
+DefaultType text/plain
+CGIPath /bin:/usr/bin:/usr/local/bin:../../bin:../../usr/bin:../../usr/local/bin
+
+AddType application/x-httpd-cgi cgi
+AddType application/x-httpd-cgi sh
+
+ScriptAlias /cgi-bin/ ../../www/cgi-bin
+PluginRoot ../../usr/lib/boa
diff --git a/libs/sgi-webuci/root/etc/mime.types b/libs/sgi-webuci/root/etc/mime.types
new file mode 100644 (file)
index 0000000..ee11c1b
--- /dev/null
@@ -0,0 +1,748 @@
+###############################################################################
+#
+#  MIME-TYPES and the extensions that represent them
+#
+#  This file is part of the "mime-support" package.  Please send email (not a
+#  bug report) to mime-support@packages.debian.org if you would like new types
+#  and/or extensions to be added.
+#
+#  The reason that all types are managed by the mime-support package instead
+#  allowing individual packages to install types in much the same way as they
+#  add entries in to the mailcap file is so these types can be referenced by
+#  other programs (such as a web server) even if the specific support package
+#  for that type is not installed.
+#
+#  Users can add their own types if they wish by creating a ".mime.types"
+#  file in their home directory.  Definitions included there will take
+#  precedence over those listed here.
+#
+#  Note: Compression schemes like "gzip", "bzip", and "compress" are not
+#  actually "mime-types".  They are "encodings" and hence must _not_ have
+#  entries in this file to map their extensions.  The "mime-type" of an
+#  encoded file refers to the type of data that has been encoded, not the
+#  type of encoding.
+#
+###############################################################################
+
+
+application/activemessage
+application/andrew-inset                       ez
+application/applefile
+application/atom                               atom
+application/atomcat+xml                                atomcat
+application/atomserv+xml                       atomsrv
+application/atomicmail
+application/batch-SMTP
+application/beep+xml
+application/cals-1840
+application/cap                                        cap pcap
+application/commonground
+application/cu-seeme                           cu
+application/cybercash
+application/dca-rft
+application/dec-dx
+application/docbook+xml
+application/dsptype                            tsp
+application/dvcs
+application/edi-consent
+application/edi-x12
+application/edifact
+application/eshop
+application/font-tdpfr
+application/futuresplash                       spl
+application/ghostview
+application/hta                                        hta
+application/http
+application/hyperstudio
+application/iges
+application/index
+application/index.cmd
+application/index.obj
+application/index.response
+application/index.vnd
+application/iotp
+application/ipp
+application/isup
+application/java-archive                       jar
+application/java-serialized-object             ser
+application/java-vm                            class
+application/mac-binhex40                       hqx
+application/mac-compactpro                     cpt
+application/macwriteii
+application/marc
+application/mathematica                                nb
+application/mathematica-old
+application/ms-tnef
+application/msaccess                           mdb
+application/msword                             doc dot
+application/news-message-id
+application/news-transmission
+application/ocsp-request
+application/ocsp-response
+application/octet-stream                       bin
+application/oda                                        oda
+application/ogg                                        ogg
+application/parityfec
+application/pdf                                        pdf
+application/pgp-encrypted
+application/pgp-keys                           key
+application/pgp-signature                      pgp
+application/pics-rules                         prf
+application/pkcs10
+application/pkcs7-mime
+application/pkcs7-signature
+application/pkix-cert
+application/pkix-crl
+application/pkixcmp
+application/postscript                         ps ai eps
+application/prs.alvestrand.titrax-sheet
+application/prs.cww
+application/prs.nprend
+application/qsig
+application/rar                                        rar
+application/rdf+xml                            rdf
+application/remote-printing
+application/riscos
+application/rss+xml                            rss
+application/rtf                                        rtf
+application/sdp
+application/set-payment
+application/set-payment-initiation
+application/set-registration
+application/set-registration-initiation
+application/sgml
+application/sgml-open-catalog
+application/sieve
+application/slate
+application/smil                               smi smil
+application/timestamp-query
+application/timestamp-reply
+application/vemmi
+application/whoispp-query
+application/whoispp-response
+application/wita
+application/wordperfect                                wpd
+application/wordperfect5.1                     wp5
+application/x400-bp
+application/xhtml+xml                          xhtml xht
+application/xml                                        xml xsl
+application/xml-dtd
+application/xml-external-parsed-entity
+application/zip                                        zip
+application/vnd.3M.Post-it-Notes
+application/vnd.accpac.simply.aso
+application/vnd.accpac.simply.imp
+application/vnd.acucobol
+application/vnd.aether.imp
+application/vnd.anser-web-certificate-issue-initiation
+application/vnd.anser-web-funds-transfer-initiation
+application/vnd.audiograph
+application/vnd.bmi
+application/vnd.businessobjects
+application/vnd.canon-cpdl
+application/vnd.canon-lips
+application/vnd.cinderella                     cdy
+application/vnd.claymore
+application/vnd.commerce-battelle
+application/vnd.commonspace
+application/vnd.comsocaller
+application/vnd.contact.cmsg
+application/vnd.cosmocaller
+application/vnd.ctc-posml
+application/vnd.cups-postscript
+application/vnd.cups-raster
+application/vnd.cups-raw
+application/vnd.cybank
+application/vnd.dna
+application/vnd.dpgraph
+application/vnd.dxr
+application/vnd.ecdis-update
+application/vnd.ecowin.chart
+application/vnd.ecowin.filerequest
+application/vnd.ecowin.fileupdate
+application/vnd.ecowin.series
+application/vnd.ecowin.seriesrequest
+application/vnd.ecowin.seriesupdate
+application/vnd.enliven
+application/vnd.epson.esf
+application/vnd.epson.msf
+application/vnd.epson.quickanime
+application/vnd.epson.salt
+application/vnd.epson.ssf
+application/vnd.ericsson.quickcall
+application/vnd.eudora.data
+application/vnd.fdf
+application/vnd.ffsns
+application/vnd.flographit
+application/vnd.framemaker
+application/vnd.fsc.weblaunch
+application/vnd.fujitsu.oasys
+application/vnd.fujitsu.oasys2
+application/vnd.fujitsu.oasys3
+application/vnd.fujitsu.oasysgp
+application/vnd.fujitsu.oasysprs
+application/vnd.fujixerox.ddd
+application/vnd.fujixerox.docuworks
+application/vnd.fujixerox.docuworks.binder
+application/vnd.fut-misnet
+application/vnd.google-earth.kml+xml           kml
+application/vnd.google-earth.kmz               kmz
+application/vnd.grafeq
+application/vnd.groove-account
+application/vnd.groove-identity-message
+application/vnd.groove-injector
+application/vnd.groove-tool-message
+application/vnd.groove-tool-template
+application/vnd.groove-vcard
+application/vnd.hhe.lesson-player
+application/vnd.hp-HPGL
+application/vnd.hp-PCL
+application/vnd.hp-PCLXL
+application/vnd.hp-hpid
+application/vnd.hp-hps
+application/vnd.httphone
+application/vnd.hzn-3d-crossword
+application/vnd.ibm.MiniPay
+application/vnd.ibm.afplinedata
+application/vnd.ibm.modcap
+application/vnd.informix-visionary
+application/vnd.intercon.formnet
+application/vnd.intertrust.digibox
+application/vnd.intertrust.nncp
+application/vnd.intu.qbo
+application/vnd.intu.qfx
+application/vnd.irepository.package+xml
+application/vnd.is-xpr
+application/vnd.japannet-directory-service
+application/vnd.japannet-jpnstore-wakeup
+application/vnd.japannet-payment-wakeup
+application/vnd.japannet-registration
+application/vnd.japannet-registration-wakeup
+application/vnd.japannet-setstore-wakeup
+application/vnd.japannet-verification
+application/vnd.japannet-verification-wakeup
+application/vnd.koan
+application/vnd.lotus-1-2-3
+application/vnd.lotus-approach
+application/vnd.lotus-freelance
+application/vnd.lotus-notes
+application/vnd.lotus-organizer
+application/vnd.lotus-screencam
+application/vnd.lotus-wordpro
+application/vnd.mcd
+application/vnd.mediastation.cdkey
+application/vnd.meridian-slingshot
+application/vnd.mif
+application/vnd.minisoft-hp3000-save
+application/vnd.mitsubishi.misty-guard.trustweb
+application/vnd.mobius.daf
+application/vnd.mobius.dis
+application/vnd.mobius.msl
+application/vnd.mobius.plc
+application/vnd.mobius.txf
+application/vnd.motorola.flexsuite
+application/vnd.motorola.flexsuite.adsi
+application/vnd.motorola.flexsuite.fis
+application/vnd.motorola.flexsuite.gotap
+application/vnd.motorola.flexsuite.kmr
+application/vnd.motorola.flexsuite.ttc
+application/vnd.motorola.flexsuite.wem
+application/vnd.mozilla.xul+xml                        xul
+application/vnd.ms-artgalry
+application/vnd.ms-asf
+application/vnd.ms-excel                       xls xlb xlt
+application/vnd.ms-lrm
+application/vnd.ms-pki.seccat                  cat
+application/vnd.ms-pki.stl                     stl
+application/vnd.ms-powerpoint                  ppt pps
+application/vnd.ms-project
+application/vnd.ms-tnef
+application/vnd.ms-works
+application/vnd.mseq
+application/vnd.msign
+application/vnd.music-niff
+application/vnd.musician
+application/vnd.netfpx
+application/vnd.noblenet-directory
+application/vnd.noblenet-sealer
+application/vnd.noblenet-web
+application/vnd.novadigm.EDM
+application/vnd.novadigm.EDX
+application/vnd.novadigm.EXT
+application/vnd.oasis.opendocument.chart                       odc
+application/vnd.oasis.opendocument.database                    odb
+application/vnd.oasis.opendocument.formula                     odf
+application/vnd.oasis.opendocument.graphics                    odg
+application/vnd.oasis.opendocument.graphics-template           otg
+application/vnd.oasis.opendocument.image                       odi
+application/vnd.oasis.opendocument.presentation                        odp
+application/vnd.oasis.opendocument.presentation-template       otp
+application/vnd.oasis.opendocument.spreadsheet                 ods
+application/vnd.oasis.opendocument.spreadsheet-template                ots
+application/vnd.oasis.opendocument.text                                odt
+application/vnd.oasis.opendocument.text-master                 odm
+application/vnd.oasis.opendocument.text-template               ott
+application/vnd.oasis.opendocument.text-web                    oth
+application/vnd.osa.netdeploy
+application/vnd.palm
+application/vnd.pg.format
+application/vnd.pg.osasli
+application/vnd.powerbuilder6
+application/vnd.powerbuilder6-s
+application/vnd.powerbuilder7
+application/vnd.powerbuilder7-s
+application/vnd.powerbuilder75
+application/vnd.powerbuilder75-s
+application/vnd.previewsystems.box
+application/vnd.publishare-delta-tree
+application/vnd.pvi.ptid1
+application/vnd.pwg-xhtml-print+xml
+application/vnd.rapid
+application/vnd.rim.cod                                cod
+application/vnd.s3sms
+application/vnd.seemail
+application/vnd.shana.informed.formdata
+application/vnd.shana.informed.formtemplate
+application/vnd.shana.informed.interchange
+application/vnd.shana.informed.package
+application/vnd.smaf                           mmf
+application/vnd.sss-cod
+application/vnd.sss-dtf
+application/vnd.sss-ntf
+application/vnd.stardivision.calc              sdc
+application/vnd.stardivision.chart             sds
+application/vnd.stardivision.draw              sda
+application/vnd.stardivision.impress           sdd
+application/vnd.stardivision.math              sdf
+application/vnd.stardivision.writer            sdw
+application/vnd.stardivision.writer-global     sgl
+application/vnd.street-stream
+application/vnd.sun.xml.calc                   sxc
+application/vnd.sun.xml.calc.template          stc
+application/vnd.sun.xml.draw                   sxd
+application/vnd.sun.xml.draw.template          std
+application/vnd.sun.xml.impress                        sxi
+application/vnd.sun.xml.impress.template       sti
+application/vnd.sun.xml.math                   sxm
+application/vnd.sun.xml.writer                 sxw
+application/vnd.sun.xml.writer.global          sxg
+application/vnd.sun.xml.writer.template                stw
+application/vnd.svd
+application/vnd.swiftview-ics
+application/vnd.symbian.install                        sis
+application/vnd.triscape.mxs
+application/vnd.trueapp
+application/vnd.truedoc
+application/vnd.tve-trigger
+application/vnd.ufdl
+application/vnd.uplanet.alert
+application/vnd.uplanet.alert-wbxml
+application/vnd.uplanet.bearer-choice
+application/vnd.uplanet.bearer-choice-wbxml
+application/vnd.uplanet.cacheop
+application/vnd.uplanet.cacheop-wbxml
+application/vnd.uplanet.channel
+application/vnd.uplanet.channel-wbxml
+application/vnd.uplanet.list
+application/vnd.uplanet.list-wbxml
+application/vnd.uplanet.listcmd
+application/vnd.uplanet.listcmd-wbxml
+application/vnd.uplanet.signal
+application/vnd.vcx
+application/vnd.vectorworks
+application/vnd.vidsoft.vidconference
+application/vnd.visio                          vsd
+application/vnd.vividence.scriptfile
+application/vnd.wap.sic
+application/vnd.wap.slc
+application/vnd.wap.wbxml                      wbxml
+application/vnd.wap.wmlc                       wmlc
+application/vnd.wap.wmlscriptc                 wmlsc
+application/vnd.webturbo
+application/vnd.wrq-hp3000-labelled
+application/vnd.wt.stf
+application/vnd.xara
+application/vnd.xfdl
+application/vnd.yellowriver-custom-menu
+application/x-123                              wk
+application/x-7z-compressed                    7z
+application/x-abiword                          abw
+application/x-apple-diskimage                  dmg
+application/x-bcpio                            bcpio
+application/x-bittorrent                       torrent
+application/x-cab                              cab
+application/x-cbr                              cbr
+application/x-cbz                              cbz
+application/x-cdf                              cdf
+application/x-cdlink                           vcd
+application/x-chess-pgn                                pgn
+application/x-core
+application/x-cpio                             cpio
+application/x-csh                              csh
+application/x-debian-package                   deb udeb
+application/x-director                         dcr dir dxr
+application/x-dms                              dms
+application/x-doom                             wad
+application/x-dvi                              dvi
+application/x-httpd-eruby                      rhtml
+application/x-executable
+application/x-flac                             flac
+application/x-font                             pfa pfb gsf pcf pcf.Z
+application/x-freemind                         mm
+application/x-futuresplash                     spl
+application/x-gnumeric                         gnumeric
+application/x-go-sgf                           sgf
+application/x-graphing-calculator              gcf
+application/x-gtar                             gtar tgz taz
+application/x-hdf                              hdf
+application/x-httpd-php                                phtml pht php
+application/x-httpd-php-source                 phps
+application/x-httpd-php3                       php3
+application/x-httpd-php3-preprocessed          php3p
+application/x-httpd-php4                       php4
+application/x-ica                              ica
+application/x-internet-signup                  ins isp
+application/x-iphone                           iii
+application/x-iso9660-image                    iso
+application/x-java-applet
+application/x-java-bean
+application/x-java-jnlp-file                   jnlp
+application/x-javascript                       js
+application/x-jmol                             jmz
+application/x-kchart                           chrt
+application/x-kdelnk
+application/x-killustrator                     kil
+application/x-koan                             skp skd skt skm
+application/x-kpresenter                       kpr kpt
+application/x-kspread                          ksp
+application/x-kword                            kwd kwt
+application/x-latex                            latex
+application/x-lha                              lha
+application/x-lyx                              lyx
+application/x-lzh                              lzh
+application/x-lzx                              lzx
+application/x-maker                            frm maker frame fm fb book fbdoc
+application/x-mif                              mif
+application/x-ms-wmd                           wmd
+application/x-ms-wmz                           wmz
+application/x-msdos-program                    com exe bat dll
+application/x-msi                              msi
+application/x-netcdf                           nc
+application/x-ns-proxy-autoconfig              pac
+application/x-nwc                              nwc
+application/x-object                           o
+application/x-oz-application                   oza
+application/x-pkcs7-certreqresp                        p7r
+application/x-pkcs7-crl                                crl
+application/x-python-code                      pyc pyo
+application/x-quicktimeplayer                  qtl
+application/x-redhat-package-manager           rpm
+application/x-rx
+application/x-sh                               sh
+application/x-shar                             shar
+application/x-shellscript
+application/x-shockwave-flash                  swf swfl
+application/x-stuffit                          sit sitx
+application/x-sv4cpio                          sv4cpio
+application/x-sv4crc                           sv4crc
+application/x-tar                              tar
+application/x-tcl                              tcl
+application/x-tex-gf                           gf
+application/x-tex-pk                           pk
+application/x-texinfo                          texinfo texi
+application/x-trash                            ~ % bak old sik
+application/x-troff                            t tr roff
+application/x-troff-man                                man
+application/x-troff-me                         me
+application/x-troff-ms                         ms
+application/x-ustar                            ustar
+application/x-videolan
+application/x-wais-source                      src
+application/x-wingz                            wz
+application/x-x509-ca-cert                     crt
+application/x-xcf                              xcf
+application/x-xfig                             fig
+application/x-xpinstall                                xpi
+
+audio/32kadpcm
+audio/3gpp
+audio/basic                                    au snd
+audio/g.722.1
+audio/l16
+audio/midi                                     mid midi kar
+audio/mp4a-latm
+audio/mpa-robust
+audio/mpeg                                     mpga mpega mp2 mp3 m4a
+audio/mpegurl                                  m3u
+audio/parityfec
+audio/prs.sid                                  sid
+audio/telephone-event
+audio/tone
+audio/vnd.cisco.nse
+audio/vnd.cns.anp1
+audio/vnd.cns.inf1
+audio/vnd.digital-winds
+audio/vnd.everad.plj
+audio/vnd.lucent.voice
+audio/vnd.nortel.vbk
+audio/vnd.nuera.ecelp4800
+audio/vnd.nuera.ecelp7470
+audio/vnd.nuera.ecelp9600
+audio/vnd.octel.sbc
+audio/vnd.qcelp
+audio/vnd.rhetorex.32kadpcm
+audio/vnd.vmx.cvsd
+audio/x-aiff                                   aif aiff aifc
+audio/x-gsm                                    gsm
+audio/x-mpegurl                                        m3u
+audio/x-ms-wma                                 wma
+audio/x-ms-wax                                 wax
+audio/x-pn-realaudio-plugin
+audio/x-pn-realaudio                           ra rm ram
+audio/x-realaudio                              ra
+audio/x-scpls                                  pls
+audio/x-sd2                                    sd2
+audio/x-wav                                    wav
+
+chemical/x-alchemy                             alc
+chemical/x-cache                               cac cache
+chemical/x-cache-csf                           csf
+chemical/x-cactvs-binary                       cbin cascii ctab
+chemical/x-cdx                                 cdx
+chemical/x-cerius                              cer
+chemical/x-chem3d                              c3d
+chemical/x-chemdraw                            chm
+chemical/x-cif                                 cif
+chemical/x-cmdf                                        cmdf
+chemical/x-cml                                 cml
+chemical/x-compass                             cpa
+chemical/x-crossfire                           bsd
+chemical/x-csml                                        csml csm
+chemical/x-ctx                                 ctx
+chemical/x-cxf                                 cxf cef
+#chemical/x-daylight-smiles                    smi
+chemical/x-embl-dl-nucleotide                  emb embl
+chemical/x-galactic-spc                                spc
+chemical/x-gamess-input                                inp gam gamin
+chemical/x-gaussian-checkpoint                 fch fchk
+chemical/x-gaussian-cube                       cub
+chemical/x-gaussian-input                      gau gjc gjf
+chemical/x-gaussian-log                                gal
+chemical/x-gcg8-sequence                       gcg
+chemical/x-genbank                             gen
+chemical/x-hin                                 hin
+chemical/x-isostar                             istr ist
+chemical/x-jcamp-dx                            jdx dx
+chemical/x-kinemage                            kin
+chemical/x-macmolecule                         mcm
+chemical/x-macromodel-input                    mmd mmod
+chemical/x-mdl-molfile                         mol
+chemical/x-mdl-rdfile                          rd
+chemical/x-mdl-rxnfile                         rxn
+chemical/x-mdl-sdfile                          sd sdf
+chemical/x-mdl-tgf                             tgf
+#chemical/x-mif                                        mif
+chemical/x-mmcif                               mcif
+chemical/x-mol2                                        mol2
+chemical/x-molconn-Z                           b
+chemical/x-mopac-graph                         gpt
+chemical/x-mopac-input                         mop mopcrt mpc dat zmt
+chemical/x-mopac-out                           moo
+chemical/x-mopac-vib                           mvb
+chemical/x-ncbi-asn1                           asn
+chemical/x-ncbi-asn1-ascii                     prt ent
+chemical/x-ncbi-asn1-binary                    val aso
+chemical/x-ncbi-asn1-spec                      asn
+chemical/x-pdb                                 pdb ent
+chemical/x-rosdal                              ros
+chemical/x-swissprot                           sw
+chemical/x-vamas-iso14976                      vms
+chemical/x-vmd                                 vmd
+chemical/x-xtel                                        xtel
+chemical/x-xyz                                 xyz
+
+image/cgm
+image/g3fax
+image/gif                                      gif
+image/ief                                      ief
+image/jpeg                                     jpeg jpg jpe
+image/naplps
+image/pcx                                      pcx
+image/png                                      png
+image/prs.btif
+image/prs.pti
+image/svg+xml                                  svg svgz
+image/tiff                                     tiff tif
+image/vnd.cns.inf2
+image/vnd.djvu                                 djvu djv
+image/vnd.dwg
+image/vnd.dxf
+image/vnd.fastbidsheet
+image/vnd.fpx
+image/vnd.fst
+image/vnd.fujixerox.edmics-mmr
+image/vnd.fujixerox.edmics-rlc
+image/vnd.mix
+image/vnd.net-fpx
+image/vnd.svf
+image/vnd.wap.wbmp                             wbmp
+image/vnd.xiff
+image/x-cmu-raster                             ras
+image/x-coreldraw                              cdr
+image/x-coreldrawpattern                       pat
+image/x-coreldrawtemplate                      cdt
+image/x-corelphotopaint                                cpt
+image/x-icon                                   ico
+image/x-jg                                     art
+image/x-jng                                    jng
+image/x-ms-bmp                                 bmp
+image/x-photoshop                              psd
+image/x-portable-anymap                                pnm
+image/x-portable-bitmap                                pbm
+image/x-portable-graymap                       pgm
+image/x-portable-pixmap                                ppm
+image/x-rgb                                    rgb
+image/x-xbitmap                                        xbm
+image/x-xpixmap                                        xpm
+image/x-xwindowdump                            xwd
+
+inode/chardevice
+inode/blockdevice
+inode/directory-locked
+inode/directory
+inode/fifo
+inode/socket
+
+message/delivery-status
+message/disposition-notification
+message/external-body
+message/http
+message/s-http
+message/news
+message/partial
+message/rfc822                                 eml
+
+model/iges                                     igs iges
+model/mesh                                     msh mesh silo
+model/vnd.dwf
+model/vnd.flatland.3dml
+model/vnd.gdl
+model/vnd.gs-gdl
+model/vnd.gtw
+model/vnd.mts
+model/vnd.vtu
+model/vrml                                     wrl vrml
+
+multipart/alternative
+multipart/appledouble
+multipart/byteranges
+multipart/digest
+multipart/encrypted
+multipart/form-data
+multipart/header-set
+multipart/mixed
+multipart/parallel
+multipart/related
+multipart/report
+multipart/signed
+multipart/voice-message
+
+text/calendar                                  ics icz
+text/css                                       css
+text/csv                                       csv
+text/directory
+text/english
+text/enriched
+text/h323                                      323
+text/html                                      html htm shtml
+text/iuls                                      uls
+text/mathml                                    mml
+text/parityfec
+text/plain                                     asc txt text pot
+text/prs.lines.tag
+text/rfc822-headers
+text/richtext                                  rtx
+text/rtf
+text/scriptlet                                 sct wsc
+text/t140
+text/texmacs                                   tm ts
+text/tab-separated-values                      tsv
+text/uri-list
+text/vnd.abc
+text/vnd.curl
+text/vnd.DMClientScript
+text/vnd.flatland.3dml
+text/vnd.fly
+text/vnd.fmi.flexstor
+text/vnd.in3d.3dml
+text/vnd.in3d.spot
+text/vnd.IPTC.NewsML
+text/vnd.IPTC.NITF
+text/vnd.latex-z
+text/vnd.motorola.reflex
+text/vnd.ms-mediapackage
+text/vnd.sun.j2me.app-descriptor               jad
+text/vnd.wap.si
+text/vnd.wap.sl
+text/vnd.wap.wml                               wml
+text/vnd.wap.wmlscript                         wmls
+text/x-bibtex                                  bib
+text/x-boo                                     boo
+text/x-c++hdr                                  h++ hpp hxx hh
+text/x-c++src                                  c++ cpp cxx cc
+text/x-chdr                                    h
+text/x-component                               htc
+text/x-crontab
+text/x-csh                                     csh
+text/x-csrc                                    c
+text/x-dsrc                                    d
+text/x-diff                                    diff patch
+text/x-haskell                                 hs
+text/x-java                                    java
+text/x-literate-haskell                                lhs
+text/x-makefile
+text/x-moc                                     moc
+text/x-pascal                                  p pas
+text/x-pcs-gcd                                 gcd
+text/x-perl                                    pl pm
+text/x-python                                  py
+text/x-server-parsed-html
+text/x-setext                                  etx
+text/x-sh                                      sh
+text/x-tcl                                     tcl tk
+text/x-tex                                     tex ltx sty cls
+text/x-vcalendar                               vcs
+text/x-vcard                                   vcf
+
+video/3gpp                                     3gp
+video/dl                                       dl
+video/dv                                       dif dv
+video/fli                                      fli
+video/gl                                       gl
+video/mpeg                                     mpeg mpg mpe
+video/mp4                                      mp4
+video/quicktime                                        qt mov
+video/mp4v-es
+video/parityfec
+video/pointer
+video/vnd.fvt
+video/vnd.motorola.video
+video/vnd.motorola.videop
+video/vnd.mpegurl                              mxu
+video/vnd.mts
+video/vnd.nokia.interleaved-multimedia
+video/vnd.vivo
+video/x-la-asf                                 lsf lsx
+video/x-mng                                    mng
+video/x-ms-asf                                 asf asx
+video/x-ms-wm                                  wm
+video/x-ms-wmv                                 wmv
+video/x-ms-wmx                                 wmx
+video/x-ms-wvx                                 wvx
+video/x-msvideo                                        avi
+video/x-sgi-movie                              movie
+
+x-conference/x-cooltalk                                ice
+
+x-epoc/x-sisx-app                              sisx
+x-world/x-vrml                                 vrm vrml wrl
diff --git a/libs/sgi-webuci/root/lib/webuci/main.lua b/libs/sgi-webuci/root/lib/webuci/main.lua
deleted file mode 100644 (file)
index cb2730d..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-module("webuci", package.seeall)
-
-function prepare_req(uri)
-       require("luci.dispatcher").createindex()
-       env = {}
-       env.REQUEST_URI = uri
-end
-
-function handle_req(context)
-       env.SERVER_PROTOCOL = context.server_proto
-       env.REMOTE_ADDR     = context.remote_addr
-       env.REQUEST_METHOD  = context.request_method
-       env.PATH_INFO       = context.uri
-       env.REMOTE_PORT     = context.remote_port
-       env.SERVER_ADDR     = context.server_addr
-       env.SCRIPT_NAME     = env.REQUEST_URI:sub(1, #env.REQUEST_URI - #env.PATH_INFO)
-       
-       luci.sgi.webuci.initenv(env)
-       luci.dispatcher.httpdispatch()
-end
\ No newline at end of file
diff --git a/libs/sgi-webuci/root/usr/lib/boa/luci.lua b/libs/sgi-webuci/root/usr/lib/boa/luci.lua
new file mode 100644 (file)
index 0000000..2ea6ba4
--- /dev/null
@@ -0,0 +1,61 @@
+module("luci-plugin", package.seeall)
+
+function normalize(path)
+    local newpath
+       while newpath ~= path do
+               if (newpath) then
+                       path = newpath
+               end
+               newpath = string.gsub(path, "/[^/]+/../", "/")
+       end
+       return newpath
+end
+
+function init(path)
+       -- NB: path points to ROOT/usr/lib/boa, change it to /usr/lib/lua
+       root = normalize(path .. '/../../../')
+       path = normalize(path .. '/../lua/')
+       package.cpath = path..'?.so;'..package.cpath
+       package.path = path..'?.lua;'..package.path
+
+       require("luci.dispatcher")
+       require("luci.sgi.webuci")
+       require("uci")
+
+       if (root ~= '/') then
+               -- Entering dummy mode
+               uci.set_savedir(root..'/tmp/.uci')
+               uci.set_confdir(root..'/etc/config')
+               
+               luci.sys.hostname = function() return "" end
+               luci.sys.loadavg  = function() return 0,0,0,0,0 end
+               luci.sys.reboot   = function() return end
+               luci.sys.sysinfo  = function() return "","","" end
+               luci.sys.syslog   = function() return "" end
+               
+               luci.sys.net.arptable           = function() return {} end
+               luci.sys.net.devices            = function() return {} end
+               luci.sys.net.routes                     = function() return {} end
+               luci.sys.wifi.getiwconfig       = function() return {} end
+               luci.sys.wifi.iwscan            = function() return {} end
+       end
+end
+
+function prepare_req(uri)
+       luci.dispatcher.createindex()
+       env = {}
+       env.REQUEST_URI = uri
+end
+
+function handle_req(context)
+       env.SERVER_PROTOCOL = context.server_proto
+       env.REMOTE_ADDR     = context.remote_addr
+       env.REQUEST_METHOD  = context.request_method
+       env.PATH_INFO       = context.uri
+       env.REMOTE_PORT     = context.remote_port
+       env.SERVER_ADDR     = context.server_addr
+       env.SCRIPT_NAME     = env.REQUEST_URI:sub(1, #env.REQUEST_URI - #env.PATH_INFO)
+
+       luci.sgi.webuci.initenv(env, vars)
+       luci.dispatcher.httpdispatch()
+end
diff --git a/libs/sgi-webuci/src/cgi.c b/libs/sgi-webuci/src/cgi.c
new file mode 100644 (file)
index 0000000..f8bf404
--- /dev/null
@@ -0,0 +1,530 @@
+/*
+ * CGI routines for luci
+ * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/* 
+ * Based on code from cgilib:
+ * 
+ *   cgi.c - Some simple routines for CGI programming
+ *   Copyright (c) 1996-9,2007,8  Martin Schulze <joey@infodrom.org>
+ *
+ *   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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#define _GNU_SOURCE 1
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdbool.h>
+#include <strings.h>
+#include <ctype.h>
+#include <lauxlib.h>
+
+#define BUFSIZE 128
+
+static char *
+cgiGetLine (FILE *stream)
+{
+       static char *line = NULL;
+       static size_t size = 0;
+       char buf[BUFSIZE];
+       char *cp;
+
+       if (!line) {
+               if ((line = (char *)malloc (BUFSIZE)) == NULL)
+                       return NULL;
+               size = BUFSIZE;
+       }
+       line[0] = '\0';
+
+       while (!feof (stream)) {
+               if ((cp = fgets (buf, sizeof (buf), stream)) == NULL)
+                       return NULL;
+
+               if (strlen(line)+strlen(buf)+1 > size) {
+                       if ((cp = (char *)realloc (line, size + BUFSIZE)) == NULL)
+                               return line;
+                       size += BUFSIZE;
+                       line = cp;
+               }
+
+               strcat (line, buf);
+               if (line[strlen(line)-1] == '\n') {
+                       line[strlen(line)-1] = '\0';
+                       if (line[strlen(line)-1] == '\r')
+                               line[strlen(line)-1] = '\0';
+                       return line;
+               }
+       }
+
+       return NULL;
+}
+
+
+static const char *
+luci_getenv(lua_State *L, const char *name)
+{
+       const char *ret;
+
+       lua_getfield(L, lua_upvalueindex(2), name);
+       ret = lua_tostring(L, -1);
+       lua_pop(L, 1);
+       return ret;
+}
+
+static void
+luci_setvar(lua_State *L, const char *name, const char *value, bool append)
+{
+       /* Check if there is an existing value already */
+       lua_getfield(L, lua_upvalueindex(1), name);
+       if (lua_isnil(L, -1)) {
+               /* nope, we're safe - add a new one */
+               lua_pushstring(L, value);
+               lua_setfield(L, lua_upvalueindex(1), name);
+       } else if (lua_istable(L, -1) && append) {
+               /* it's a table already, but appending is requested
+                * take the last element and append the new string to it */
+               int tlast = lua_objlen(L, -1);
+               lua_rawgeti(L, -1, tlast);
+               lua_pushstring(L, value);
+               lua_pushstring(L, "\n");
+               lua_concat(L, 3);
+               lua_rawseti(L, -2, tlast);
+       } else if (lua_istable(L, -1)) {
+               /* it's a table, which means we already have two
+                * or more entries, add the next one */
+
+               int tnext = lua_objlen(L, -1) + 1; /* next entry */
+
+               lua_pushstring(L, value);
+               luaL_setn(L, -2, tnext);
+               lua_rawseti(L, -2, tnext);
+       } else if (lua_isstring(L, -1) && append) {
+               /* append the new string to the existing variable */
+               lua_pushstring(L, value);
+               lua_pushstring(L, "\n");
+               lua_concat(L, 3);
+               lua_setfield(L, lua_upvalueindex(1), name);
+       } else if (lua_isstring(L, -1)) {
+               /* we're trying to add a variable that already has
+                * a string value. convert the string value to a
+                * table and add our new value to the table as well
+                */
+               lua_createtable(L, 2, 0);
+               lua_pushvalue(L, -2); /* copy of the initial string value */
+               lua_rawseti(L, -2, 1);
+
+               lua_pushstring(L, value);
+               lua_rawseti(L, -2, 2);
+               lua_setfield(L, lua_upvalueindex(1), name);
+       } else {
+               luaL_error(L, "Invalid table entry type for index '%s'", name);
+       }
+}
+
+char *cgiDecodeString (char *text)
+{
+       char *cp, *xp;
+
+       for (cp=text,xp=text; *cp; cp++) {
+               if (*cp == '%') {
+                       if (strchr("0123456789ABCDEFabcdef", *(cp+1))
+                               && strchr("0123456789ABCDEFabcdef", *(cp+2))) {
+                               if (islower(*(cp+1)))
+                                       *(cp+1) = toupper(*(cp+1));
+                               if (islower(*(cp+2)))
+                                       *(cp+2) = toupper(*(cp+2));
+                               *(xp) = (*(cp+1) >= 'A' ? *(cp+1) - 'A' + 10 : *(cp+1) - '0' ) * 16
+                                       + (*(cp+2) >= 'A' ? *(cp+2) - 'A' + 10 : *(cp+2) - '0');
+                               xp++;cp+=2;
+                       }
+               } else {
+                       *(xp++) = *cp;
+               }
+       }
+       memset(xp, 0, cp-xp);
+       return text;
+}
+
+#if 0
+/* cgiReadFile()
+ *
+ * Read and save a file fro a multipart request
+ */
+#include <errno.h>
+char *cgiReadFile (FILE *stream, char *boundary)
+{
+       char *crlfboundary, *buf;
+       size_t boundarylen;
+       int c;
+       unsigned int pivot;
+       char *cp;
+       char template[]= "/tmp/cgilibXXXXXX";
+       FILE *tmpfile;
+       int fd;
+
+       boundarylen = strlen(boundary)+3;
+       if ((crlfboundary = (char *)malloc (boundarylen)) == NULL)
+               return NULL;
+       sprintf (crlfboundary, "\r\n%s", boundary);
+
+       if ((buf = (char *)malloc (boundarylen)) == NULL) {
+               free (crlfboundary);
+               return NULL;
+       }
+       memset (buf, 0, boundarylen);
+       pivot = 0;
+
+       if ((fd = mkstemp (template)) == -1) {
+               free (crlfboundary);
+               free (buf);
+               return NULL;
+       }
+
+       if ((tmpfile = fdopen (fd, "w")) == NULL) {
+               free (crlfboundary);
+               free (buf);
+               unlink (template);
+               return NULL;
+       }
+       
+       while (!feof (stream)) {
+               c = fgetc (stream);
+
+               if (c == 0) {
+                       if (strlen (buf)) {
+                               for (cp=buf; *cp; cp++)
+                                       putc (*cp, tmpfile);
+                               memset (buf, 0, boundarylen);
+                               pivot = 0;
+                       }
+                       putc (c, tmpfile);
+                       continue;
+               }
+
+               if (strlen (buf)) {
+                       if (crlfboundary[pivot+1] == c) {
+                               buf[++pivot] = c;
+
+                               if (strlen (buf) == strlen (crlfboundary))
+                                       break;
+                               else
+                                       continue;
+                       } else {
+                               for (cp=buf; *cp; cp++)
+                                       putc (*cp, tmpfile);
+                               memset (buf, 0, boundarylen);
+                               pivot = 0;
+                       }
+               }
+
+               if (crlfboundary[0] == c) {
+                       buf[0] = c;
+               } else {
+                       fputc (c, tmpfile);
+               }
+       }
+
+       if (!feof (stream))
+               fgets (buf, boundarylen, stream);
+
+       fclose (tmpfile);
+
+       free (crlfboundary);
+       free (buf);
+
+       return strdup (template);
+}
+#endif
+
+/*
+ * Decode multipart/form-data
+ */
+#define MULTIPART_DELTA 5
+void luci_parse_multipart (lua_State *L, char *boundary)
+{
+       char *line;
+       char *cp, *xp;
+       char *name = NULL, *type = NULL;
+       char *fname = NULL;
+       int header = 1;
+       bool append = false;
+
+       while ((line = cgiGetLine (stdin)) != NULL) {
+               if (!strncmp (line, boundary, strlen(boundary))) {
+                       header = 1;
+                       if (name)
+                               free(name);
+                       if (type)
+                               free(type);
+                       name = NULL;
+                       type = NULL;
+                       append = false;
+               } else if (header && !name && !strncasecmp (line, "Content-Disposition: form-data; ", 32)) {
+                       if ((cp = strstr (line, "name=\"")) == NULL)
+                               continue;
+                       cp += 6;
+                       if ((xp = strchr (cp, '\"')) == NULL)
+                               continue;
+                       name = malloc(xp-cp + 1);
+                       strncpy(name, cp, xp-cp);
+                       name[xp-cp] = 0;
+                       cgiDecodeString (name);
+
+                       if ((cp = strstr (line, "filename=\"")) == NULL)
+                               continue;
+                       cp += 10;
+                       if ((xp = strchr (cp, '\"')) == NULL)
+                               continue;
+                       fname = malloc(xp-cp + 1);
+                       strncpy(fname, cp, xp-cp);
+                       fname[xp-cp] = 0;
+                       cgiDecodeString (fname);
+               } else if (header && !type && !strncasecmp (line, "Content-Type: ", 14)) {
+                       cp = line + 14;
+                       type = strdup (cp);
+               } else if (header) {
+                       if (!strlen(line)) {
+                               header = 0;
+
+                               if (fname) {
+#if 0
+                                       header = 1;
+                                       tmpfile = cgiReadFile (stdin, boundary);
+
+                                       if (!tmpfile) {
+                                               free (name);
+                                               free (fname);
+                                               if (type)
+                                                       free (type);
+                                               name = fname = type = NULL;
+                                       }
+
+                                       cgiDebugOutput (2, "Wrote %s (%s) to file: %s", name, fname, tmpfile);
+
+                                       if (!strlen (fname)) {
+                                               cgiDebugOutput (3, "Found empty filename, removing");
+                                               unlink (tmpfile);
+                                               free (tmpfile);
+                                               free (name);
+                                               free (fname);
+                                               if (type)
+                                                       free (type);
+                                               name = fname = type = NULL;
+                                       } else {
+                                               if ((file = (s_file *)malloc (sizeof (s_file))) == NULL) {
+                                                       cgiDebugOutput (3, "malloc failed, ignoring %s=%s", name, fname);
+                                                       unlink (tmpfile);
+                                                       free (tmpfile);
+                                                       free (name);
+                                                       free (fname);
+                                                       if (type)
+                                                               free (type);
+                                                       name = fname = type = NULL;
+                                                       continue;
+                                               }
+
+                                               file->name = name;
+                                               file->type = type;
+                                               file->tmpfile = tmpfile;
+                                               if ((cp = rindex (fname, '/')) == NULL)
+                                                       file->filename = fname;
+                                               else {
+                                                       file->filename = strdup (++cp);
+                                                       free (fname);
+                                               }
+                                               name = type = fname = NULL;
+
+                                               if (!files) {
+                                                       if ((files = (s_file **)malloc(2*sizeof (s_file *))) == NULL) {
+                                                               cgiDebugOutput (3, "malloc failed, ignoring %s=%s", name, fname);
+                                                               unlink (tmpfile);
+                                                               free (tmpfile);
+                                                               free (name);
+                                                               name = NULL;
+                                                               if (type) {
+                                                                       free (type);
+                                                                       type = NULL;
+                                                               }
+                                                               free (file->filename);
+                                                               free (file);
+                                                               continue;
+                                                       }
+                                                       memset (files, 0, 2*sizeof (s_file *));
+                                                       index = 0;
+                                               } else {
+                                                       for (index=0; files[index]; index++);
+                                                       if ((tmpf = (s_file **)realloc(files, (index+2)*sizeof (s_file *))) == NULL) {
+                                                               cgiDebugOutput (3, "realloc failed, ignoring %s=%s", name, fname);
+                                                               unlink (tmpfile);
+                                                               free (tmpfile);
+                                                               free (name);
+                                                               if (type)
+                                                                       free (type);
+                                                               free (file->filename);
+                                                               free (file);
+                                                               name = type = fname = NULL;
+                                                               continue;
+                                                       }
+                                                       files = tmpf;
+                                                       memset (files + index, 0, 2*sizeof (s_file *));
+                                               }
+                                               files[index] = file;
+                                       }
+#else
+                                       free(fname);
+                                       fname = NULL;
+#endif
+                               }
+                       }
+               } else {
+                       if (!name)
+                               return;
+
+                       cgiDecodeString(line);
+                       luci_setvar(L, name, line, append);
+                       if (!append) /* beginning of variable contents */
+                               append = true;
+               }
+       }
+}
+
+/* parse the request header and store variables
+ * in the array supplied as function argument 1 on the stack
+ */
+int luci_parse_header (lua_State *L)
+{
+       int length;
+       char *line = NULL;
+       int numargs;
+       char *cp = NULL, *ip = NULL, *esp = NULL;
+       const char *ct, *il;
+       int i;
+
+       if (!lua_istable(L, lua_upvalueindex(1)))
+               luaL_error(L, "Invalid argument");
+
+       if (!lua_istable(L, lua_upvalueindex(2)))
+               luaL_error(L, "Invalid argument");
+
+       ct = luci_getenv(L, "content_type");
+       if (ct) {
+               ct = cp = strdup(ct);
+       }
+       if (cp && strstr(cp, "multipart/form-data") && strstr(cp, "boundary=")) {
+               cp = strstr(cp, "boundary=") + strlen ("boundary=") - 2;
+               *cp = *(cp+1) = '-';
+               luci_parse_multipart(L, cp);
+               free((char *) ct);
+               return 0;
+       }
+       free((char *) ct);
+
+       ct = luci_getenv(L, "request_method");
+       il = luci_getenv(L, "content_length");
+
+       if (!ct) {
+               fprintf(stderr, "no request method!\n");
+               return 0;
+       }
+
+       if (!strcmp(ct, "POST")) {
+               if (il) {
+                       length = atoi(il);
+                       if (length <= 0)
+                               return 0;
+                       line = (char *)malloc (length+2);
+                       if (line)
+                               fgets(line, length+1, stdin);
+               }
+       } else if (!strcmp(ct, "GET")) {
+               ct = luci_getenv(L, "query_string");
+               if (ct)
+                       esp = strdup(ct);
+               if (esp && strlen(esp)) {
+                       line = (char *)malloc (strlen(esp)+2);
+                       if (line)
+                               strcpy (line, esp);
+               }
+               free(esp);
+       }
+
+       if (!line)
+               return 0;
+
+       /*
+        *  From now on all cgi variables are stored in the variable line
+        *  and look like  foo=bar&foobar=barfoo&foofoo=
+        */
+       for (cp=line; *cp; cp++)
+               if (*cp == '+')
+                       *cp = ' ';
+
+       if (strlen(line)) {
+               for (numargs=1,cp=line; *cp; cp++)
+                       if (*cp == '&' || *cp == ';' ) numargs++;
+       } else
+               numargs = 0;
+
+       cp = line;
+       i=0;
+       while (*cp) {
+               char *name;
+               char *value;
+
+               if ((ip = (char *)strchr(cp, '&')) != NULL) {
+                       *ip = '\0';
+               } else if ((ip = (char *)strchr(cp, ';')) != NULL) {
+                       *ip = '\0';
+               } else
+                       ip = cp + strlen(cp);
+
+               if ((esp=(char *)strchr(cp, '=')) == NULL)
+                       goto skip;
+
+               if (!strlen(esp))
+                       goto skip;
+
+               if (i >= numargs)
+                       goto skip;
+
+               esp[0] = 0;
+               name = cp;
+               cgiDecodeString (name);
+
+               cp = ++esp;
+               value = cp;
+               cgiDecodeString (value);
+
+               luci_setvar(L, name, value, false);
+skip:
+               cp = ++ip;
+       }
+       free(line);
+       return 0;
+}
+
diff --git a/libs/sgi-webuci/src/luci.c b/libs/sgi-webuci/src/luci.c
new file mode 100644 (file)
index 0000000..d65fc20
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * luci
+ * Copyright (C) 2008 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation
+ *
+ * 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.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <boa-plugin.h>
+#include <lauxlib.h>
+#include <lualib.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#define LUAMAIN "luci.lua"
+
+static lua_State *L = NULL;
+
+extern int luci_parse_header (lua_State *L);
+
+static int luci_init(struct httpd_plugin *p)
+{
+       char *path = NULL;
+       int ret = 0;
+
+       L = luaL_newstate();
+       if (!L)
+               goto error;
+
+       luaL_openlibs(L);
+
+       path = malloc(strlen(p->dir) + sizeof(LUAMAIN) + 2);
+       strcpy(path, p->dir);
+       strcat(path, "/" LUAMAIN);
+
+       ret = luaL_dofile(L, path);
+
+       lua_getfield(L, LUA_GLOBALSINDEX, "luci-plugin");
+       do {
+               if (!lua_istable(L, -1)) {
+                       ret = 1;
+                       break;
+               }
+
+               lua_getfield(L, -1, "init");
+               if (!lua_isfunction(L, -1))
+                       break;
+
+               lua_pushstring(L, p->dir);
+               ret = lua_pcall(L, 1, 0, 0);
+       } while (0);
+       free(path);
+
+       if (ret != 0)
+               goto error;
+
+       return 1;
+
+error:
+       fprintf(stderr, "Error: ");
+       if (L) {
+               const char *s = lua_tostring(L, -1);
+               if (!s)
+                       s = "unknown error";
+               fprintf(stderr, "%s\n", s);
+               lua_close(L);
+       } else {
+               fprintf(stderr, "Out of memory!\n");
+       }
+       return 0;
+}
+
+static void pushvar(char *name, char *val)
+{
+       if (!val)
+               return;
+
+       lua_pushstring(L, val);
+       lua_setfield(L, -2, name);
+}
+
+static int luci_pcall(lua_State *L, char *func, int narg)
+{
+       int ret;
+
+       ret = lua_pcall(L, narg, narg, 0);
+       if (ret) {
+               const char *s = lua_tostring(L, -1);
+               if (s)
+                       fprintf(stderr, "Error running %s: %s\n", func, s);
+               return ret;
+       }
+       if (!narg)
+               return ret;
+
+       ret = lua_isnumber(L, -1);
+       if (!ret)
+               goto done;
+
+       ret = lua_tonumber(L, -1);
+
+done:
+       lua_pop(L, 1);
+       return ret;
+}
+
+static int luci_prepare_req(struct httpd_plugin *p, struct http_context *ctx)
+{
+       int ret;
+
+       lua_getglobal(L, "luci-plugin");
+       lua_getfield(L, -1, "prepare_req");
+
+       ret = lua_isfunction(L, -1);
+       if (!ret)
+               goto done;
+
+       lua_pushstring(L, ctx->uri);
+
+       ret = luci_pcall(L, "prepare_req", 1);
+
+done:
+       lua_pop(L, 1);
+       return ret;
+}
+
+static int luci_handle_req(struct httpd_plugin *p, struct http_context *ctx)
+{
+       int ret;
+
+       lua_newtable(L); /* new table for the http context */
+
+       /* convert http_context data structure to lua table */
+#define PUSH(x)        pushvar(#x, ctx->x)
+       PUSH(request_method);
+       PUSH(server_addr);
+       PUSH(server_proto);
+       PUSH(query_string);
+       PUSH(remote_addr);
+       lua_pushinteger(L, ctx->remote_port);
+       lua_setfield(L, -2, "remote_port");
+       PUSH(content_type);
+       PUSH(content_length);
+       PUSH(http_accept);
+#undef PUSH
+
+       if (!strncmp(ctx->uri, p->prefix, strlen(p->prefix)))
+               pushvar("uri", ctx->uri + strlen(p->prefix));
+       else
+               pushvar("uri", ctx->uri);
+
+
+       /* make sure the global 'luci' table is prepared */
+       lua_getglobal(L, "luci-plugin");
+       if (!lua_istable(L, -1))
+               return 0;
+
+       lua_getfield(L, -1, "init_req");
+       if (!lua_isfunction(L, -1)) {
+               /* ignore error */
+               lua_pop(L, 1);
+       } else {
+               lua_pushvalue(L, -3);
+               luci_pcall(L, "init_req", 1);
+       }
+
+       /* storage space for cgi variables */
+       lua_newtable(L);
+       lua_pushvalue(L, -1); /* copy for setfield */
+       lua_setfield(L, -3, "vars");
+
+       lua_pushvalue(L, -3); /* the http context table */
+
+       /* 
+        * make luci_parse_header a closure
+        * argument 1: the luci.vars table
+        * argument 2: the http context table
+        */
+       lua_pushcclosure(L, luci_parse_header, 2);
+       ret = luci_pcall(L, "parse_header", 0);
+
+       lua_getfield(L, -1, "handle_req");
+       ret = lua_isfunction(L, -1);
+       if (!ret)
+               goto done;
+
+       lua_pushvalue(L, -3);
+       ret = luci_pcall(L, "handle_req", 1);
+
+       /* pop the luci and http context tables */
+done:
+       lua_pop(L, 2);
+       return ret;
+}
+
+static void luci_unload(struct httpd_plugin *p)
+{
+       lua_close(L);
+}
+
+HTTPD_PLUGIN {
+       .prefix = "/luci/",
+       .init = luci_init,
+       .done = luci_unload,
+       .prepare_req = luci_prepare_req,
+       .handle_req = luci_handle_req,
+};
index 87170a9b18c03ab47fcea460de8af82666156ebd..701c9393867e5f0f636443adcaad829bc0871c1e 100644 (file)
@@ -1,7 +1,7 @@
 config core main
        option lang de
-       option mediaurlbase /luci/fledermaus
-       option resourcebase /luci/resources
+       option mediaurlbase /luci-static/fledermaus
+       option resourcebase /luci-static/resources
        
 config core brand
        option title            "OpenWRT Kamikaze"
@@ -36,4 +36,4 @@ config internal languages
        option en "English"
                
 config internal themes
-       option Fledermaus "/luci/fledermaus"
+       option Fledermaus "/luci-static/fledermaus"
diff --git a/themes/fledermaus/root/www/luci-static/fledermaus/cascade.css b/themes/fledermaus/root/www/luci-static/fledermaus/cascade.css
new file mode 100644 (file)
index 0000000..5920254
--- /dev/null
@@ -0,0 +1,303 @@
+@charset "utf-8";
+
+body {
+       font-family: Verdana, Arial, sans-serif;
+       background-color: #aaaaaa;
+}
+
+h1 {
+       margin: 0%;
+       font-size: 1.4em;
+       font-weight: bold;
+       margin-bottom: 0.5em;
+}
+
+h2 {
+       margin: 0%;
+       font-size: 1.2em;
+       font-weight: bold;
+}
+
+h3 {
+       margin: 0%;
+}
+
+#header {
+       padding: 0.2em;
+       height: 4.5em;
+       background-color: #262626;
+}
+
+#columns {
+       border-left: 10.1em solid #262626;
+       border-right: 10.1em solid #262626;
+       display: block;
+       background-color: white;
+       padding: 0.1em;
+}
+
+#columnswrapper {
+       display: block;
+       margin-left: -10em;
+       margin-right: -10em;
+}
+
+#content {
+       margin-left: 14em;
+       margin-right: 14em;
+       display: block;
+       position: relative;
+       padding: 2px;
+       font-size: 0.8em;
+}
+
+.headerlogo {
+       height: 4em;
+       padding: 5px;
+}
+
+.headerlogo img {
+       height: 100%;
+}
+
+.headertitle {
+       font-size: 2.4em;
+       color: gray;
+       letter-spacing: 0.5em;
+       text-transform: lowercase;
+}
+
+.separator {
+       padding-left: 0.25em;
+       font-weight: bold;
+       font-size: 0.8em;
+       line-height: 1.4em;
+}
+
+.whitetext {
+       color: white;
+}
+
+.yellowtext {
+       color: #ffcb05;
+}
+
+.magentatext {
+       color: #dc0065;
+}
+
+.inheritcolor {
+       color: inherit;
+}
+
+.smalltext {
+       font-size: 0.8em;
+}
+
+.yellow {
+       background-color: #ffcb05;
+}
+
+.magenta {
+       background-color: #dc0065;
+}
+
+.nodeco {
+       text-decoration: none;
+}
+
+.redhover:hover {
+       color: red;
+}
+
+.bold {
+       font-weight: bold;
+}
+
+.sidebar {
+       position: relative;
+       padding: 0.25em;
+       color: gray;
+       width: 9em;
+       font-weight: bold;
+}
+
+.separator a, .sidebar a {
+       color: inherit;
+       text-decoration: inherit;
+}
+
+.separator a:hover, .sidebar a:hover {
+       color: red;
+}
+
+.sidebar div {
+       padding-bottom: 0.5em;
+}
+
+.sidebar ul {
+       font-size: 0.8em;
+       color: white;
+       list-style-type: none;
+       padding-left: 1em;
+       margin-top: 0%;
+}
+
+.table {
+       display: table;
+}
+
+.table-row {
+       display: table-row;
+}
+
+.table-cell {
+       display: table-cell;
+}
+
+.left {
+       float: left;
+       text-align: left;
+}
+
+.right {
+       float: right;
+       text-align: right;
+}
+
+.clear {
+       clear: both;
+}
+
+.hidden {
+       display: none;
+}
+
+.inline {
+       display: inline;
+}
+
+.code {
+       background: #f7f7f7;
+       border: 1px solid #d7d7d7;
+       margin: 1em 1.75em;
+       padding: 1em;
+}
+
+code {
+       display: block;
+       background: #f7f7f7;
+       border: 1px solid #d7d7d7;
+       margin: 1em 1.75em;
+       padding: 1em;
+       overflow: auto;
+       white-space: pre;
+}
+
+table th, table, td {
+       vertical-align: top;
+       text-align: left;
+       border: 1px solid gray;
+}
+
+.cbi-section {
+       margin-top: 1em;
+}
+
+.cbi-section-remove {
+       text-align: right;
+}
+
+.cbi-value {
+       display: table-row;
+}
+
+.cbi-value-title {
+       display: table-cell;
+       line-height: 1.75em;
+       font-weight: bold;
+       padding: 0.25em;
+}
+
+.cbi-value-field {
+       display: table-cell;
+       text-align: left;
+       padding: 0.25em;
+       line-height: 1.75em;
+}
+
+.cbi-value-field input, .cbi-value-field select,
+.cbi-optionals select, .cbi-optionals input,
+.cbi-section-remove input, .cbi-section-create input  {
+       font-size: 0.8em;
+       margin: 0%;
+}
+
+.cbi-section-descr {
+       padding-bottom: 1em;
+}
+
+.cbi-value-description {
+       display: inline;
+       font-style: italic;
+       font-size: 0.8em; 
+       padding: 0.25em;
+       margin-bottom: 0.5em;
+}
+
+.cbi-form-separator {
+       margin-top: 1em;
+}
+
+.cbi-section-node {
+       display: table;
+       padding: 0.25em;
+       background: #f7f7f7;
+       border: 1px solid #d7d7d7;
+}
+
+.cbi-section-row {
+       display: table-row;
+}
+
+.cbi-section-row-head {
+       display: table-cell;
+       font-weight: bold;
+       padding: 0.25em;
+}
+
+.cbi-section-row-descr {
+       display: table-cell;
+       padding: 0.25em;
+       font-size: 0.8em;
+}
+
+.cbi-section-node h3 {
+       margin-bottom: 0.5em;
+}
+
+.cbi-error {
+       color: red;
+       font-weight: bold;
+       font-size: 0.8em;
+       margin-bottom: 0.75em;
+}
+
+.cbi-optionals {
+       margin-top: 1em;
+       display: table-cell;
+}
+
+.cbi-optionals option {
+       font-size: 0.8em;
+}
+
+.error {
+       color: red;
+       font-weight: bold;
+}
+
+.ok {
+       color: green;
+       font-weight: bold;
+}
\ No newline at end of file
diff --git a/themes/fledermaus/root/www/luci-static/fledermaus/logo.png b/themes/fledermaus/root/www/luci-static/fledermaus/logo.png
new file mode 100644 (file)
index 0000000..d4c5dd9
Binary files /dev/null and b/themes/fledermaus/root/www/luci-static/fledermaus/logo.png differ
diff --git a/themes/fledermaus/root/www/luci/fledermaus/cascade.css b/themes/fledermaus/root/www/luci/fledermaus/cascade.css
deleted file mode 100644 (file)
index 5920254..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-@charset "utf-8";
-
-body {
-       font-family: Verdana, Arial, sans-serif;
-       background-color: #aaaaaa;
-}
-
-h1 {
-       margin: 0%;
-       font-size: 1.4em;
-       font-weight: bold;
-       margin-bottom: 0.5em;
-}
-
-h2 {
-       margin: 0%;
-       font-size: 1.2em;
-       font-weight: bold;
-}
-
-h3 {
-       margin: 0%;
-}
-
-#header {
-       padding: 0.2em;
-       height: 4.5em;
-       background-color: #262626;
-}
-
-#columns {
-       border-left: 10.1em solid #262626;
-       border-right: 10.1em solid #262626;
-       display: block;
-       background-color: white;
-       padding: 0.1em;
-}
-
-#columnswrapper {
-       display: block;
-       margin-left: -10em;
-       margin-right: -10em;
-}
-
-#content {
-       margin-left: 14em;
-       margin-right: 14em;
-       display: block;
-       position: relative;
-       padding: 2px;
-       font-size: 0.8em;
-}
-
-.headerlogo {
-       height: 4em;
-       padding: 5px;
-}
-
-.headerlogo img {
-       height: 100%;
-}
-
-.headertitle {
-       font-size: 2.4em;
-       color: gray;
-       letter-spacing: 0.5em;
-       text-transform: lowercase;
-}
-
-.separator {
-       padding-left: 0.25em;
-       font-weight: bold;
-       font-size: 0.8em;
-       line-height: 1.4em;
-}
-
-.whitetext {
-       color: white;
-}
-
-.yellowtext {
-       color: #ffcb05;
-}
-
-.magentatext {
-       color: #dc0065;
-}
-
-.inheritcolor {
-       color: inherit;
-}
-
-.smalltext {
-       font-size: 0.8em;
-}
-
-.yellow {
-       background-color: #ffcb05;
-}
-
-.magenta {
-       background-color: #dc0065;
-}
-
-.nodeco {
-       text-decoration: none;
-}
-
-.redhover:hover {
-       color: red;
-}
-
-.bold {
-       font-weight: bold;
-}
-
-.sidebar {
-       position: relative;
-       padding: 0.25em;
-       color: gray;
-       width: 9em;
-       font-weight: bold;
-}
-
-.separator a, .sidebar a {
-       color: inherit;
-       text-decoration: inherit;
-}
-
-.separator a:hover, .sidebar a:hover {
-       color: red;
-}
-
-.sidebar div {
-       padding-bottom: 0.5em;
-}
-
-.sidebar ul {
-       font-size: 0.8em;
-       color: white;
-       list-style-type: none;
-       padding-left: 1em;
-       margin-top: 0%;
-}
-
-.table {
-       display: table;
-}
-
-.table-row {
-       display: table-row;
-}
-
-.table-cell {
-       display: table-cell;
-}
-
-.left {
-       float: left;
-       text-align: left;
-}
-
-.right {
-       float: right;
-       text-align: right;
-}
-
-.clear {
-       clear: both;
-}
-
-.hidden {
-       display: none;
-}
-
-.inline {
-       display: inline;
-}
-
-.code {
-       background: #f7f7f7;
-       border: 1px solid #d7d7d7;
-       margin: 1em 1.75em;
-       padding: 1em;
-}
-
-code {
-       display: block;
-       background: #f7f7f7;
-       border: 1px solid #d7d7d7;
-       margin: 1em 1.75em;
-       padding: 1em;
-       overflow: auto;
-       white-space: pre;
-}
-
-table th, table, td {
-       vertical-align: top;
-       text-align: left;
-       border: 1px solid gray;
-}
-
-.cbi-section {
-       margin-top: 1em;
-}
-
-.cbi-section-remove {
-       text-align: right;
-}
-
-.cbi-value {
-       display: table-row;
-}
-
-.cbi-value-title {
-       display: table-cell;
-       line-height: 1.75em;
-       font-weight: bold;
-       padding: 0.25em;
-}
-
-.cbi-value-field {
-       display: table-cell;
-       text-align: left;
-       padding: 0.25em;
-       line-height: 1.75em;
-}
-
-.cbi-value-field input, .cbi-value-field select,
-.cbi-optionals select, .cbi-optionals input,
-.cbi-section-remove input, .cbi-section-create input  {
-       font-size: 0.8em;
-       margin: 0%;
-}
-
-.cbi-section-descr {
-       padding-bottom: 1em;
-}
-
-.cbi-value-description {
-       display: inline;
-       font-style: italic;
-       font-size: 0.8em; 
-       padding: 0.25em;
-       margin-bottom: 0.5em;
-}
-
-.cbi-form-separator {
-       margin-top: 1em;
-}
-
-.cbi-section-node {
-       display: table;
-       padding: 0.25em;
-       background: #f7f7f7;
-       border: 1px solid #d7d7d7;
-}
-
-.cbi-section-row {
-       display: table-row;
-}
-
-.cbi-section-row-head {
-       display: table-cell;
-       font-weight: bold;
-       padding: 0.25em;
-}
-
-.cbi-section-row-descr {
-       display: table-cell;
-       padding: 0.25em;
-       font-size: 0.8em;
-}
-
-.cbi-section-node h3 {
-       margin-bottom: 0.5em;
-}
-
-.cbi-error {
-       color: red;
-       font-weight: bold;
-       font-size: 0.8em;
-       margin-bottom: 0.75em;
-}
-
-.cbi-optionals {
-       margin-top: 1em;
-       display: table-cell;
-}
-
-.cbi-optionals option {
-       font-size: 0.8em;
-}
-
-.error {
-       color: red;
-       font-weight: bold;
-}
-
-.ok {
-       color: green;
-       font-weight: bold;
-}
\ No newline at end of file
diff --git a/themes/fledermaus/root/www/luci/fledermaus/logo.png b/themes/fledermaus/root/www/luci/fledermaus/logo.png
deleted file mode 100644 (file)
index d4c5dd9..0000000
Binary files a/themes/fledermaus/root/www/luci/fledermaus/logo.png and /dev/null differ