# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# see http://www.akamoz.jp/you/adsl/remove-prepend.en.htm 
# for usage of this patch.
#
Index: Makefile
===================================================================
diff -u -r1.3 -r1.3.2.1
--- Makefile	23 Dec 2004 11:03:58 -0000	1.3
+++ Makefile	26 Jul 2011 13:39:00 -0000	1.3.2.1
@@ -1174,12 +1174,13 @@
 load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o \
 slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a lock.a fd.a \
 wait.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \
-fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib
+fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib \
+constmap.o control.o case.a
 	./load qmail-local qmail.o quote.o now.o gfrom.o myctime.o \
 	slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a \
 	lock.a fd.a wait.a env.a stralloc.a alloc.a strerr.a \
-	substdio.a error.a str.a fs.a datetime.a auto_qmail.o \
-	auto_patrn.o  `cat socket.lib`
+	substdio.a error.a str.a datetime.a auto_qmail.o \
+	auto_patrn.o constmap.o control.o case.a fs.a `cat socket.lib`
 
 qmail-local.0: \
 qmail-local.8
Index: qmail-local.c
===================================================================
diff -u -r1.2 -r1.2.2.1
--- qmail-local.c	23 Dec 2004 11:03:58 -0000	1.2
+++ qmail-local.c	26 Jul 2011 13:39:00 -0000	1.2.2.1
@@ -28,6 +28,9 @@
 #include "myctime.h"
 #include "gfrom.h"
 #include "auto_patrn.h"
+#include "auto_qmail.h"
+#include "control.h"
+#include "constmap.h"
 
 void usage() { strerr_die1x(100,"qmail-local: usage: qmail-local [ -nN ] user homedir local dash ext domain sender aliasempty"); }
 
@@ -63,6 +66,7 @@
 stralloc cmds = {0};
 stralloc messline = {0};
 stralloc foo = {0};
+stralloc envrecipz = {0};
 
 char buf[1024];
 char outbuf[1024];
@@ -444,6 +448,87 @@
  substdio_putsflush(subfdoutsmall,"\n");
 }
 
+/*
+ * Check recip against the control file fn, which contains
+ * the virtual domain table like control/virtualdomains,
+ * and return offset of recip just after prepend part if hit.
+ * Return 0 if else. The procedure is as follows.
+ * CAUTION: This mechanism works well only for virtual domains,
+ *   does NOT work well for virtual users, becase the prepend part 
+ *   cannot be correctly guessed from the mangled address.
+ * 1. Open the control file which name is auto_qmail "/control/" fn.
+ * 2. Read into vdoms.
+ * 3. Create constmap into mapvdoms.
+ * 4. Test against virtual user exception.
+ * 5. Test against virtual users.
+ *	Test continues if constmap hits but prepend is not matched.
+ * 6. Test against virtual domains.
+ *	Test terminates if constmap hits.
+ */
+static int stripvdomprepend_local(recip, fn)
+const char *recip;	/* recipient address */
+const char *fn;		/* control file name */
+{
+ int i;
+ const char *prepend;
+ static stralloc sa_temp = { 0 };
+ static stralloc vdoms = { 0 };
+ static struct constmap mapvdoms;
+
+	int reciplen;
+	int pos;
+	int atpos;
+
+ /* read the control file */
+ if (!stralloc_copys(&sa_temp, auto_qmail)) temp_nomem();
+ if (!stralloc_cats(&sa_temp, "/control/")) temp_nomem();
+ if (!stralloc_cats(&sa_temp, fn)) temp_nomem();
+ if (!stralloc_0(&sa_temp)) temp_nomem();
+ switch(control_readfile(&vdoms, sa_temp.s, 0))
+  {
+    case -1: temp_qmail(sa_temp.s);
+    case 0: if (!constmap_init(&mapvdoms, "", 0, 1)) temp_nomem();
+    case 1: if (!constmap_init(&mapvdoms, vdoms.s, vdoms.len, 1)) temp_nomem();
+  }
+
+	reciplen = str_len(recip);
+	atpos = str_rchr(recip, '@');
+
+	/* check against exception */
+	prepend = constmap(&mapvdoms, recip, reciplen);
+	if ((prepend != 0) && (*prepend == 0))
+		return 0;
+
+	/* test against virtual users */
+	for (i = 0; i < atpos; i++) {
+		if (recip[i] == '-') {
+			prepend = constmap(&mapvdoms, recip+i+1, reciplen-i-1);
+			if (prepend == 0) continue;
+			if (*prepend == 0) continue;
+			pos = str_len(prepend);
+			if (i != pos) continue;
+			if (str_diffn(recip, prepend, pos)) continue;
+			return pos + 1;
+		}
+	}
+	/* recip[i] == @ here. */
+
+	/* test against virtual domains */
+	for (i++; i <= reciplen; i++) {
+		if ((recip[i-1] == '@') || (recip[i] == '.') || (i == reciplen)) {
+			prepend = constmap(&mapvdoms, recip + i, reciplen - i);
+			if (prepend == 0) continue;
+			if (*prepend == 0) break;
+			pos = str_len(prepend);
+			if (str_diffn(recip, prepend, pos)) break;
+			if (recip[pos] != '-') break;
+			return pos + 1;
+		}
+	}
+
+	return 0;
+}
+
 void main(argc,argv)
 int argc;
 char **argv;
