diff -urN lighttpd-1.4.26_ori/src/Makefile.in lighttpd-1.4.26/src/Makefile.in
--- lighttpd-1.4.26_ori/src/Makefile.in	2010-02-08 04:05:44.000000000 +0800
+++ lighttpd-1.4.26/src/Makefile.in	2010-08-18 09:49:15.793875000 +0800
@@ -232,6 +232,12 @@
 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
 	$(AM_CFLAGS) $(CFLAGS) $(mod_flv_streaming_la_LDFLAGS) \
 	$(LDFLAGS) -o $@
+mod_formlogin_la_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_mod_formlogin_la_OBJECTS = mod_formlogin.lo
+mod_formlogin_la_OBJECTS = $(am_mod_formlogin_la_OBJECTS)
+mod_formlogin_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(mod_formlogin_la_LDFLAGS) $(LDFLAGS) -o $@
 mod_indexfile_la_DEPENDENCIES = $(am__DEPENDENCIES_2)
 am_mod_indexfile_la_OBJECTS = mod_indexfile.lo
 mod_indexfile_la_OBJECTS = $(am_mod_indexfile_la_OBJECTS)
@@ -451,7 +457,7 @@
 	$(mod_dirlisting_la_SOURCES) $(mod_evasive_la_SOURCES) \
 	$(mod_evhost_la_SOURCES) $(mod_expire_la_SOURCES) \
 	$(mod_extforward_la_SOURCES) $(mod_fastcgi_la_SOURCES) \
-	$(mod_flv_streaming_la_SOURCES) $(mod_indexfile_la_SOURCES) \
+	$(mod_flv_streaming_la_SOURCES) $(mod_formlogin_la_SOURCES) $(mod_indexfile_la_SOURCES) \
 	$(mod_magnet_la_SOURCES) $(mod_mysql_vhost_la_SOURCES) \
 	$(mod_proxy_la_SOURCES) $(mod_redirect_la_SOURCES) \
 	$(mod_rewrite_la_SOURCES) $(mod_rrdtool_la_SOURCES) \
@@ -469,7 +475,7 @@
 	$(mod_compress_la_SOURCES) $(mod_dirlisting_la_SOURCES) \
 	$(mod_evasive_la_SOURCES) $(mod_evhost_la_SOURCES) \
 	$(mod_expire_la_SOURCES) $(mod_extforward_la_SOURCES) \
-	$(mod_fastcgi_la_SOURCES) $(mod_flv_streaming_la_SOURCES) \
+	$(mod_fastcgi_la_SOURCES) $(mod_flv_streaming_la_SOURCES) $(mod_formlogin_la_SOURCES) \
 	$(mod_indexfile_la_SOURCES) $(mod_magnet_la_SOURCES) \
 	$(mod_mysql_vhost_la_SOURCES) $(mod_proxy_la_SOURCES) \
 	$(mod_redirect_la_SOURCES) $(mod_rewrite_la_SOURCES) \
@@ -669,13 +675,16 @@
 	mod_ssi.la mod_secdownload.la mod_expire.la mod_evhost.la \
 	mod_simple_vhost.la mod_fastcgi.la mod_extforward.la \
 	mod_access.la mod_compress.la mod_auth.la mod_rewrite.la \
-	mod_redirect.la mod_status.la mod_accesslog.la
+	mod_redirect.la mod_status.la mod_accesslog.la mod_formlogin.la
 @NO_RDYNAMIC_TRUE@liblightcomp_la_SOURCES = $(common_src)
 @NO_RDYNAMIC_TRUE@liblightcomp_la_CFLAGS = $(AM_CFLAGS)
 @NO_RDYNAMIC_TRUE@liblightcomp_la_LDFLAGS = -avoid-version -no-undefined
 @NO_RDYNAMIC_TRUE@liblightcomp_la_LIBADD = $(PCRE_LIB) $(SSL_LIB) $(FAM_LIBS)
 @NO_RDYNAMIC_FALSE@common_libadd = 
 @NO_RDYNAMIC_TRUE@common_libadd = liblightcomp.la
+mod_formlogin_la_SOURCES = mod_formlogin.c
+mod_formlogin_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
+mod_formlogin_la_LIBADD = $(common_libadd)
 mod_flv_streaming_la_SOURCES = mod_flv_streaming.c
 mod_flv_streaming_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
 mod_flv_streaming_la_LIBADD = $(common_libadd)
