--- lighttpd-1.4.19/src/mod_rewrite.c	2007-04-10 09:52:58.000000000 +0200
+++ mod_rewrite.c	2008-08-24 17:30:59.000000000 +0200
@@ -7,6 +7,7 @@
 #include "buffer.h"
 
 #include "plugin.h"
+#include "stat_cache.h"
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -31,6 +32,7 @@
 
 typedef struct {
 	rewrite_rule_buffer *rewrite;
+	rewrite_rule_buffer *rewrite_NF;
 	data_config *context; /* to which apply me */
 } plugin_config;
 
@@ -161,6 +163,7 @@
 		for (i = 0; i < srv->config_context->used; i++) {
 			plugin_config *s = p->config_storage[i];
 			rewrite_rule_buffer_free(s->rewrite);
+			rewrite_rule_buffer_free(s->rewrite_NF);
 
 			free(s);
 		}
@@ -172,7 +175,7 @@
 	return HANDLER_GO_ON;
 }
 
-static int parse_config_entry(server *srv, plugin_config *s, array *ca, const char *option, int once) {
+static int parse_config_entry(server *srv, array *ca, rewrite_rule_buffer *kvb, const char *option, int once) {
 	data_unset *du;
 
 	if (NULL != (du = array_get_element(ca, option))) {
@@ -198,7 +201,7 @@
 				return HANDLER_ERROR;
 			}
 
-			if (0 != rewrite_rule_buffer_append(s->rewrite,
+			if (0 != rewrite_rule_buffer_append(kvb,
 							    ((data_string *)(da->value->data[j]))->key,
 							    ((data_string *)(da->value->data[j]))->value,
 							    once)) {
@@ -224,14 +227,23 @@
 		{ "url.rewrite-repeat",        NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
 		{ "url.rewrite-once",          NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
 
+		/* these functions only rewrite if the target is not already in the filestore
+		 *
+		 * url.rewrite-repeat-NF is the equivalent of url.rewrite-repeat
+		 * url.rewrite-once-NF is the equivalent of url.rewrite-once
+		 *
+		 */
+		{ "url.rewrite-repeat-NF",     NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
+		{ "url.rewrite-once-NF",       NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
+
 		/* old names, still supported
 		 *
 		 * url.rewrite remapped to url.rewrite-once
 		 * url.rewrite-final    is url.rewrite-once
 		 *
 		 */
-		{ "url.rewrite",               NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
-		{ "url.rewrite-final",         NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
+		{ "url.rewrite",               NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
+		{ "url.rewrite-final",         NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
 		{ NULL,                        NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
 	};
 
@@ -245,11 +257,15 @@
 		array *ca;
 
 		s = calloc(1, sizeof(plugin_config));
-		s->rewrite   = rewrite_rule_buffer_init();
+		s->rewrite = rewrite_rule_buffer_init();
+		s->rewrite_NF = rewrite_rule_buffer_init();
 
 		cv[0].destination = s->rewrite;
 		cv[1].destination = s->rewrite;
-		cv[2].destination = s->rewrite;
+		cv[2].destination = s->rewrite_NF;
+		cv[3].destination = s->rewrite_NF;
+		cv[4].destination = s->rewrite;
+		cv[5].destination = s->rewrite;
 
 		p->config_storage[i] = s;
 		ca = ((data_config *)srv->config_context->data[i])->value;
@@ -258,10 +274,12 @@
 			return HANDLER_ERROR;
 		}
 
-		parse_config_entry(srv, s, ca, "url.rewrite-once",   1);
-		parse_config_entry(srv, s, ca, "url.rewrite-final",  1);
-		parse_config_entry(srv, s, ca, "url.rewrite",        1);
-		parse_config_entry(srv, s, ca, "url.rewrite-repeat", 0);
+		parse_config_entry(srv, ca, s->rewrite, "url.rewrite-once",      1);
+		parse_config_entry(srv, ca, s->rewrite, "url.rewrite-final",     1);
+		parse_config_entry(srv, ca, s->rewrite_NF, "url.rewrite-once-NF",   1);
+		parse_config_entry(srv, ca, s->rewrite_NF, "url.rewrite-repeat-NF", 0);
+		parse_config_entry(srv, ca, s->rewrite, "url.rewrite",           1);
+		parse_config_entry(srv, ca, s->rewrite, "url.rewrite-repeat",    0);
 	}
 
 	return HANDLER_GO_ON;
@@ -272,6 +290,7 @@
 	plugin_config *s = p->config_storage[0];
 
 	p->conf.rewrite = s->rewrite;
+	p->conf.rewrite_NF = s->rewrite_NF;
 	p->conf.context = NULL;
 
 	/* skip the first, the global context */
@@ -297,6 +316,12 @@
 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-repeat"))) {
 				p->conf.rewrite = s->rewrite;
 				p->conf.context = dc;
+			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-once-NF"))) {
+				p->conf.rewrite_NF = s->rewrite_NF;
+				p->conf.context = dc;
+			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-repeat-NF"))) {
+				p->conf.rewrite_NF = s->rewrite_NF;
+				p->conf.context = dc;
 			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-final"))) {
 				p->conf.rewrite = s->rewrite;
 				p->conf.context = dc;
@@ -320,44 +345,17 @@
 	return HANDLER_GO_ON;
 }
 
-URIHANDLER_FUNC(mod_rewrite_uri_handler) {
+static int process_rewrite_rules(server *srv, connection *con, plugin_data *p, handler_ctx *hctx, rewrite_rule_buffer *kvb) {
 #ifdef HAVE_PCRE_H
-	plugin_data *p = p_d;
 	size_t i;
-	handler_ctx *hctx;
-
-	/*
-	 * REWRITE URL
-	 *
-	 * e.g. rewrite /base/ to /index.php?section=base
-	 *
-	 */
-
-	if (con->plugin_ctx[p->id]) {
-		hctx = con->plugin_ctx[p->id];
-
-		if (hctx->loops++ > 100) {
-			log_error_write(srv, __FILE__, __LINE__,  "s",
-					"ENDLESS LOOP IN rewrite-rule DETECTED ... aborting request, perhaps you want to use url.rewrite-once instead of url.rewrite-repeat");
-
-			return HANDLER_ERROR;
-		}
-
-		if (hctx->state == REWRITE_STATE_FINISHED) return HANDLER_GO_ON;
-	}
-
-	mod_rewrite_patch_connection(srv, con, p);
-
-	if (!p->conf.rewrite) return HANDLER_GO_ON;
-
 	buffer_copy_string_buffer(p->match_buf, con->request.uri);
 
-	for (i = 0; i < p->conf.rewrite->used; i++) {
+	for (i = 0; i < kvb->used; i++) {
 		pcre *match;
 		const char *pattern;
 		size_t pattern_len;
 		int n;
-		rewrite_rule *rule = p->conf.rewrite->ptr[i];
+		rewrite_rule *rule = kvb->ptr[i];
 # define N 10
 		int ovec[N * 3];
 
@@ -427,9 +425,87 @@
 
 			return HANDLER_COMEBACK;
 		}
-	}
 #undef N
+	}
+#else
+	UNUSED(srv);
+	UNUSED(con);
+	UNUSED(p);
+	UNUSED(hctx);
+	UNUSED(kvb);
+#endif
+
+	return HANDLER_GO_ON;
+}
+
+URIHANDLER_FUNC(mod_rewrite_physical) {
+#ifdef HAVE_PCRE_H
+	plugin_data *p = p_d;
+	handler_ctx *hctx;
+	handler_t r;
+
+	if (con->mode != DIRECT) return HANDLER_GO_ON;
+
+	if (con->plugin_ctx[p->id]) {
+		hctx = con->plugin_ctx[p->id];
+
+		if (hctx->loops++ > 100) {
+			log_error_write(srv, __FILE__, __LINE__,  "s",
+					"ENDLESS LOOP IN rewrite-rule DETECTED ... aborting request, perhaps you want to use url.rewrite-once instead of url.rewrite-repeat");
+
+			return HANDLER_ERROR;
+		}
+
+		if (hctx->state == REWRITE_STATE_FINISHED) return HANDLER_GO_ON;
+	}
+
+	mod_rewrite_patch_connection(srv, con, p);
+
+	if (!p->conf.rewrite_NF) return HANDLER_GO_ON;
+
+	stat_cache_entry *sce = NULL;
+	if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) return HANDLER_GO_ON;	
+
+	switch(r = process_rewrite_rules(srv, con, p, hctx, p->conf.rewrite_NF)) {
+	case HANDLER_COMEBACK:
+		buffer_reset(con->physical.path);
+	default:
+		return r;
+		break;
+	}
+#else
+	UNUSED(srv);
+	UNUSED(con);
+	UNUSED(p_d);
+#endif
+
+	return HANDLER_GO_ON;
+}
+
+URIHANDLER_FUNC(mod_rewrite_uri_handler) {
+#ifdef HAVE_PCRE_H
+	plugin_data *p = p_d;
+	handler_ctx *hctx;
+
+
+	if (con->plugin_ctx[p->id]) {
+		hctx = con->plugin_ctx[p->id];
+
+		if (hctx->loops++ > 100) {
+			log_error_write(srv, __FILE__, __LINE__,  "s",
+					"ENDLESS LOOP IN rewrite-rule DETECTED ... aborting request, perhaps you want to use url.rewrite-once instead of url.rewrite-repeat");
+
+			return HANDLER_ERROR;
+		}
+
+		if (hctx->state == REWRITE_STATE_FINISHED) return HANDLER_GO_ON;
+	}
+
+	mod_rewrite_patch_connection(srv, con, p);
+
+	if (!p->conf.rewrite) return HANDLER_GO_ON;
 
+	return process_rewrite_rules(srv, con, p, hctx, p->conf.rewrite);
 #else
 	UNUSED(srv);
 	UNUSED(con);
@@ -448,6 +524,7 @@
 	 */
 
 	p->handle_uri_raw = mod_rewrite_uri_handler;
+	p->handle_physical = mod_rewrite_physical;
 	p->set_defaults = mod_rewrite_set_defaults;
 	p->cleanup     = mod_rewrite_free;
 	p->connection_reset = mod_rewrite_con_reset;