@@ -459,6 +544,8 @@
  int flagforwardonly;
  char *x;
 
+	int pos;
+
  umask(077);
  sig_pipeignore();
 
@@ -500,12 +587,15 @@
  if (!stralloc_cats(&envrecip,"@")) temp_nomem();
  if (!stralloc_cats(&envrecip,host)) temp_nomem();
 
- if (!stralloc_copy(&foo,&envrecip)) temp_nomem();
- if (!stralloc_0(&foo)) temp_nomem();
- if (!env_put2("RECIPIENT",foo.s)) temp_nomem();
+ if (!stralloc_copy(&envrecipz, &envrecip)) temp_nomem();
+ if (!stralloc_0(&envrecipz)) temp_nomem();
+ if (!env_put2("RECIPIENT", envrecipz.s)) temp_nomem();
 
  if (!stralloc_copys(&dtline,"Delivered-To: ")) temp_nomem();
- if (!stralloc_cat(&dtline,&envrecip)) temp_nomem();
+
+	pos = stripvdomprepend_local(envrecipz.s, "removeprependdt");
+ 	if (!stralloc_cats(&dtline, envrecipz.s + pos)) temp_nomem();
+
  for (i = 0;i < dtline.len;++i) if (dtline.s[i] == '\n') dtline.s[i] = '_';
  if (!stralloc_cats(&dtline,"\n")) temp_nomem();
 
@@ -593,16 +683,17 @@
    if (str_diff(sender,"#@[]"))
      if (qmeox("-owner") == 0)
       {
+       const char *stripped = local + stripvdomprepend_local(envrecipz.s, "removeprepend");
        if (qmeox("-owner-default") == 0)
 	{
-         if (!stralloc_copys(&ueo,local)) temp_nomem();
+         if (!stralloc_copys(&ueo, stripped)) temp_nomem();
          if (!stralloc_cats(&ueo,"-owner-@")) temp_nomem();
          if (!stralloc_cats(&ueo,host)) temp_nomem();
          if (!stralloc_cats(&ueo,"-@[]")) temp_nomem();
 	}
        else
 	{
-         if (!stralloc_copys(&ueo,local)) temp_nomem();
+         if (!stralloc_copys(&ueo, stripped)) temp_nomem();
          if (!stralloc_cats(&ueo,"-owner@")) temp_nomem();
          if (!stralloc_cats(&ueo,host)) temp_nomem();
 	}