@@ -908,6 +917,8 @@
 	$(AM_V_CCLD)$(mod_fastcgi_la_LINK) -rpath $(libdir) $(mod_fastcgi_la_OBJECTS) $(mod_fastcgi_la_LIBADD) $(LIBS)
 mod_flv_streaming.la: $(mod_flv_streaming_la_OBJECTS) $(mod_flv_streaming_la_DEPENDENCIES) 
 	$(AM_V_CCLD)$(mod_flv_streaming_la_LINK) -rpath $(libdir) $(mod_flv_streaming_la_OBJECTS) $(mod_flv_streaming_la_LIBADD) $(LIBS)
+mod_formlogin.la: $(mod_formlogin_la_OBJECTS) $(mod_formlogin_la_DEPENDENCIES) 
+	$(mod_formlogin_la_LINK) -rpath $(libdir) $(mod_formlogin_la_OBJECTS) $(mod_formlogin_la_LIBADD) $(LIBS)
 mod_indexfile.la: $(mod_indexfile_la_OBJECTS) $(mod_indexfile_la_DEPENDENCIES) 
 	$(AM_V_CCLD)$(mod_indexfile_la_LINK) -rpath $(libdir) $(mod_indexfile_la_OBJECTS) $(mod_indexfile_la_LIBADD) $(LIBS)
 mod_magnet.la: $(mod_magnet_la_OBJECTS) $(mod_magnet_la_DEPENDENCIES) 
