+++ /dev/null
-include ../../build/module.mk
-include ../../build/config.mk
-include ../../build/gccconfig.mk
-
-%.o: %.c
- $(COMPILE) $(LUA_CFLAGS) $(FPIC) -c -o $@ $<
-
-compile: src/fastindex.o
- mkdir -p dist$(LUCI_LIBRARYDIR)
- $(LINK) $(SHLIB_FLAGS) -o dist$(LUCI_LIBRARYDIR)/fastindex.so src/fastindex.o $(LUA_SHLIBS)
-
-clean:
- rm -f src/*.o
+++ /dev/null
-/*
- * fastindex - fast lua module indexing plugin
- * 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 <sys/types.h>
-#include <sys/time.h>
-#include <sys/cdefs.h>
-
-#ifndef _POSIX_C_SOURCE
-#define _POSIX_C_SOURCE /* XXX: portability hack for timestamp */
-#endif
-
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <glob.h>
-
-#include <lualib.h>
-#include <lauxlib.h>
-#include "list.h"
-
-#define MODNAME "luci.fastindex"
-#define DEFAULT_BUFLEN 1024
-
-//#define DEBUG 1
-
-#ifdef DEBUG
-#define DPRINTF(...) fprintf(stderr, __VA_ARGS__)
-#else
-#define DPRINTF(...) do {} while (0)
-#endif
-
-/**
- * list_for_each_offset - iterate over a list, start with the provided pointer
- * @pos: the &struct list_head to use as a loop cursor.
- * @head: the head for your list.
- */
-#define list_for_each_offset(pos, head, offset) \
- for (pos = (offset)->next; pos != (offset); \
- pos = ((pos->next == (head)) && ((offset) != (head)) ? (head)->next : pos->next))
-
-static char *namespace = NULL;
-
-struct fastindex_entry {
- struct list_head list;
- time_t timestamp;
- int checked;
- char *name;
-};
-
-struct fastindex_pattern {
- struct list_head list;
- char pattern[];
-};
-
-struct fastindex {
- lua_State *L;
- int checked;
- char *func;
- struct list_head patterns;
- struct list_head *last;
- struct list_head entries;
- int ofs;
- char *buf;
- int buflen;
-};
-
-static inline struct fastindex *
-to_fastindex(struct lua_State *L)
-{
- struct fastindex *f;
- lua_getfield(L, lua_upvalueindex(1), "__data");
- f = lua_touserdata(L, -1);
- lua_pop(L, 1);
- return f;
-}
-
-static int
-fastindex_module(lua_State *L)
-{
- const char *s;
- s = luaL_checkstring(L, 1);
-
- if (s) {
- if (namespace)
- free(namespace);
- namespace = strdup(s);
- }
-
- return 0;
-}
-
-static struct fastindex_entry *
-find_entry(struct fastindex *f, char *name)
-{
- struct list_head *p;
-
- if (!f->last)
- f->last = &f->entries;
-
- list_for_each_offset(p, &f->entries, f->last) {
- struct fastindex_entry *e;
- e = container_of(p, struct fastindex_entry, list);
- if (!strcmp(e->name, name))
- return e;
- }
- return NULL;
-}
-
-static struct fastindex_entry *
-new_entry(struct fastindex *f, char *name)
-{
- struct fastindex_entry *e;
-
- e = malloc(sizeof(struct fastindex_entry));
- if (!e)
- goto error;
-
- memset(e, 0, sizeof(struct fastindex_entry));
- e->name = strdup(name);
- if (!e->name) {
- free(e);
- goto error;
- }
- INIT_LIST_HEAD(&e->list);
-
- return e;
-
-error:
- return NULL;
-}
-
-static void free_entry(struct fastindex_entry *e)
-{
- list_del(&e->list);
- free(e->name);
- free(e);
-}
-
-int bufferwriter(lua_State *L, const void *p, size_t sz, void *ud)
-{
- struct fastindex *f = ud;
-
- while (f->ofs + sz > f->buflen) {
- char *b = f->buf;
- f->buflen *= 2;
- f->buf = realloc(f->buf, f->buflen);
- if (!f->buf) {
- free(b);
- return 1;
- }
- }
- memcpy(f->buf + f->ofs, p, sz);
- f->ofs += sz;
- return 0;
-}
-
-static void
-load_index(struct fastindex *f, struct fastindex_entry *e)
-{
- lua_State *L;
-
- DPRINTF("Loading module: %s\n", e->name);
-
- if (!f->buf)
- f->buf = malloc(f->buflen);
-
- if (!f->buf)
- luaL_error(f->L, "Out of memory!\n");
-
- f->ofs = 0;
- L = luaL_newstate();
- if (!L)
- return;
-
- namespace = NULL;
- luaL_openlibs(L);
- lua_pushcfunction(L, fastindex_module);
- lua_setfield(L, LUA_GLOBALSINDEX, "module");
-
- do {
- if (luaL_dofile(L, e->name)) {
- DPRINTF("Warning: unable to open module '%s'\n", e->name);
- break;
- }
-
- lua_getglobal(L, f->func);
- lua_dump(L, bufferwriter, f);
- DPRINTF("Got %d bytes\n", f->ofs);
- if (f->ofs == 0)
- break;
- lua_createtable(f->L, (namespace ? 2 : 1), 0);
- luaL_loadbuffer(f->L, f->buf, f->ofs, "tmp");
- lua_rawseti(f->L, -2, 1);
- if (namespace) {
- DPRINTF("Module has namespace '%s'\n", namespace);
- lua_pushstring(f->L, namespace);
- lua_rawseti(f->L, -2, 2);
- free(namespace);
- namespace = NULL;
- }
- lua_setfield(f->L, -2, e->name);
- } while (0);
-
- lua_close(L);
-}
-
-
-static int
-fastindex_scan(lua_State *L)
-{
- struct list_head *tmp, *p;
- struct fastindex *f;
- glob_t gl;
- int i;
- int gl_flags = GLOB_NOESCAPE | GLOB_NOSORT | GLOB_MARK;
-
- f = to_fastindex(L);
- f->checked++;
-
-
- if (list_empty(&f->patterns))
- return 0;
-
- lua_getfield(L, lua_upvalueindex(1), "indexes");
- list_for_each(p, &f->patterns) {
- struct fastindex_pattern *pt = container_of(p, struct fastindex_pattern, list);
- glob(pt->pattern, gl_flags, NULL, &gl);
- gl_flags |= GLOB_APPEND;
- }
- for (i = 0; i < gl.gl_pathc; i++) {
- struct fastindex_entry *e;
- struct stat st;
-
- if (stat(gl.gl_pathv[i], &st))
- continue;
-
- if ((st.st_mode & S_IFMT) != S_IFREG)
- continue;
-
- e = find_entry(f, gl.gl_pathv[i]);
- if (!e) {
- e = new_entry(f, gl.gl_pathv[i]);
- list_add_tail(&e->list, &f->entries);
- }
-
- e->checked = f->checked;
- if ((e->timestamp < st.st_mtime)) {
- load_index(f, e);
- e->timestamp = st.st_mtime;
- }
- }
- globfree(&gl);
- list_for_each_safe(p, tmp, &f->entries) {
- struct fastindex_entry *e = container_of(p, struct fastindex_entry, list);
- if (e->checked < f->checked) {
- lua_pushnil(f->L);
- lua_setfield(f->L, -2, e->name);
- free_entry(e);
- }
- }
- lua_pop(L, 1);
-
- return 0;
-}
-
-static int
-fastindex_free(lua_State *L)
-{
- struct fastindex *f;
- struct list_head *p, *tmp;
-
- f = lua_touserdata(L, -1);
- list_for_each_safe(p, tmp, &f->patterns) {
- struct fastindex_pattern *pt;
- pt = container_of(p, struct fastindex_pattern, list);
- list_del(p);
- free(pt);
- }
- list_for_each_safe(p, tmp, &f->entries) {
- struct fastindex_entry *e;
- e = container_of(p, struct fastindex_entry, list);
- free_entry(e);
- }
- return 0;
-}
-
-static int
-fastindex_add(lua_State *L)
-{
- struct fastindex_pattern *pt;
- struct fastindex *f;
- const char *str;
-
- f = to_fastindex(L);
- str = luaL_checkstring(L, 1);
- if (!str)
- luaL_error(L, "Invalid argument");
-
- pt = malloc(sizeof(struct fastindex_pattern) + strlen(str) + 1);
- if (!pt)
- luaL_error(L, "Out of memory");
-
- INIT_LIST_HEAD(&pt->list);
- strcpy(pt->pattern, str);
- list_add(&pt->list, &f->patterns);
-
- return 0;
-}
-
-static const luaL_Reg fastindex_m[] = {
- { "add", fastindex_add },
- { "scan", fastindex_scan },
- { NULL, NULL }
-};
-
-static int
-fastindex_new(lua_State *L)
-{
- struct fastindex *f;
- const char *func;
-
- func = luaL_checkstring(L, 1);
-
- f = lua_newuserdata(L, sizeof(struct fastindex));
- lua_createtable(L, 0, 2);
- lua_pushvalue(L, -1);
- lua_setfield(L, -2, "__index");
- lua_pushcfunction(L, fastindex_free);
- lua_setfield(L, -2, "__gc");
- lua_pushvalue(L, -1);
- lua_setmetatable(L, -3);
- lua_pushvalue(L, -2);
- lua_setfield(L, -2, "__data");
- lua_createtable(L, 0, 1);
- lua_setfield(L, -2, "indexes");
- lua_pushvalue(L, -2);
- luaI_openlib(L, NULL, fastindex_m, 1);
-
- memset(f, 0, sizeof(struct fastindex));
- f->L = L;
- f->buflen = DEFAULT_BUFLEN;
- INIT_LIST_HEAD(&f->entries);
- INIT_LIST_HEAD(&f->patterns);
-
- f->func = strdup(func);
- if (!f->func) {
- if (f->func)
- free(f->func);
- luaL_error(L, "Out of memory\n");
- }
-
- return 1;
-}
-
-static const luaL_Reg fastindex[] = {
- { "new", fastindex_new },
- { NULL, NULL },
-};
-
-int
-luaopen_luci_fastindex(lua_State *L)
-{
- luaL_register(L, MODNAME, fastindex);
- return 0;
-}
+++ /dev/null
-#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
+++ /dev/null
-boa-patches/series
-boa-*.*
+++ /dev/null
-include ../../build/config.mk
-include ../../build/gccconfig.mk
-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 top 2>/dev/null)" = "$$(tail -n1 patches/series)" ] || 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) -DINET6 -DACCEPT_ON -DWHEN_DOES_THIS_APPLY"
-
-%.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) -o dist/usr/lib/boa/luci.so src/luci.o src/cgi.o $(LDFLAGS) $(LUA_LIBS)
-
-clean:
- rm -rf $(BOA_DIR) $(BOA_FILE)
- rm -f boa-patches/series
- rm -f src/*.o
+++ /dev/null
-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(¤t_time);
-- time_offset = TIMEZONE_OFFSET(t);
-- } else {
-- t = gmtime(¤t_time);
-- time_offset = 0;
-- }
--
-+ t = gmtime(¤t_time);
-+ time_offset = 0;
-+
- p = buf + 29;
- *p-- = '\0';
- *p-- = ' ';
-
+++ /dev/null
-Index: boa-0.94.13/src/config.c
-===================================================================
---- boa-0.94.13.orig/src/config.c 2008-06-29 00:55:19.000000000 +0200
-+++ boa-0.94.13/src/config.c 2008-06-29 00:59:08.000000000 +0200
-@@ -273,12 +273,12 @@
- }
-
- he = gethostbyname(temp_name);
-- if (he == NULL) {
-- perror("gethostbyname:");
-- exit(1);
-- }
-+ if (he && he->h_name)
-+ server_name = he->h_name;
-+ else
-+ server_name = "OpenWrt";
-
-- server_name = strdup(he->h_name);
-+ server_name = strdup(server_name);
- if (server_name == NULL) {
- perror("strdup:");
- exit(1);
+++ /dev/null
-Index: boa-0.94.13/src/boa.c
-===================================================================
---- boa-0.94.13.orig/src/boa.c 2002-07-23 17:50:29.000000000 +0200
-+++ boa-0.94.13/src/boa.c 2008-06-29 01:12:31.000000000 +0200
-@@ -222,7 +222,7 @@
- /* test for failed-but-return-was-successful setuid
- * http://www.securityportal.com/list-archive/bugtraq/2000/Jun/0101.html
- */
-- if (setuid(0) != -1) {
-+ if ((server_uid != 0) && (setuid(0) != -1)) {
- DIE("icky Linux kernel bug!");
- }
- } else {
+++ /dev/null
-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-06-29 01:12:36.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-06-29 02:02:42.000000000 +0200
-@@ -0,0 +1,191 @@
-+/*
-+ * 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;
-+ ctx.cookie = req->cookie;
-+ 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 | RTLD_GLOBAL);
-+ 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);
-+ return 1;
-+}
-+
-+
-Index: boa-0.94.13/src/request.c
-===================================================================
---- boa-0.94.13.orig/src/request.c 2008-06-29 01:11:52.000000000 +0200
-+++ boa-0.94.13/src/request.c 2008-06-29 01:49:46.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);
-@@ -698,6 +716,8 @@
- req->header_user_agent = value;
- if (!add_cgi_env(req, "USER_AGENT", value, 1))
- return 0;
-+ } else if (!memcmp(line, "COOKIE", 7)) {
-+ req->cookie = value;
- } else {
- if (!add_cgi_env(req, line, value, 1))
- return 0;
-Index: boa-0.94.13/src/Makefile.in
-===================================================================
---- boa-0.94.13.orig/src/Makefile.in 2008-06-29 01:11:52.000000000 +0200
-+++ boa-0.94.13/src/Makefile.in 2008-06-29 01:12:36.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 2008-06-29 01:11:52.000000000 +0200
-+++ boa-0.94.13/src/boa.h 2008-06-29 01:12:36.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 2008-06-29 01:11:52.000000000 +0200
-+++ boa-0.94.13/src/config.c 2008-06-29 01:12:36.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 2008-06-29 01:11:52.000000000 +0200
-+++ boa-0.94.13/src/alias.c 2008-06-29 01:12:36.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 2008-06-29 01:11:52.000000000 +0200
-+++ boa-0.94.13/src/globals.h 2008-06-29 01:47:25.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 */
-@@ -99,6 +101,7 @@
- char *query_string; /* env variable */
- char *content_type; /* env variable */
- char *content_length; /* env variable */
-+ char *cookie; /* env variable */
-
- struct mmap_entry *mmap_entry_var;
-
-Index: boa-0.94.13/src/read.c
-===================================================================
---- boa-0.94.13.orig/src/read.c 2008-06-29 01:11:52.000000000 +0200
-+++ boa-0.94.13/src/read.c 2008-06-29 01:12:36.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-06-29 02:02:27.000000000 +0200
-@@ -0,0 +1,68 @@
-+#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;
-+ char *cookie;
-+
-+ 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
+++ /dev/null
-Index: boa-0.94.13/src/request.c
-===================================================================
---- boa-0.94.13.orig/src/request.c 2008-06-29 01:11:52.000000000 +0200
-+++ boa-0.94.13/src/request.c 2008-10-07 18:10:59.000000000 +0200
-@@ -281,6 +281,10 @@
- if (req->script_name)
- free(req->script_name);
-
-+#ifdef ACCEPT_ON
-+ req->accept[0] = '\0';
-+#endif
-+
- if ((req->keepalive == KA_ACTIVE) &&
- (req->response_status < 500) && req->kacount > 0) {
- int bytes_to_move;
+++ /dev/null
-diff -urN boa-0.94.13.orig/src/boa.c boa-0.94.13/src/boa.c
---- boa-0.94.13.orig/src/boa.c 2008-10-28 16:15:45.000000000 +0100
-+++ boa-0.94.13/src/boa.c 2008-10-28 15:56:27.000000000 +0100
-@@ -27,6 +27,12 @@
- #include <sys/resource.h>
-
- /* globals */
-+
-+#ifdef INET6
-+int server_addr_family;
-+socklen_t server_addr_len;
-+#endif
-+
- int backlog = SO_MAXCONN;
- time_t start_time;
-
-@@ -164,14 +170,36 @@
- return 0;
- }
-
-+#ifdef INET6
-+sa_family_t *get_addr_family(struct sockaddr *address)
-+{
-+ if(server_addr_family == AF_INET6) {
-+ return &(((struct sockaddr_in6 *) address)->sin6_family);
-+ }
-+
-+ return &(((struct sockaddr_in *) address)->sin_family);
-+}
-+#endif
-+
- static int create_server_socket(void)
- {
- int server_s;
-
-- server_s = socket(SERVER_AF, SOCK_STREAM, IPPROTO_TCP);
-+#ifdef INET6
-+ server_addr_family = AF_INET6;
-+ server_addr_len = sizeof(struct sockaddr_in6);
-+ server_s = socket(server_addr_family, SOCK_STREAM, IPPROTO_TCP);
- if (server_s == -1) {
-- DIE("unable to create socket");
-+ server_addr_family = AF_INET;
-+ server_addr_len = sizeof(struct sockaddr_in);
-+#endif
-+ server_s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-+ if (server_s == -1) {
-+ DIE("unable to create socket");
-+ }
-+#ifdef INET6
- }
-+#endif
-
- /* server socket is nonblocking */
- if (set_nonblock_fd(server_s) == -1) {
-diff -urN boa-0.94.13.orig/src/boa.h boa-0.94.13/src/boa.h
---- boa-0.94.13.orig/src/boa.h 2008-10-28 16:15:58.000000000 +0100
-+++ boa-0.94.13/src/boa.h 2008-10-28 14:45:52.000000000 +0100
-@@ -199,4 +199,12 @@
- int plugin_handle(request * req);
- struct httpd_plugin *plugin_lookup(request *req);
-
-+/* IPv6 */
-+
-+#ifdef INET6
-+extern int server_addr_family;
-+extern socklen_t server_addr_len;
-+sa_family_t *get_addr_family(struct sockaddr *address);
-+#endif
-+
- #endif
-diff -urN boa-0.94.13.orig/src/compat.h boa-0.94.13/src/compat.h
---- boa-0.94.13.orig/src/compat.h 2002-06-06 07:02:28.000000000 +0200
-+++ boa-0.94.13/src/compat.h 2008-10-28 15:31:16.000000000 +0100
-@@ -71,11 +71,13 @@
-
- #ifdef INET6
- #define SOCKADDR sockaddr_storage
--#define S_FAMILY __s_family
--#define SERVER_AF AF_INET6
-+#define SOCKADDR_LEN server_addr_len
-+#define S_FAMILY(address) (*get_addr_family((struct sockaddr *) (address)))
-+#define SERVER_AF server_addr_family
- #else
- #define SOCKADDR sockaddr_in
--#define S_FAMILY sin_family
-+#define SOCKADDR_LEN sizeof(struct sockaddr_in)
-+#define S_FAMILY(address) ((*address).sin_family)
- #define SERVER_AF AF_INET
- #endif
-
-diff -urN boa-0.94.13.orig/src/ip.c boa-0.94.13/src/ip.c
---- boa-0.94.13.orig/src/ip.c 2002-01-21 03:19:16.000000000 +0100
-+++ boa-0.94.13/src/ip.c 2008-10-28 15:52:05.000000000 +0100
-@@ -44,52 +44,64 @@
-
- #include "boa.h"
- #include <arpa/inet.h> /* inet_ntoa */
-+#include <netinet/in.h>
-
- /* Binds to the existing server_s, based on the configuration string
- in server_ip. IPv6 version doesn't pay attention to server_ip yet. */
- int bind_server(int server_s, char *server_ip)
- {
-+ struct sockaddr *server_sockaddr;
-+ struct sockaddr_in server_sockaddr4;
-+
- #ifdef INET6
-- struct sockaddr_in6 server_sockaddr;
-- server_sockaddr.sin6_family = AF_INET6;
-- memcpy(&server_sockaddr.sin6_addr, &in6addr_any, sizeof (in6addr_any));
-- server_sockaddr.sin6_port = htons(server_port);
--#else
-- struct sockaddr_in server_sockaddr;
-- memset(&server_sockaddr, 0, sizeof server_sockaddr);
-+ struct sockaddr_in6 server_sockaddr6;
-+ if(SERVER_AF == AF_INET6) {
-+ server_sockaddr6.sin6_family = AF_INET6;
-+ memcpy(&server_sockaddr6.sin6_addr, &in6addr_any, sizeof (in6addr_any));
-+ server_sockaddr6.sin6_port = htons(server_port);
-+ server_sockaddr = (struct sockaddr *) &server_sockaddr6;
-+ } else {
-+#endif
-+ memset(&server_sockaddr4, 0, SOCKADDR_LEN);
- #ifdef HAVE_SIN_LEN /* uncomment for BSDs */
-- server_sockaddr.sin_len = sizeof server_sockaddr;
-+ server_sockaddr4.sin_len = SOCKADDR_LEN;
- #endif
-- server_sockaddr.sin_family = AF_INET;
-- if (server_ip != NULL) {
-- inet_aton(server_ip, &server_sockaddr.sin_addr);
-- } else {
-- server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
-+ server_sockaddr4.sin_family = AF_INET;
-+ if (server_ip != NULL) {
-+ inet_aton(server_ip, &server_sockaddr4.sin_addr);
-+ } else {
-+ server_sockaddr4.sin_addr.s_addr = htonl(INADDR_ANY);
-+ }
-+ server_sockaddr4.sin_port = htons(server_port);
-+ server_sockaddr = (struct sockaddr *) &server_sockaddr4;
-+#ifdef INET6
- }
-- server_sockaddr.sin_port = htons(server_port);
- #endif
-
-- return bind(server_s, (struct sockaddr *) &server_sockaddr,
-- sizeof (server_sockaddr));
-+ return bind(server_s, server_sockaddr, SOCKADDR_LEN);
- }
-
- char *ascii_sockaddr(struct SOCKADDR *s, char *dest, int len)
- {
- #ifdef INET6
-- if (getnameinfo((struct sockaddr *) s,
-- sizeof(struct SOCKADDR),
-- dest, len, NULL, 0, NI_NUMERICHOST)) {
-- fprintf(stderr, "[IPv6] getnameinfo failed\n");
-- *dest = '\0';
-- }
-+ if(SERVER_AF == AF_INET6) {
-+ if (getnameinfo((struct sockaddr *) s,
-+ SOCKADDR_LEN,
-+ dest, len, NULL, 0, NI_NUMERICHOST)) {
-+ fprintf(stderr, "[IPv6] getnameinfo failed\n");
-+ *dest = '\0';
-+ }
- #ifdef WHEN_DOES_THIS_APPLY
-- if ((s->__ss_family == AF_INET6) &&
-- IN6_IS_ADDR_V4MAPPED(&(((struct sockaddr_in6 *) s)->sin6_addr))) {
-- memmove(dest, dest+7, NI_MAXHOST);
-- }
-+ if (((((struct sockaddr_in6 *) s)->sin6_family) == AF_INET6) &&
-+ IN6_IS_ADDR_V4MAPPED(&(((struct sockaddr_in6 *) s)->sin6_addr))) {
-+ memmove(dest, dest+7, NI_MAXHOST);
-+ }
- #endif
--#else
-- memmove(dest, inet_ntoa(s->sin_addr), len);
-+ } else {
-+#endif
-+ memmove(dest, inet_ntoa(((struct sockaddr_in *) s)->sin_addr), len);
-+#ifdef INET6
-+ }
- #endif
- return dest;
- }
-@@ -98,17 +110,21 @@
- {
- int p = -1;
- #ifdef INET6
-- char serv[NI_MAXSERV];
-+ if(SERVER_AF == AF_INET6) {
-+ char serv[NI_MAXSERV];
-
-- if (getnameinfo((struct sockaddr *) s,
-- sizeof(struct SOCKADDR),
-- NULL, 0, serv, sizeof(serv), NI_NUMERICSERV)) {
-- fprintf(stderr, "[IPv6] getnameinfo failed\n");
-+ if (getnameinfo((struct sockaddr *) s,
-+ SOCKADDR_LEN,
-+ NULL, 0, serv, sizeof(serv), NI_NUMERICSERV)) {
-+ fprintf(stderr, "[IPv6] getnameinfo failed\n");
-+ } else {
-+ p = atoi(serv);
-+ }
- } else {
-- p = atoi(serv);
-+#endif
-+ p = ntohs(((struct sockaddr_in *) s)->sin_port);
-+#ifdef INET6
- }
--#else
-- p = ntohs(s->sin_port);
- #endif
- return p;
- }
-diff -urN boa-0.94.13.orig/src/mmap_cache.c boa-0.94.13/src/mmap_cache.c
---- boa-0.94.13.orig/src/mmap_cache.c 2002-03-24 23:35:34.000000000 +0100
-+++ boa-0.94.13/src/mmap_cache.c 2008-10-28 14:55:16.000000000 +0100
-@@ -67,7 +67,7 @@
-
- m = mmap(0, s->st_size, PROT_READ, MAP_OPTIONS, data_fd, 0);
-
-- if ((int) m == -1) {
-+ if ((ssize_t) m == -1) {
- /* boa_perror(req,"mmap"); */
- return NULL;
- }
-diff -urN boa-0.94.13.orig/src/request.c boa-0.94.13/src/request.c
---- boa-0.94.13.orig/src/request.c 2008-10-28 16:16:03.000000000 +0100
-+++ boa-0.94.13/src/request.c 2008-10-28 15:17:20.000000000 +0100
-@@ -75,12 +75,12 @@
- int fd; /* socket */
- struct SOCKADDR remote_addr; /* address */
- struct SOCKADDR salocal;
-- int remote_addrlen = sizeof (struct SOCKADDR);
-+ int remote_addrlen = SOCKADDR_LEN;
- request *conn; /* connection */
-- size_t len;
-+ socklen_t len;
- static int system_bufsize = 0; /* Default size of SNDBUF given by system */
-
-- remote_addr.S_FAMILY = 0xdead;
-+ S_FAMILY(&remote_addr) = 0xdead;
- fd = accept(server_s, (struct sockaddr *) &remote_addr,
- &remote_addrlen);
-
-@@ -133,7 +133,7 @@
- }
- #endif
-
-- len = sizeof(salocal);
-+ len = SOCKADDR_LEN;
-
- if (getsockname(fd, (struct sockaddr *) &salocal, &len) != 0) {
- WARN("getsockname");
+++ /dev/null
-#!/bin/sh
-CWD=$1
-cat <<EOF
-Port 8080
-ErrorLog /dev/stderr
-AccessLog /dev/stderr
-DocumentRoot $CWD/www
-DirectoryMaker $CWD/usr/lib/boa/boa_indexer
-KeepAliveMax 1000
-KeepAliveTimeout 10
-MimeTypes $CWD/etc/mime.types
-DefaultType text/plain
-CGIPath $CWD/bin:$CWD/usr/bin:$CWD/usr/local/bin
-
-AddType application/x-httpd-cgi cgi
-AddType application/x-httpd-cgi sh
-
-ScriptAlias /cgi-bin/ $CWD/www/cgi-bin
-PluginRoot $CWD/usr/lib/boa
-EOF
+++ /dev/null
---[[
-LuCI - SGI-Module for Webuci
-
-Description:
-Server Gateway Interface for Webuci
-
-FileId:
-$Id$
-
-License:
-Copyright 2008 Steven Barth <steven@midlink.org>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-]]--
-module("luci.sgi.webuci", package.seeall)
-local ltn12 = require("luci.ltn12")
-require("luci.http")
-require("luci.util")
-require("luci.dispatcher")
-
-function run(env, vars)
- local r = luci.http.Request(
- env,
- ltn12.source.empty(),
- ltn12.sink.file(io.stderr)
- )
-
- r.message.params = vars
-
- local x = coroutine.create(luci.dispatcher.httpdispatch)
- local status = ""
- local headers = {}
- local active = true
-
- while coroutine.status(x) ~= "dead" do
- local res, id, data1, data2 = coroutine.resume(x, r)
-
- if not res then
- print(env.SERVER_PROTOCOL .. " 500 Internal Server Error")
- print("Content-Type: text/plain\n")
- print(id)
- break;
- end
-
- if active then
- if id == 1 then
- status = env.SERVER_PROTOCOL .. " " .. tostring(data1) .. " " .. data2 .. "\r\n"
- elseif id == 2 then
- headers[data1] = data2
- elseif id == 3 then
- io.write(status)
- for k, v in pairs(headers) do
- io.write(k .. ": " .. v .. "\r\n")
- end
- io.write("\r\n")
- elseif id == 4 then
- io.write(data1)
- elseif id == 5 then
- active = false
- end
- end
- end
-end
+++ /dev/null
-Port 80
-ErrorLog /dev/stderr
-AccessLog /dev/stderr
-DocumentRoot /www
-DirectoryMaker /usr/lib/boa/boa_indexer
-KeepAliveMax 1000
-KeepAliveTimeout 10
-MimeTypes /etc/mime.types
-DefaultType text/plain
-ServerName localhost
-CGIPath /bin:/usr/bin
-
-AddType application/x-httpd-cgi cgi
-AddType application/x-httpd-cgi sh
-
-ScriptAlias /cgi-bin/ /www/cgi-bin
-PluginRoot /usr/lib/boa
+++ /dev/null
-#!/bin/sh /etc/rc.common
-#
-# Written by Miquel van Smoorenburg <miquels@cistron.nl>.
-# Modified for Debian GNU/Linux
-# by Ian Murdock <imurdock@gnu.ai.mit.edu>.
-# Modified for boa by Bill Allombert <ballombe@debian.org>.
-# Modified for OpenWrt by Steven Barth <steven@midlink.org>.
-
-### BEGIN INIT INFO
-# Provides: boa
-# Required-Start: $local_fs $remote_fs $network
-# Required-Stop: $local_fs $remote_fs $network
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: Boa: lightweight and high performance web server
-### END INIT INFO
-
-PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
-DAEMON=/usr/bin/boa
-NAME=boa
-DESC="HTTP server"
-START=49
-
-test -x $DAEMON || exit 0
-
-set -e
-
-start() {
- echo -n "Starting $DESC: $NAME"
- start-stop-daemon -S -q -x $DAEMON
- echo "."
-}
-
-stop() {
- echo -n "Stopping $DESC: $NAME"
- start-stop-daemon -K -q -x $DAEMON
- echo "."
-}
-
-restart() {
- echo -n "Restarting $DESC: $NAME... "
- start-stop-daemon -K -s HUP -q -x $DAEMON
- echo "done."
-}
-
-reload() {
- #
- # If the daemon can reload its config files on the fly
- # for example by sending it SIGHUP, do it here.
- #
- # If the daemon responds to changes in its config file
- # directly anyway, make this a do-nothing entry.
- #
- echo -n "Reloading $DESC configuration... "
- start-stop-daemon -K -s 1 -q -x $DAEMON
- echo "done."
-}
+++ /dev/null
-###############################################################################
-#
-# 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
+++ /dev/null
-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("luci.model.uci")
-
- if (root ~= '/') then
- -- Entering dummy mode
- luci.model.uci.cursor = function(config, ...)
- return uci.cursor(config or root .. "/etc/config", ...)
- end
-
- 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
-
- luci.sys.user.checkpasswd = function() return true end
- end
-end
-
-function prepare_req(uri)
- luci.dispatcher.createindex()
- env = {}
- env.REQUEST_URI = uri
- -- TODO: setting luci-plugin.reload = true allows this function to trigger a context reload
-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.HTTP_COOKIE = context.cookie
- env.HTTP_ACCEPT = context.http_accept
- env.SCRIPT_NAME = env.REQUEST_URI:sub(1, #env.REQUEST_URI - #env.PATH_INFO)
-
- luci.sgi.webuci.run(env, vars)
-end
+++ /dev/null
-/*
- * 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;
-}
-
+++ /dev/null
-/*
- * 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 lua_State *luci_context_init(struct httpd_plugin *p)
-{
- char *path = NULL;
- lua_State *Lnew;
- int ret = 0;
-
- Lnew = luaL_newstate();
- if (!Lnew)
- goto error;
-
- luaL_openlibs(Lnew);
-
- path = malloc(strlen(p->dir) + sizeof(LUAMAIN) + 2);
- strcpy(path, p->dir);
- strcat(path, "/" LUAMAIN);
-
- ret = luaL_dofile(Lnew, path);
-
- lua_getfield(Lnew, LUA_GLOBALSINDEX, "luci-plugin");
- do {
- if (!lua_istable(Lnew, -1)) {
- ret = 1;
- break;
- }
-
- lua_getfield(Lnew, -1, "init");
- if (!lua_isfunction(Lnew, -1))
- break;
-
- lua_pushstring(Lnew, p->dir);
- ret = lua_pcall(Lnew, 1, 0, 0);
- } while (0);
- free(path);
-
- if (ret != 0)
- goto error;
-
- return Lnew;
-
-error:
- fprintf(stderr, "Error: ");
- if (Lnew) {
- const char *s = lua_tostring(Lnew, -1);
- if (!s)
- s = "unknown error";
- fprintf(stderr, "%s\n", s);
- lua_close(Lnew);
- } else {
- fprintf(stderr, "Out of memory!\n");
- }
- return NULL;
-}
-
-static int luci_init(struct httpd_plugin *p)
-{
- L = luci_context_init(p);
- return (L != NULL);
-}
-
-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;
- bool reload = false;
-
- lua_getglobal(L, "luci-plugin");
- lua_getfield(L, -1, "reload");
- if (lua_isboolean(L, -1))
- reload = lua_toboolean(L, -1);
- lua_pop(L, 1);
-
- if (reload) {
- lua_close(L);
- L = luci_context_init(p);
- 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(cookie);
- 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,
-};
+++ /dev/null
-include ../../build/config.mk
-include ../../build/module.mk
\ No newline at end of file
+++ /dev/null
---[[
-LuCI - SGI-Module for WSAPI
-
-Description:
-Server Gateway Interface for WSAPI
-
-FileId:
-$Id$
-
-License:
-Copyright 2008 Steven Barth <steven@midlink.org>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-]]--
-module("luci.sgi.wsapi", package.seeall)
-local ltn12 = require("luci.ltn12")
-require("luci.http")
-require("luci.dispatcher")
-require("luci.http.protocol")
-
-function run(wsapi_env)
- local r = luci.http.Request(
- wsapi_env,
- ltn12.source.file(wsapi_env.input),
- ltn12.sink.file(wsapi_env.error)
- )
-
- local res, id, data1, data2 = true, 0, nil, nil
- local headers = {}
- local status = 200
-
- local x = coroutine.create(luci.dispatcher.httpdispatch)
- local active = true
-
- while id < 3 do
- res, id, data1, data2 = coroutine.resume(x, r)
-
- if not res then
- status = 500
- headers["Content-Type"] = "text/plain"
- local err = {id}
- return status, headers, function() local x = table.remove(err) return x end
- end
-
- if id == 1 then
- status = data1
- elseif id == 2 then
- headers[data1] = data2
- end
- end
-
- local function iter()
- local res, id, data = coroutine.resume(x)
- if id == 4 and active then
- return data
- elseif id == 5 then
- active = false
- return ""
- else
- return ""
- end
- if coroutine.status(x) == "dead" then
- return nil
- end
- end
-
- return status, headers, iter
-end