tnew - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
LICENSE
---
commit 20bd3ca2e2bc7c1b284a5a52e72a32530529d234
parent 0e6fee11c89b146aa5419bbdf26514bc34bdaf81
Author: rsc 
Date:   Sun,  9 Apr 2006 00:24:28 +0000

new

Diffstat:
  M src/cmd/upas/vf/mkfile              |       6 +++---
  A src/cmd/upas/vf/unvf.c              |     156 +++++++++++++++++++++++++++++++
  M src/cmd/upas/vf/vf.c                |      24 ++++++++++++++++--------

3 files changed, 175 insertions(+), 11 deletions(-)
---
diff --git a/src/cmd/upas/vf/mkfile b/src/cmd/upas/vf/mkfile
t@@ -1,8 +1,8 @@
 <$PLAN9/src/mkhdr
 
-TARG=vf
+TARG=vf unvf
 
-OFILES=vf.$O\
+OFILES=
 
 LIB=../common/libcommon.a\
 
t@@ -16,5 +16,5 @@ UPDATE=\
         $HFILES\
         ${OFILES:%.$O=%.c}\
 
-<$PLAN9/src/mkone
+<$PLAN9/src/mkmany
 CFLAGS=$CFLAGS -I../common
diff --git a/src/cmd/upas/vf/unvf.c b/src/cmd/upas/vf/unvf.c
t@@ -0,0 +1,156 @@
+/*
+ * For decoding the files that get passed to validateattachment.
+ * NOT a general mime decoder.
+ */
+#include 
+#include 
+#include 
+
+enum { None, Base64, Quoted };
+static int decquoted(char *out, char *in, char *e);
+
+void
+main(void)
+{
+        Biobuf b, b1;
+        char *p, *encoding;
+        int e, len;
+        
+        Binit(&b, 0, OREAD);
+        Binit(&b1, 1, OWRITE);
+        
+        /* header */
+        encoding = nil;
+        while((p = Brdstr(&b, '\n', 1)) != nil){
+                if(p[0] == 0)
+                        break;
+                if(strncmp(p, "Content-Transfer-Encoding: ", 27) == 0)
+                        encoding = strdup(p+27);
+                free(p);
+        }
+
+        e = None;
+        if(encoding == nil)
+                e = None;
+        else if(strcmp(encoding, "base64") == 0)
+                e = Base64;
+        else if(strcmp(encoding, "quoted-printable") == 0)
+                e = Quoted;
+
+        while((p = Brdstr(&b, '\n', 0)) != nil){
+                if(strncmp(p, "--", 2) == 0 && e != None)
+                        break;
+                len = strlen(p);
+                switch(e){
+                case None:
+                        break;
+                case Base64:
+                        len = dec64((uchar*)p, len, p, len);
+                        break;
+                case Quoted:
+                        len = decquoted(p, p, p+len);
+                        break;
+                }
+                Bwrite(&b1, p, len);
+                free(p);
+        }
+        exits(0);
+}
+
+/*
+ *  decode quoted 
+ */
+enum
+{
+        Self=        1,
+        Hex=        2
+};
+uchar        tableqp[256];
+
+static void
+initquoted(void)
+{
+        int c;
+
+        memset(tableqp, 0, 256);
+        for(c = ' '; c <= '<'; c++)
+                tableqp[c] = Self;
+        for(c = '>'; c <= '~'; c++)
+                tableqp[c] = Self;
+        tableqp['\t'] = Self;
+        tableqp['='] = Hex;
+}
+
+static int
+hex2int(int x)
+{
+        if(x >= '0' && x <= '9')
+                return x - '0';
+        if(x >= 'A' && x <= 'F')
+                return (x - 'A') + 10;
+        if(x >= 'a' && x <= 'f')
+                return (x - 'a') + 10;
+        return 0;
+}
+
+static char*
+decquotedline(char *out, char *in, char *e)
+{
+        int c, soft;
+
+        /* dump trailing white space */
+        while(e >= in && (*e == ' ' || *e == '\t' || *e == '\r' || *e == '\n'))
+                e--;
+
+        /* trailing '=' means no newline */
+        if(*e == '='){
+                soft = 1;
+                e--;
+        } else
+                soft = 0;
+
+        while(in <= e){
+                c = (*in++) & 0xff;
+                switch(tableqp[c]){
+                case Self:
+                        *out++ = c;
+                        break;
+                case Hex:
+                        c = hex2int(*in++)<<4;
+                        c |= hex2int(*in++);
+                        *out++ = c;
+                        break;
+                }
+        }
+        if(!soft)
+                *out++ = '\n';
+        *out = 0;
+
+        return out;
+}
+
+static int
+decquoted(char *out, char *in, char *e)
+{
+        char *p, *nl;
+
+        if(tableqp[' '] == 0)
+                initquoted();
+
+        p = out;
+        while((nl = strchr(in, '\n')) != nil && nl < e){
+                p = decquotedline(p, in, nl);
+                in = nl + 1;
+        }
+        if(in < e)
+                p = decquotedline(p, in, e-1);
+
+        /* make sure we end with a new line */
+        if(*(p-1) != '\n'){
+                *p++ = '\n';
+                *p = 0;
+        }
+
+        return p - out;
+}
+
diff --git a/src/cmd/upas/vf/vf.c b/src/cmd/upas/vf/vf.c
t@@ -5,6 +5,11 @@
 #include "common.h"
 #include 
 
+enum {
+        Accept = 0xA,
+        Discard = 0xD,
+};
+
 Biobuf in;
 Biobuf out;
 
t@@ -400,12 +405,12 @@ savetmp(Part *p)
         char buf[40], *name;
         int fd;
         
-        strcpy(buf, "/tmp/vf.XXXXXXXXXXX");
-        name = mktemp(buf);
-        if((fd = create(name, OWRITE|OEXCL, 0666)) < 0){
+        strcpy(buf, "/var/tmp/vf.XXXXXXXXXXX");
+        if((fd = mkstemp(buf)) < 0){
                 fprint(2, "error creating temporary file: %r\n");
                 refuse();
         }
+        name = buf;
         close(fd);
         if(save(p, name) < 0){
                 fprint(2, "error saving temporary file: %r\n");
t@@ -433,10 +438,13 @@ runchecker(Part *p)
         int pid;
         char *name;
         Waitmsg *w;
+        static char *val;
         
-        if(access("/mail/lib/validateattachment", AEXEC) < 0)
+        if(val == nil)
+                val = unsharp("#9/mail/lib/validateattachment");
+        if(val == nil || access(val, AEXEC) < 0)
                 return 0;
-        
+
         name = savetmp(p);
         fprint(2, "run checker %s\n", name);
         switch(pid = fork()){
t@@ -444,7 +452,7 @@ runchecker(Part *p)
                 sysfatal("fork: %r");
         case 0:
                 dup(2, 1);
-                execl("/mail/lib/validateattachment", "validateattachment", name, nil);
+                execl(val, "validateattachment", name, nil);
                 _exits("exec failed");
         }
 
t@@ -462,11 +470,11 @@ runchecker(Part *p)
         }
         if(p->filename)
                 name = s_to_c(p->filename);
-        if(strstr(w->msg, "discard")){
+        if(atoi(w->msg) == Discard){
                 syslog(0, "mail", "vf validateattachment rejected %s", name);
                 refuse();
         }
-        if(strstr(w->msg, "accept")){
+        if(atoi(w->msg) == Accept){
                 syslog(0, "mail", "vf validateattachment accepted %s", name);
                 return 1;
         }