@@ -1105,6 +1116,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_extforward.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_fastcgi.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_flv_streaming.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_formlogin.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_indexfile.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_magnet_la-mod_magnet.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_magnet_la-mod_magnet_cache.Plo@am__quote@
diff -urN lighttpd-1.4.26_ori/src/mod_formlogin.c lighttpd-1.4.26/src/mod_formlogin.c
--- lighttpd-1.4.26_ori/src/mod_formlogin.c	1970-01-01 08:00:00.000000000 +0800
+++ lighttpd-1.4.26/src/mod_formlogin.c	2010-08-13 09:24:41.392274000 +0800
@@ -0,0 +1,401 @@
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include "base.h"
+#include "log.h"
+#include "buffer.h"
+
+#include "plugin.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef USE_OPENSSL
+# include <openssl/md5.h>
+#else
+# include "md5.h"
+#endif
+
+#include <syslog.h>
+#include "sessions.h"
+
+/**
+ * this is a formlogin for a lighttpd plugin
+ *
+ * just replaces every occurance of 'formlogin' by your plugin name
+ *
+ * e.g. in vim:
+ *
+ *   :%s/formlogin/myhandler/
+ *
+ */
+
+/* plugin config for all request/connections */
+
+typedef struct {
+	buffer *auth_file;
+	buffer *cookie_name;
+	buffer *cookie_domain;
+	array *exclude_path;
+	array *sslvpn_path;
+	unsigned short cookie_max_age;
+	formlogin_config* fl_cfg;
+} plugin_config;
+
+typedef struct {
+	PLUGIN_DATA;
+
+	plugin_config **config_storage;
+
+	plugin_config conf;
+} plugin_data;
+
+/* init the plugin data */
+INIT_FUNC(mod_formlogin_init) {
+	plugin_data *p;
+
+	int fd;
+    
+	(void) openlog("formlogin", LOG_PERROR, LOG_USER);
+	p = calloc(1, sizeof(*p));
+	
+	// init formlogin config
+	if ((p->conf.fl_cfg = (formlogin_config *)openConfigMmap(FL_CFG_NAME, "w", &fd, FL_CFG_SIZE))) {
+		memset(p->conf.fl_cfg, 0, FL_CFG_SIZE);
+		closeConfigMmap(fd, (int *)p->conf.fl_cfg, FL_CFG_SIZE);
+	}
+
+	return p;
+}
+
+/* detroy the plugin data */
+FREE_FUNC(mod_formlogin_free) {
+	plugin_data *p = p_d;
+
+	int fd;
+    
+	if ((p->conf.fl_cfg = (formlogin_config *)openConfigMmap(FL_CFG_NAME, "w", &fd, FL_CFG_SIZE))) {
+		memset(p->conf.fl_cfg, 0, FL_CFG_SIZE);
+		closeConfigMmap(fd, (int *)p->conf.fl_cfg, FL_CFG_SIZE);
+	}
+	
+	UNUSED(srv);
+
+	if (!p) return HANDLER_GO_ON;
+
+	if (p->config_storage) {
+		size_t i;
+		for (i = 0; i < srv->config_context->used; i++) {
+			plugin_config *s = p->config_storage[i];
+
+			buffer_free(s->auth_file);
+			buffer_free(s->cookie_name);
+			buffer_free(s->cookie_domain);
+			array_free(s->exclude_path);
+			array_free(s->sslvpn_path);
+
+			free(s);
+		}
+		free(p->config_storage);
+	}
+
+	free(p);
+
+	return HANDLER_GO_ON;
+}
+
+/* handle plugin config and check values */
+
+SETDEFAULTS_FUNC(mod_formlogin_set_defaults) {
+	plugin_data *p = p_d;
+	size_t i = 0;
+
+	config_values_t cv[] = {
+		{ "formlogin.auth-file",		     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
+		{ "formlogin.cookie-name",       NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
+		{ "formlogin.cookie-max-age",    NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },        /* 2 */
+		{ "formlogin.cookie-domain",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 3 */
+		{ "formlogin.exclude-path",      NULL, T_CONFIG_ARRAY,  T_CONFIG_SCOPE_CONNECTION },       /* 4 */
+		{ "formlogin.sslvpn-path",      NULL, T_CONFIG_ARRAY,  T_CONFIG_SCOPE_CONNECTION },       /* 5 */
+
+		{ "formlogin.cookiename",        NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
+		{ NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+	};
+
+	if (!p) return HANDLER_ERROR;
+
+	p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+
+	for (i = 0; i < srv->config_context->used; i++) {
+		plugin_config *s;
+
+		s = calloc(1, sizeof(plugin_config));
+		s->auth_file			= buffer_init();
+		s->cookie_name    = buffer_init();
+		s->cookie_domain  = buffer_init();
+		s->exclude_path		= array_init();
+		s->sslvpn_path		= array_init();
+		s->cookie_max_age = FL_DEF_UPDATE;
+
+		cv[0].destination = s->auth_file;
+		cv[1].destination = s->cookie_name;
+		cv[2].destination = &(s->cookie_max_age);
+		cv[3].destination = s->cookie_domain;
+		cv[4].destination = s->exclude_path;
+		cv[5].destination = s->sslvpn_path;
+
+		p->config_storage[i] = s;
+
+		if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+			return HANDLER_ERROR;
+		}
+		
+		if (buffer_is_empty(s->auth_file)) {
+			buffer_copy_string(s->auth_file, FL_AUTH_PATH);
+		}
+
+		if (buffer_is_empty(s->cookie_name)) {
+			buffer_copy_string(s->cookie_name, FL_SESSIONID_NAME);
+		} else {
+			size_t j;
+			for (j = 0; j < s->cookie_name->used - 1; j++) {
+				char c = s->cookie_name->ptr[j] | 32;
+				if (c < 'a' || c > 'z') {
+					log_error_write(srv, __FILE__, __LINE__, "sb",
+							"invalid character in formlogin.cookie-name:",
+							s->cookie_name);
+
+					return HANDLER_ERROR;
+				}
+			}
+		}
+
+		if (!buffer_is_empty(s->cookie_domain)) {
+			size_t j;
+			for (j = 0; j < s->cookie_domain->used - 1; j++) {
+				char c = s->cookie_domain->ptr[j];
+				if (c <= 32 || c >= 127 || c == '"' || c == '\\') {
+					log_error_write(srv, __FILE__, __LINE__, "sb",
+							"invalid character in formlogin.cookie-domain:",
+							s->cookie_domain);
+
+					return HANDLER_ERROR;
+				}
+			}
+		}
+	}
+
+	return HANDLER_GO_ON;
+}
+
+#define PATCH(x) \
+	p->conf.x = s->x;
+static int mod_formlogin_patch_connection(server *srv, connection *con, plugin_data *p) {
+	size_t i, j;
+	plugin_config *s = p->config_storage[0];
+
+	PATCH(auth_file);
+	PATCH(cookie_name);
+	PATCH(cookie_domain);
+	PATCH(exclude_path);
+	PATCH(sslvpn_path);
+	PATCH(cookie_max_age);
+
+	/* skip the first, the global context */
+	for (i = 1; i < srv->config_context->used; i++) {
+		data_config *dc = (data_config *)srv->config_context->data[i];
+		s = p->config_storage[i];
+
+		/* condition didn't match */
+		if (!config_check_cond(srv, con, dc)) continue;
+
+		/* merge config */
+		for (j = 0; j < dc->value->used; j++) {
+			data_unset *du = dc->value->data[j];
+			
+			if (buffer_is_equal_string(du->key, CONST_STR_LEN("formlogin.auth-file"))) {
+				PATCH(auth_file);
+			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("formlogin.cookie-name"))) {
+				PATCH(cookie_name);
+			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("formlogin.exclude-path"))) {
+				PATCH(exclude_path);
+			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("formlogin.cookie-max-age"))) {
+				PATCH(cookie_max_age);
+			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("formlogin.cookie-domain"))) {
+				PATCH(cookie_domain);
+			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("formlogin.sslvpn-path"))) {
+				PATCH(sslvpn_path);
+			}
+		}
+	}
+
+	return 0;
+}
+#undef PATCH
+
+URIHANDLER_FUNC(mod_formlogin_uri_handler) {
+	static int init_auth_file = 0;
+	plugin_data *p = p_d;
+	data_string *ds;
+#ifdef HAVE_IPV6
+	char b2[INET6_ADDRSTRLEN + 1];
+#endif
+	char strLocation[256];
+	const char* remote_ip;
+	unsigned char h[16];
+	MD5_CTX Md5Ctx;
+	char hh[32];
+	int auth_required = 1;
+	size_t k;
+	int fd;
+	int levels = -1;
+	unsigned long uptime = get_uptime();
+
+	if (con->uri.path->used == 0) return HANDLER_GO_ON;
+
+	mod_formlogin_patch_connection(srv, con, p);
+
+
+
+#ifdef HAVE_IPV6
+		remote_ip = inet_ntop(con->dst_addr.plain.sa_family,
+			      con->dst_addr.plain.sa_family == AF_INET6 ?
+			      (const void *) &(con->dst_addr.ipv6.sin6_addr) :
+			      (const void *) &(con->dst_addr.ipv4.sin_addr),
+			      b2, sizeof(b2)-1);
+#else
+		remote_ip = inet_ntoa(con->dst_addr.ipv4.sin_addr);
+#endif
+
+	if (!init_auth_file && (p->conf.fl_cfg = (formlogin_config *)openConfigMmap(FL_CFG_NAME, "w", &fd, FL_CFG_SIZE))) {
+		strcpy(p->conf.fl_cfg->auth_file,  p->conf.auth_file->ptr);
+		p->conf.fl_cfg->update_time = p->conf.cookie_max_age;
+		init_auth_file = 1;
+		closeConfigMmap(fd, (int *)p->conf.fl_cfg, FL_CFG_SIZE);
+	}
+
+	if (p->conf.exclude_path->used) {
+		for (k = 0; k < p->conf.exclude_path->used; k++) {
+			data_string *ds = (data_string *)p->conf.exclude_path->data[k];
+			if (con->conf.force_lowercase_filenames) {
+				if (0 == strncasecmp(con->uri.path->ptr, ds->value->ptr, strlen(ds->value->ptr))) {
+					auth_required = 0;
+					break;
+				}
+			} else {
+				if (0 == strncmp(con->uri.path->ptr, ds->value->ptr, strlen(ds->value->ptr))) {
+					auth_required = 0;
+					break;
+				}
+			}
+		}
+	}
+	
+	if (auth_required && p->conf.sslvpn_path->used) {
+		for (k = 0; k < p->conf.sslvpn_path->used; k++) {
+			data_string *ds = (data_string *)p->conf.sslvpn_path->data[k];
+			if (con->conf.force_lowercase_filenames) {
+				if (0 == strncasecmp(con->uri.path->ptr, ds->value->ptr, strlen(ds->value->ptr))) {
+					auth_required = 2;
+					break;
+				}
+			} else {
+				if (0 == strncmp(con->uri.path->ptr, ds->value->ptr, strlen(ds->value->ptr))) {
+					auth_required = 2;
+					break;
+				}
+			}
+		}
+	}
+
+	if(!auth_required) return HANDLER_GO_ON;
+
+	if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) {
+		char *g;
+		/* we have a cookie, does it contain a valid name ? */
+
+		/* parse the cookie
+		 *
+		 * check for cookiename + (WS | '=')
+		 *
+		 */
+
+		//syslog(LOG_NOTICE, "cookie: %s, name: %s", ds->value->ptr, p->conf.cookie_name->ptr);
+		if (NULL != (g = strstr(ds->value->ptr, p->conf.cookie_name->ptr))) {
+			char *nc;
+
+			/* skip WS */
+			for (nc = g + p->conf.cookie_name->used-1; *nc == ' ' || *nc == '\t'; nc++);
+
+			if (*nc == '=') {
+				/* ok, found the key of our own cookie */
+
+				if (strlen(nc) >= 32) {
+					if ((p->conf.fl_cfg = (formlogin_config *)openConfigMmap(FL_CFG_NAME, "w", &fd, FL_CFG_SIZE))) {
+						k = form_get_idx_by_sessionid(p->conf.fl_cfg->sessions, uptime, nc+1);
+						
+						if(k!=-1) levels = p->conf.fl_cfg->sessions[k].level;
+
+
+						if(k!=-1 && p->conf.fl_cfg->sessions[k].level < 3 && auth_required==1) {
+								p->conf.fl_cfg->sessions[k].last_time = uptime;
+								closeConfigMmap(fd, (int *)p->conf.fl_cfg, FL_CFG_SIZE);
+								return HANDLER_GO_ON;
+						} else if(k!=-1 && p->conf.fl_cfg->sessions[k].level == 3 && auth_required==2 && con->conf.is_ssl) {
+								p->conf.fl_cfg->sessions[k].last_time = uptime;
+								closeConfigMmap(fd, (int *)p->conf.fl_cfg, FL_CFG_SIZE);
+								return HANDLER_GO_ON;
+						}
+						closeConfigMmap(fd, (int *)p->conf.fl_cfg, FL_CFG_SIZE);
+					}
+
+				}
+			}
+		}
+	}
+
+	if(levels == 3) 
+	{
+		if(!con->conf.is_ssl) {
+			if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Host"))) {
+				sprintf(strLocation, "https://%s%s", ds->value->ptr, FL_LOGIN_PAGE);
+			}
+			con->http_status = 302;
+			response_header_insert(srv, con, CONST_STR_LEN("Content-Length"), CONST_STR_LEN("0"));
+			response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_STR_LEN(strLocation));
+			return HANDLER_FINISHED;
+		} else {
+			con->http_status = 403;
+			buffer_reset(con->physical.path);
+
+			return HANDLER_FINISHED;
+		}
+	} else {
+		con->http_status = 302;
+		response_header_insert(srv, con, CONST_STR_LEN("Content-Length"), CONST_STR_LEN("0"));
+		response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_STR_LEN(FL_LOGIN_PAGE));
+		return HANDLER_FINISHED;
+	}
+}
+
+/* this function is called at dlopen() time and inits the callbacks */
+
+int mod_formlogin_plugin_init(plugin *p) {
+	p->version     = LIGHTTPD_VERSION_ID;
+	p->name        = buffer_init_string("formlogin");
+
+	p->init        = mod_formlogin_init;
+	p->handle_uri_clean  = mod_formlogin_uri_handler;
+	p->set_defaults  = mod_formlogin_set_defaults;
+	p->cleanup     = mod_formlogin_free;
+
+	p->data        = NULL;
+
+	return 0;
+}
diff -urN lighttpd-1.4.26_ori/src/sessions.h lighttpd-1.4.26/src/sessions.h
--- lighttpd-1.4.26_ori/src/sessions.h	1970-01-01 08:00:00.000000000 +0800
+++ lighttpd-1.4.26/src/sessions.h	2010-08-13 09:24:41.392274000 +0800
@@ -0,0 +1,395 @@
+#include <time.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <syslog.h>
+
+#define CFGDIR_RAM "/var/switch"
+
+
+#ifdef _CGI_DEBUG__
+#define CGI_T_E(fmt, ...) syslog(LOG_ERR, fmt, ##__VA_ARGS__)
+#define CGI_T_W(fmt, ...) syslog(LOG_WARNING, fmt, ##__VA_ARGS__)
+#define CGI_T_D(fmt, ...) syslog(LOG_INFO, fmt, ##__VA_ARGS__)
+#else
+#define CGI_T_E(fmt, ...)       /* Go Away */
+#define CGI_T_W(fmt, ...)       /* Go Away */
+#define CGI_T_D(fmt, ...)       /* Go Away */
+#endif
+
+
+#define FL_DEF_UPDATE		300
+#define FL_SESSION_MAX		10
+#define FL_SSLAPP_MAX		30
+#define FL_CFG_SIZE			(sizeof(formlogin_config))
+#define FL_CFG_NAME			"FL_CFG"
+#define FL_AUTH_REALM		"Vigor"
+#define	FL_AUTH_PATH		"/etc/httpusers.conf"
+#define FL_SESSIONID_NAME	"SESSION_ID_VIGOR"
+#define FL_LOGIN_PAGE		"/login.htm"
+#define FL_INDEX_PAGE		"/index.htm"
+#define FL_SSLVPN_PAGE		"/sslvpn_index.htm"
+#define FL_STATUS_PAGE		"/sslvpn_status.htm"
+#define FL_TMOUT_PAGE		"/l_m.htm"
+
+#define USER_LEN		32
+#define COOKIE_LEN		48
+#define HOST_LEN		16
+#define PATH_LEN		128
+
+#define INVAILED_USER	0
+#define ADMIN_USER		1
+#define GENERAL_USER	2
+#define SSLVPN_USER		3
+
+#define ADMIN_INDEX		0
+#define USER_INDEX		1
+#define SSLVPN_INDEX	2
+
+#define INIT_ACTIVE		0
+#define NO_ACTIVE		1
+#define STILL_ACTIVE	2
+
+
+#define CREDIT_BASIC	0
+#define CREDIT_COOKIE	1
+
+
+typedef struct _formlogin_session
+{
+	char username[USER_LEN];
+	char cookie[COOKIE_LEN];
+	char remote_ip[HOST_LEN];
+	int creditial_type[FL_SSLAPP_MAX];
+	char creditials[FL_SSLAPP_MAX][70];
+	unsigned long creditials_ipadd[FL_SSLAPP_MAX];
+	unsigned long creditial_last[FL_SSLAPP_MAX];
+	unsigned long update_time;
+	unsigned long last_time;
+	unsigned short level;
+	unsigned short active;
+} formlogin_session;
+
+typedef struct _formlogin_session_bak
+{
+	char remote_ip[HOST_LEN];
+	unsigned long last_time;
+} formlogin_session_bak;
+
+
+typedef struct _formlogin_config
+{
+	unsigned long update_time;
+	char auth_file[PATH_LEN];
+	formlogin_session sessions[FL_SESSION_MAX];
+	formlogin_session_bak sessions_bak[FL_SESSION_MAX];
+} formlogin_config;
+
+int *openConfigMmap(const char *fn, const char *mode, int *return_fd, size_t size);
+int closeConfigMmap(int fd, int *mmap, size_t size);
+long get_uptime(void);
+
+int form_check_user_style(formlogin_config* config, char *username, int *index_in_sessiontable);
+void form_bak_session_info(formlogin_config* config, int index);
+int form_add_session(formlogin_config* config, int index, char *username,
+			char *remote_ip, char *p_sid, int user_style, unsigned long cur_time);
+int form_del_session(formlogin_config* config, int index);
+int form_is_session_active(formlogin_session* sessions, unsigned long cur_time, int index);
+int form_get_idx_by_sessionid(formlogin_session* sessions, unsigned long cur_time, char *pSessionId);
+
+
+int *openConfigMmap(const char *fn, const char *mode, int *return_fd, size_t size)
+{
+    char fnbuf[40];
+    int fd;
+    int *map; 
+    int result;
+    
+    snprintf(fnbuf, sizeof(fnbuf), "%s/%s.mmap", CFGDIR_RAM, fn);
+    
+    if(!strcmp(mode, "r")){
+        
+        fd = open(fnbuf, O_RDONLY);
+        if (fd == -1) {
+            CGI_T_E("Error opening file for reading");
+            return NULL;
+            //exit(EXIT_FAILURE);
+        }
+    
+        map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0);
+        if (map == MAP_FAILED) {
+            close(fd);
+            CGI_T_E("Error mmapping the file");
+            exit(EXIT_FAILURE);
+        }
+    } else {
+#if 0
+            fd = open(fnbuf, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
+            if (fd == -1) {
+                CGI_T_E("Error opening file for writing");
+                return NULL;
+                //exit(EXIT_FAILURE);
+            }
+        
+            CGI_T_D("opening file for writing successfully! ");
+            
+            result = lseek(fd, size-1, SEEK_SET);
+            if (result == -1) {
+                close(fd);
+                CGI_T_E("Error calling lseek() to 'stretch' the file");
+                exit(EXIT_FAILURE);
+            }
+            
+            result = write(fd, "", 1);
+            if (result != 1) {
+                close(fd);
+                CGI_T_E("Error writing last byte of the file");
+                exit(EXIT_FAILURE);
+            }
+        
+            map = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+            if (mmap == MAP_FAILED) {
+                close(fd);
+                CGI_T_E("Error mmapping the file");
+                //exit(EXIT_FAILURE);
+                return NULL;
+            }
+#else        
+        fd = open(fnbuf, O_RDONLY);
+        if (fd == -1) {
+            fd = open(fnbuf, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
+            if (fd == -1) {
+                CGI_T_E("Error opening file for writing");
+                return NULL;
+                //exit(EXIT_FAILURE);
+            }
+        
+            CGI_T_D("opening file for writing successfully! ");
+            
+            result = lseek(fd, size-1, SEEK_SET);
+            if (result == -1) {
+                close(fd);
+                CGI_T_E("Error calling lseek() to 'stretch' the file");
+                exit(EXIT_FAILURE);
+            }
+            
+            result = write(fd, "", 1);
+            if (result != 1) {
+                close(fd);
+                CGI_T_E("Error writing last byte of the file");
+                exit(EXIT_FAILURE);
+            }
+        
+            map = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+            if (map == MAP_FAILED) {
+                close(fd);
+                CGI_T_E("Error mmapping the file");
+                //exit(EXIT_FAILURE);
+                return NULL;
+            }
+            CGI_T_D("openConfig_finish ");
+        } else {
+            
+            close(fd);
+            
+            fd = open(fnbuf, O_RDWR, (mode_t)0600);
+            if (fd == -1) {
+                CGI_T_E("Error opening file for writing");
+                return NULL;
+                //exit(EXIT_FAILURE);
+            }
+                
+            map = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+            if (map == MAP_FAILED) {
+                close(fd);
+                CGI_T_E("Error mmapping the file");
+                //exit(EXIT_FAILURE);
+                return NULL;
+            }
+        }
+#endif
+    }
+    
+    *return_fd = fd;
+    return map;
+}
+
+int closeConfigMmap(int fd, int *mmap, size_t size)
+{
+    if (munmap(mmap, size) == -1) {
+        CGI_T_E("Error un-mmapping the file");
+    }
+    close(fd);
+    CGI_T_D("closeConfigMmap" );
+    
+    return 0;
+}
+
+long get_uptime(void)
+{
+    FILE *f=fopen("/proc/uptime","r");
+    long time = 0;
+    if (f && fscanf(f, "%ld", &time) == 1) {
+        fclose(f);
+        return time;
+    }
+    return 0;
+}
+
+/*
+Input: username, index_in_sessiontable
+Output: index_in_sessiontable
+Return: User Style
+*/
+int form_check_user_style(formlogin_config* config, char *username, int *index_in_sessiontable)
+{
+	int i, blank_idx;
+	if ( (!strcmp("root", username) || !strcmp("admin", username)) ) {
+		*index_in_sessiontable = ADMIN_INDEX;
+		return ADMIN_USER;
+	}
+
+	// remove "user", Joel, 2009/5/22
+	//if ( (!strcmp("", username) || !strcmp("user", username)) ) {
+	if ( !strcmp("", username) ) {
+		*index_in_sessiontable = USER_INDEX;
+		return GENERAL_USER;
+	}
+	
+	*index_in_sessiontable = -1;
+	blank_idx = -1;
+	for(i = SSLVPN_INDEX; i < FL_SESSION_MAX; i++)
+	{
+		if ( !config->sessions[i].active ) {
+			if(blank_idx == -1)
+				blank_idx = i;
+			
+			continue;
+		}
+		if ( !strcmp(config->sessions[i].username, username) ) {
+			*index_in_sessiontable = i;
+			return SSLVPN_USER;
+		}
+	}
+
+	if(blank_idx != -1) {
+		*index_in_sessiontable = blank_idx;
+		return SSLVPN_USER;
+	}
+	
+	return INVAILED_USER;
+}
+
+void form_bak_session_info(formlogin_config* config, int index)
+{
+	//bak login info
+	strcpy(config->sessions_bak[index].remote_ip, config->sessions[index].remote_ip);
+	config->sessions_bak[index].last_time = config->sessions[index].last_time;
+}
+
+
+/*
+Input: config, index, username, remote_ip, p_sid, user_style, cur_time
+Output:
+Return: 0:Fail, 1:Success
+*/
+int form_add_session(formlogin_config* config, int index, char *username,
+			char *remote_ip, char *p_sid, int user_style, unsigned long cur_time)
+{
+	if(index<0 || index >= FL_SESSION_MAX) return 0;
+	
+	if(config->sessions[index].active){
+		form_bak_session_info(config, index);
+	}
+	config->sessions[index].active = 1;
+	strcpy(config->sessions[index].username, username);
+	strcpy(config->sessions[index].remote_ip, remote_ip);
+	strcpy(config->sessions[index].cookie, p_sid);
+	config->sessions[index].level = user_style;
+	config->sessions[index].last_time = cur_time;
+	config->sessions[index].update_time = config->update_time;
+	
+	memset(config->sessions[index].creditials, 0, FL_SSLAPP_MAX * 70);
+	memset(config->sessions[index].creditials_ipadd, 0, FL_SSLAPP_MAX * sizeof(unsigned long));
+	memset(config->sessions[index].creditial_last, 0, FL_SSLAPP_MAX * sizeof(unsigned long));
+	
+	return 1;
+
+}
+
+/*
+Input: config, index
+Output:
+Return: 0:Fail, 1:Success
+*/
+int form_del_session(formlogin_config* config, int index)
+{
+	if(index<0 || index >= FL_SESSION_MAX) return 0;
+	
+	form_bak_session_info(config, index);
+	config->sessions[index].active = 0;
+	
+	return 1;
+}
+
+/*
+Input: sessions, cur_time, index
+Output:
+Return: Session Active
+*/
+int form_is_session_active(formlogin_session* sessions, unsigned long cur_time, int index)
+{
+	if(!sessions[index].active) {return INIT_ACTIVE;}
+
+	if(sessions[index].update_time == 0) {return STILL_ACTIVE;}
+	
+	if(cur_time < sessions[index].last_time) { sessions[index].last_time = 0; }
+
+	if( (cur_time - sessions[index].last_time) >= sessions[index].update_time ) {
+		return NO_ACTIVE;
+	} else {
+		return STILL_ACTIVE;
+	}
+}
+
+/*
+Input: sessions, cur_time, pSessionId
+Output:
+Return: Session Index
+*/
+int form_get_idx_by_sessionid(formlogin_session* sessions, unsigned long cur_time, char *pSessionId)
+{
+	int i;
+	
+	if(NULL == pSessionId) return -1;
+	
+	for(i=0; i<FL_SESSION_MAX; i++)
+	{
+		if(!strncmp(sessions[i].cookie, pSessionId, 34)){
+			if(form_is_session_active(sessions, cur_time, i) == STILL_ACTIVE){
+				return i;
+			}
+		}
+	}
+	
+	return -1;
+}
+/*
+Input: void
+Return: ADMIN_USER, GENERAL_USER
+*/
+int get_auth(void)
+{
+	const char *cookie = getenv("HTTP_COOKIE");
+	char *p;
+
+    p = strstr(cookie, FL_SESSIONID_NAME);
+    if (p) p = p+strlen(FL_SESSIONID_NAME)+1;
+
+    if(*p-'0' == ADMIN_USER) {
+    	return ADMIN_USER;
+    } else {
+    	return GENERAL_USER;
+    } 
+}
