aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/upas/vf/unvf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/upas/vf/unvf.c')
-rw-r--r--src/cmd/upas/vf/unvf.c156
1 files changed, 156 insertions, 0 deletions
diff --git a/src/cmd/upas/vf/unvf.c b/src/cmd/upas/vf/unvf.c
new file mode 100644
index 00000000..92af6bfb
--- /dev/null
+++ b/src/cmd/upas/vf/unvf.c
@@ -0,0 +1,156 @@
+/*
+ * For decoding the files that get passed to validateattachment.
+ * NOT a general mime decoder.
+ */
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+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;
+}
+