--- smtpserver/smtpserver.c.orig Mon Mar 24 16:41:09 1997
+++ smtpserver/smtpserver.c Mon Mar 24 18:57:22 1997
@@ -92,6 +92,9 @@
#include "syslog.h" /* we use local -- we should anyway */
#include "identuser.h"
+#ifdef USE_TRANSLATION
+# include "libtrans.h"
+#endif /* USE_TRANSLATION */
#ifndef SIGCHLD
#define SIGCHLD SIGCLD
@@ -203,6 +206,11 @@
int pid, routerpid;
FILE *logfp = NULL;
int D_alloc = 0;
+#ifdef USE_TRANSLATION
+int X_translation=0;
+int X_8bit=0;
+int X_settrrc=9;
+#endif /* USE_TRANSLATION */
jmp_buf jmpalarm; /* Return-frame for breaking smtpserver
when timeout hits.. */
@@ -444,7 +452,11 @@
exit(1);
}
/* optarg = NULL; */
+#ifdef USE_TRANSLATION
+ while ((c = getopt(argc, argv, "6aBd:ighl:np:L:M:P:R:s:VvX8")) != EOF) {
+#else /* USE_TRANSLATION */
while ((c = getopt(argc, argv, "6aBd:ighl:np:L:M:P:R:s:Vv")) != EOF) {
+#endif /* USE_TRANSLATION */
switch (c) {
case '6':
use_ipv6 = 1;
@@ -505,6 +517,14 @@
prversion("smtpserver");
exit(0);
break; /* paranoia */
+#ifdef USE_TRANSLATION
+ case 'X':
+ X_translation=1;
+ break;
+ case '8':
+ X_8bit=1;
+ break;
+#endif /* USE_TRANSLATION */
default:
fprintf(stderr,
"%s: Unknown option, c=%d ('%c')\n",progname,c,c);
@@ -525,6 +545,17 @@
}
#endif /* CHECK42INETD */
if (errflg || optind != argc) {
+#ifdef USE_TRANSLATION
+#ifdef USE_INET
+ fprintf(stderr,
+ "Usage: %s [-aBivgnVX8] [-s xx] [-L maxLoadAvg] [-M SMTPmaxsize] [-R rtrprog] [-p port#] [-P postoffice] [-l logfile]\n",
+ progname);
+#else /* !USE_INET */
+ fprintf(stderr,
+ "Usage: %s [-aBivgnVX8] [-s xx] [-L maxLoadAvg] [-M SMTPmaxsize] [-R rtrprog] [-P postoffice] [-l logfile]\n",
+ progname);
+#endif /* USE_INET */
+#else /* USE_TRANSLATION */
#ifdef USE_INET
fprintf(stderr,
"Usage: %s [-aBivgnV] [-s xx] [-L maxLoadAvg] [-M SMTPmaxsize] [-R rtrprog] [-p port#] [-P postoffice] [-l logfile]\n",
@@ -534,6 +565,7 @@
"Usage: %s [-aBivgnV] [-s xx] [-L maxLoadAvg] [-M SMTPmaxsize] [-R rtrprog] [-P postoffice] [-l logfile]\n",
progname);
#endif /* USE_INET */
+#endif /* USE_TRANSLATION */
exit(1);
}
@@ -2116,6 +2148,11 @@
long tell;
int VerboseCommand = 0;
+#ifdef USE_TRANSLATION
+ char lang[4];
+
+ lang[0]='\0';
+#endif
pid = getpid();
if (!logfp)
@@ -2167,8 +2204,21 @@
#endif
hostent = gethostbyaddr((void*)&SS->localsock.v4.sin_addr, 4, AF_INET );
- if (hostent)
+ if (hostent) {
strcpy(SS->myhostname, hostent->h_name);
+#ifdef USE_TRANSLATION
+ strncpy(lang,hostent->h_name,3);
+ lang[3]='\0';
+ X_settrrc=settrtab_byname(lang);
+ }
+ if (!(*lang) || (X_settrrc < 0)) {
+ /* we don't know our codetable, hush client away */
+ type(SS, 451, NULL, "Server could not setup translation.", NULL);
+ typeflush(SS);
+ sleep(1);
+ exit(0);
+#endif /* USE_TRANSLATION */
+ }
}
SS->reject_net = 0; /* Default for source net rejection */
@@ -2200,8 +2250,14 @@
SS->myhostname);
type(SS,553, NULL, "Ask HELP for our contact information.");
} else
+#ifdef USE_TRANSLATION
+ type(SS,220, NULL, "%s ZMailer Server %s ESMTP%s (%s) ready at %s",
+ SS->myhostname, VersionNumb, ident_flag ? "+IDENT":"",
+ *lang?lang:"nulltrans", cp);
+#else /* USE_TRANSLATION */
type(SS,220, NULL, "%s ZMailer Server %s ESMTP%s ready at %s",
SS->myhostname, VersionNumb, ident_flag ? "+IDENT":"", cp);
+#endif /* USE_TRANSLATION */
typeflush(SS);
SS->state = Hello;
@@ -3160,6 +3216,16 @@
/* XXX: HEADERS -> MIME-2 */
}
+#ifdef USE_TRANSLATION
+static void header_from_mime(buf, lenptr, maxlen)
+ char *buf;
+ int *lenptr;
+ int maxlen;
+{
+ /* XXX: HEADERS -> MIME-2 */
+}
+#endif /* USE_TRANSLATION */
+
/* Implement SMTP DATA filter */
/*
@@ -3254,6 +3320,31 @@
int from__err = 0;
int linecnt = 0;
int was8bit = 0;
+#ifdef USE_TRANSLATION
+ int wi;
+ char hdr_cte[4000],hdr_ct[4000];
+ int delay_cte = 0, delay_ct = 0, append_hdr_ct = 0, append_hdr_cte = 0;
+ int ct_is_text = 1;
+#define CTE_8BIT 0
+#define CTE_BASE64 1
+#define CTE_QP 2
+ int cte = CTE_8BIT;
+ int do_decode=0,do_translate=0;
+ int qp_chars=0,qp_hex=0;
+ int b64decoding=1,b64eod=0,b64i=0;
+ char b64c[4];
+ static char index_64[128] = {
+ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
+ 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1,
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
+ 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
+ -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
+ 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
+ };
+#define char64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)])
+#endif /* USE_TRANSLATION */
typeflush(SS);
@@ -3289,9 +3380,18 @@
if (state & O_) {
if (state == endstate) {
if (col > 0) {
+#ifdef USE_TRANSLATION
+ if (has8bit && !X_8bit)
+ header_to_mime(linebuf,&col,sizeof(linebuf));
+ else
+ header_from_mime(linebuf,&col,sizeof(linebuf));
+ for (wi=0;wi
mfp);
+#else /* USE_TRANSLATION */
if (has8bit)
header_to_mime(linebuf,&col,sizeof(linebuf));
fwrite(linebuf,1,col,SS->mfp);
+#endif /* USE_TRANSLATION */
}
return cnt;
}
@@ -3330,21 +3430,91 @@
*s != '\r' && *s != '\n')
break;
if (s == eol) { /* All-blank line */
+#ifdef USE_TRANSLATION
+ /* We have all info from the headers, time to make decision */
+ if (X_8bit && ct_is_text && cte)
+ do_decode=cte;
+ if (X_translation && X_8bit && ct_is_text && (X_settrrc == 0))
+ do_translate=1;
+ if (logfp)
+ fprintf(logfp,"%d#\t(8bit decode: %s, translate: %s) [%s%s,%s]\n",pid,
+ do_decode?"YES":"NO",do_translate?"YES":"NO",
+ X_translation?"-X ":"",
+ X_8bit?"-8":"",
+ ct_is_text?"text":"non-text");
+ /* write out content-type and content-transfer-encoding */
+ if (delay_ct) {
+ if (do_translate) {
+ /* Remove "charset=xxx". It is mismatching anyway */
+ char *p,*q,*r;
+ p=hdr_ct;
+ while (*p && (*p != ';')) p++; /* skip to attrs */
+ q=p;
+ while (*p == ';') { /* check attributes */
+ r=p+1;
+ while (*r && ((*r == ' ') || (*r == '\t'))) r++;
+ if (CISTREQN(r,"CHARSET=",8)) { /* skip it */
+ p++;
+ while (*p && (*p != ';') && (*p != '\n')) p++;
+ } else { /* copy it */
+ *(q++)=*(p++);
+ while (*p && (*p != ';')) *(q++)=*(p++);
+ }
+ }
+ while (*p) *(q++)=*(p++);
+ *q='\0';
+ }
+ fwrite(hdr_ct,1,strlen(hdr_ct),SS->mfp);
+ }
+ if (delay_cte) {
+ if (do_decode) {
+ /* Transfer-encoding changed to 8bit */
+ fputs("Content-Transfer-Encoding: 8bit\n",SS->mfp);
+ } else {
+ fwrite(hdr_cte,1,strlen(hdr_cte),SS->mfp);
+ }
+ }
+#endif /* USE_TRANSLATION */
if (col > 0)
fwrite(linebuf,1,col,SS->mfp);
break; /* Into the body processing */
}
++linecnt;
if (*linebuf == ' ' || *linebuf == '\t') {
+#ifdef USE_TRANSLATION
+ if (append_hdr_ct) {
+ strcat(hdr_ct,linebuf);
+ col = 0;
+ continue;
+ }
+ if (append_hdr_cte) {
+ strcat(hdr_cte,linebuf);
+ col = 0;
+ continue;
+ }
+ if (has8bit && !X_8bit)
+ header_to_mime(linebuf,&col,sizeof(linebuf));
+ else
+ header_from_mime(linebuf,&col,sizeof(linebuf));
+ if (col > 0)
+ for (wi=0;wimfp);
+#else /* USE_TRANSLATION */
if (has8bit)
header_to_mime(linebuf,&col,sizeof(linebuf));
- has8bit = 0;
if (col > 0)
fwrite(linebuf,1,col,SS->mfp);
+#endif /* USE_TRANSLATION */
+ has8bit = 0;
col = 0;
continue; /* continuation line.. */
}
+#ifdef USE_TRANSLATION
+ append_hdr_ct = 0;
+ append_hdr_cte = 0;
+#endif /* USE_TRANSLATION */
+
/* ================ PROCESS THE HEADERS! ================ */
if (CISTREQN(linebuf,"Subject:",8)) {
insubject = 1;
@@ -3357,6 +3527,62 @@
has8bitsum += has8bit;
}
}
+
+ if (CISTREQN(linebuf,"Precedence:",11)) {
+ s = linebuf+11;
+ while (*s == ' ' || *s == '\t') ++s;
+ if ((eol - s) < 4) continue; /* Hmm.. */
+ if (CISTREQN("junk",s,4)) {
+ mail_priority = _MAILPRIO_JUNK;
+ } else if (CISTREQN("bulk",s,4)) {
+ mail_priority = _MAILPRIO_BULK;
+ }
+ }
+
+#ifdef USE_TRANSLATION
+ if (X_translation && (X_settrrc == 0)) {
+ if (CISTREQN(linebuf,"Content-Transfer-Encoding:",26)) {
+ if (1) {
+ strcpy(hdr_cte,linebuf);
+ delay_cte = 1;
+ append_hdr_cte = 1;
+ col=0;
+ has8bit = 0;
+ s = linebuf+26;
+ while (*s == ' ' || *s == '\t') ++s;
+ if ((eol - s) < 4) continue; /* Hmm.. */
+ if (CISTREQN("8bit",s,4)) {
+ cte=CTE_8BIT;
+ } else if (CISTREQN("base64",s,6)) {
+ cte=CTE_BASE64;
+ } else if (CISTREQN("quoted-printable",s,16)) {
+ cte=CTE_QP;
+ }
+ continue; /* do not write out this one */
+ }
+ } else if (CISTREQN(linebuf,"Content-Type:",13)) {
+ if (1) {
+ strcpy(hdr_ct,linebuf);
+ delay_ct = 1;
+ append_hdr_ct = 1;
+ col=0;
+ has8bit = 0;
+ s = linebuf+13;
+ while (*s == ' ' || *s == '\t') ++s;
+ if ((eol - s) < 10) continue; /* Hmm.. */
+#ifdef PARANOID_TRANSLATION
+ if (CISTREQN("text",s,4)) {
+ ct_is_text=1;
+ } else {
+ ct_is_text=0;
+ }
+#endif /* PARANOID_TRANSLATION */
+ continue; /* do not write out this one */
+ }
+ }
+ }
+#endif /* USE_TRANSLATION */
+
if (linecnt == 1 && (strncmp("From ",linebuf,5)==0 ||
strncmp(">From ",linebuf,6)==0)) {
#if 0
@@ -3368,25 +3594,24 @@
has8bit = 0;
continue;
}
+#ifdef USE_TRANSLATION
+ if (has8bit && !X_8bit)
+ header_to_mime(linebuf,&col,sizeof(linebuf));
+ else
+ header_from_mime(linebuf,&col,sizeof(linebuf));
+ /* Write the line out */
+ if (col > 0)
+ for (wi=0;wimfp);
+#else /* USE_TRANSLATION */
if (has8bit)
header_to_mime(linebuf,&col,sizeof(linebuf));
- has8bit = 0;
/* Write the line out */
if (col > 0)
fwrite(linebuf,1,col,SS->mfp);
- col = 0;
-
+#endif /* USE_TRANSLATION */
has8bit = 0;
- if (CISTREQN(linebuf,"Precedence:",11)) {
- s = linebuf+11;
- while (*s == ' ' || *s == '\t') ++s;
- if ((eol - s) < 4) continue; /* Hmm.. */
- if (CISTREQN("junk",s,4)) {
- mail_priority = _MAILPRIO_JUNK;
- } else if (CISTREQN("bulk",s,5)) {
- mail_priority = _MAILPRIO_BULK;
- }
- }
+ col = 0;
}
if (logfp && verbose)
fprintf(logfp,"%d#\t(mail_priority=%d)\n",pid,mail_priority);
@@ -3417,8 +3642,67 @@
putc((state>>8), SS->mfp);
state = (char)state;
}
- if (!ferror(SS->mfp))
+ if (!ferror(SS->mfp)) {
+#ifdef USE_TRANSLATION
+ if (do_decode == CTE_QP) {
+ if (!qp_chars && c == '=') {
+ qp_chars = 2;
+ qp_hex = 0;
+ continue;
+ }
+ if (qp_chars && c == '\n') {
+ qp_chars = 0;
+ continue;
+ }
+ if (qp_chars == 2 && (c == ' ' || c == '\t')) {
+ continue;
+ }
+ if (qp_chars && ((c >= '0' && c <= '9') ||
+ (c >= 'A' && c <= 'F') ||
+ (c >= 'a' && c <= 'f'))) {
+ qp_hex <<= 4;
+ if (c >= '0' && c <= '9')
+ qp_hex += (c - '0');
+ if (c >= 'A' && c <= 'F')
+ qp_hex += (c - 'A' + 10);
+ if (c >= 'a' && c <= 'f')
+ qp_hex += (c - 'a' + 10);
+ --qp_chars;
+ if (!qp_chars) c = qp_hex;
+ else continue;
+ } else if (qp_chars)
+ qp_chars = 0;
+ } else if (do_decode == CTE_BASE64) {
+ if (b64decoding) {
+ if ((c == ' ') || (c == '\t') ||
+ (c == '\n') || (c == '\r'))
+ continue;
+ b64c[b64i++]=char64(c);
+ if (c == '=') {
+ b64eod=1;
+ continue;
+ }
+ if (b64i < 2) continue;
+ if (b64i == 2) {
+ c=(b64c[0]<<2) |
+ ((b64c[1]&0x30)>>4);
+ } else if (b64i == 3) {
+ c=((b64c[1]&0x0f)<<4) |
+ ((b64c[2]&0x3c)>>2);
+ } else {
+ c=(b64c[2]<<6) |
+ b64c[3];
+ b64i=0;
+ if (b64eod) b64decoding=0;
+ }
+ }
+ }
+ if (do_translate)
+ putc(TR_IN(c), SS->mfp);
+ else
+#endif /* USE_TRANSLATION */
putc(c, SS->mfp);
+ }
}
typeflush(SS);
return cnt;