--- qmail2bbs.c.112103 Fri Nov 21 16:32:46 2003
+++ qmail2bbs.c Sun Nov 23 21:51:41 2003
@@ -5,6 +5,7 @@
*/
#include "bbs.h"
+#include "bbs_mime.c"
#define BLOCKFILE ".blockmail"
@@ -90,9 +91,9 @@
}
int
-append_mail(fin, sender1, sender, userid, title, received)
+append_mail(fin, sender1, sender, userid, title, received, boundary)
FILE *fin;
- char *userid, *sender1, *sender, *title, *received;
+ char *userid, *sender1, *sender, *title, *received, *boundary;
{
struct fileheader newmessage;
char fname[512], buf[256];
@@ -153,8 +154,154 @@
if (received != NULL && received[0] != '\0')
fprintf(fout, "来 源: %-.70s\n", received);
fprintf(fout, "日 期: %s\n", ctime(&tmp_time));
- while (fgets(buf, 255, fin) != NULL)
- fputs(buf, fout);
+ if (!boundary[0])
+ while (fgets(buf, 255, fin) != NULL) fputs(buf, fout);
+ else {
+ #define READ if (!fgets(buf, 255, fin)) { err=1; break;}
+ #define WRITE(data, size) FileSize += fwrite(data, 1, size, fout); totalsize += size;
+ #define CHECK if ((totalsize>MAXMAILSIZE)||(number-firstText>MAXATTACHMENTCOUNT)) err=2; if (err) break;
+ int err;
+ int ContentType, ContentEncoding;
+ int number;
+ int block;
+ char FileName[256];
+ char Boundary[256];
+ int FileSize;
+ char data[256];
+ int totalsize;
+ int firstText;
+ err = 0;
+ buf[0] = 0;
+ totalsize = 0;
+ firstText = 0;
+ do {
+ READ
+ } while (!strstr(buf, boundary));
+ number = 0;
+ do {
+ READ
+ } while (0);
+ do {
+ ContentType = 0;
+ ContentEncoding = 0;
+ number++;
+ FileName[0]=0;
+ do {
+ char* tag;
+ if (tag=strstr(buf, ": ")) {
+ tag[0]=0; tag+=2;
+ if (!strcasecmp(buf, "Content-Type")) {
+ char* t;
+ if (t=strchr(tag, ';')) *t=0;
+ if (!strcasecmp(tag, "text/plain")) ContentType = 1;
+ else if (!strcasecmp(tag, "text/html")) ContentType = 2;
+ else if (!strcasecmp(tag, "multipart/related")) ContentType = 3;
+ } else if (!strcasecmp(buf, "Content-Transfer-Encoding")) {
+ if (strstr(tag, "8bit")) ContentEncoding = 1;
+ else if (strstr(tag, "quoted-printable")) ContentEncoding = 2;
+ else if (strstr(tag, "base64")) ContentEncoding = 3;
+ }
+ } else if (tag=strstr(buf, "filename=\"")) {
+ char* t;
+ tag+=10;
+ if (t=strchr(tag, '"')) *t=0;
+ strcpy(FileName, tag);
+ } else if ((ContentType==3) && (tag=strstr(buf, "boundary=\""))) {
+ char* t;
+ tag+=10;
+ if (t=strchr(tag, '\"')) *t=0;
+ while (tag[strlen(tag)-1]<27) tag[strlen(tag)-1]=0;
+ strcpy(Boundary, tag);
+ }
+ READ
+ } while (strlen(buf)>2); /*(strcspn(buf, " \r\n")<strlen(buf));*/
+ CHECK
+ do {
+ READ
+ } while (strlen(buf)<2);
+ CHECK
+ if (!FileName[0])
+ switch (ContentType) {
+ case 1:
+ strcpy(FileName, "noname.txt");
+ break;
+ case 2:
+ strcpy(FileName, "noname.htm");
+ break;
+/* case 3:
+ strcpy(FileName, "noname.mht");
+ break;
+*/ default:
+ strcpy(FileName, "noname");
+ }
+ block = 0;
+ FileSize = 0;
+ do {
+ if ((ContentType==1)&&(number==1)) {
+ firstText = 1;
+ switch (ContentEncoding) {
+ case 1:
+ fputs(buf, fout);
+ break;
+ case 2:
+ qpdec(buf, data);
+ fputs(data, fout);
+ break;
+ case 3:
+ data[b64dec(buf, data)]=0;
+ fputs(data, fout);
+ break;
+ default:
+ fputs(buf, fout);
+ }
+
+ } else {
+ if (!newmessage.attachment) newmessage.attachment=ftell(fout);
+ if (!FileSize) {
+ fwrite(ATTACHMENT_PAD, 1, ATTACHMENT_SIZE, fout);
+ fwrite(FileName, 1, strlen(FileName)+1, fout);
+ fwrite(&FileSize, 1, 4, fout);
+ totalsize += 12+strlen(FileName)+1;
+ }
+ switch (ContentEncoding) {
+ case 1:
+ WRITE(buf, strlen(buf));
+ break;
+ case 2:
+ qpdec(buf, data);
+ WRITE(data, strlen(data));
+ break;
+ case 3:
+ WRITE(data, b64dec(buf, data));
+ break;
+ default:
+/* if ((!FileSize)&&(ContentType==3)) {
+ WRITE("Content-Type: multipart/related;\n", 33);
+ WRITE(" boundary=\"", 16);
+ WRITE(Boundary, strlen(Boundary));
+ WRITE("\";\n",3);
+ WRITE(" type=\"multipart/alternative\"\n\n", 36);
+ }
+*/ WRITE(buf, strlen(buf));
+ }
+ }
+ CHECK
+ READ
+ } while (!strstr(buf, boundary));
+ if ((ContentType!=1)||(number!=1)) {
+ fseek(fout, -FileSize-4, SEEK_CUR);
+ FileSize = htonl(FileSize);
+ fwrite(&FileSize, 1, 4, fout);
+ fseek(fout, 0, SEEK_END);
+ }
+ CHECK
+ READ
+ } while (!feof(fin));
+ /*if (err==2) fputs("Mail too long or too many attachments!", fout);*/
+ #undef READ
+ #undef WRITE
+ #undef CHECK
+ }
fclose(fout);
}
@@ -211,7 +358,7 @@
/* argv[ 2 ] is userid in bbs */
/* argv[ 3 ] is the mail title */
/* argv[ 4 ] is the message-id */
- if (argc != 3)
+ if (argc < 3)
{
char *p = (char *) rindex(argv[0], '/');
@@ -256,5 +403,7 @@
return -2;
strcpy(receiver, argv[2]);
- return append_mail(stdin, nettyp, sender, receiver, getenv("TITLE"), getenv("MSGID"));
+ return append_mail(stdin, nettyp, sender, receiver, getenv("TITLE"), getenv("MSGID"), argv[3]);
}
+
+
【 在 freewizard@happynet.org (Enter HAPPY :: Reloaded :: Revolution) 的大作中提到: 】
: 发信人: freewizard (Enter HAPPY :: Reloaded :: Revolution), 信区: sysop
: 标 题: [功能测试] 带附件的MIME邮件收发
: 发信站: HAPPY (Sun Nov 23 17:21:08 2003), 转信
: 使用方法
: 将带有附件的邮件发往 用户ID@happynet.org
: 当前限制
: 邮件大小2M
: 编码支持:8bit quoted-printable base64
--
FROM 202.38.124.252
static const char* to_b64 =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/* encode 72 characters per line */
#define CHARS_PER_LINE 72
char* b64enc(char* buff, int size, char* string)
{
int div = size / 3;
int rem = size % 3;
int chars = div*4 + rem + 1;
int newlines = (chars + CHARS_PER_LINE - 1) / CHARS_PER_LINE;
const byte* data = buff;
if (string)
{
register char* buf = string;
chars = 0;
/*@+charindex@*/
while (div > 0)
{
buf[0] = to_b64[ (data[0] >> 2) & 0x3f];
buf[1] = to_b64[((data[0] << 4) & 0x30) + ((data[1] >> 4) & 0xf)];
buf[2] = to_b64[((data[1] << 2) & 0x3c) + ((data[2] >> 6) & 0x3)];
buf[3] = to_b64[ data[2] & 0x3f];
data += 3;
buf += 4;
div--;
chars += 4;
if (chars == CHARS_PER_LINE)
{
chars = 0;
*(buf++) = '\r';
*(buf++) = '\n';
}
}
switch (rem)
{
case 2:
buf[0] = to_b64[ (data[0] >> 2) & 0x3f];
buf[1] = to_b64[((data[0] << 4) & 0x30) + ((data[1] >> 4) & 0xf)];
buf[2] = to_b64[ (data[1] << 2) & 0x3c];
buf[3] = '=';
buf += 4;
chars += 4;
break;
case 1:
buf[0] = to_b64[ (data[0] >> 2) & 0x3f];
buf[1] = to_b64[ (data[0] << 4) & 0x30];
buf[2] = '=';
buf[3] = '=';
buf += 4;
chars += 4;
break;
}
/*@=charindex@*/
/* *(buf++) = '\n'; This would result in a buffer overrun */
*buf = '\0';
}
return string;
}
int b64dec(const char* string, char* buff)
{
int size;
if (string)
{
int length = strlen(string);
/* do a format verification first */
if (length > 0)
{
int count = 0, rem = 0;
const char* tmp = string;
while (length > 0)
{
int skip = strspn(tmp, to_b64);
count += skip;
length -= skip;
tmp += skip;
if (length > 0)
{
int i, vrfy = strcspn(tmp, to_b64);
for (i = 0; i < vrfy; i++)
{
if (isspace(tmp[i]))
continue;
if (tmp[i] == '=')
{
/* we should check if we're close to the end of the string */
rem = count % 4;
/* rem must be either 2 or 3, otherwise no '=' should be here */
if (rem < 2)
return 0;
/* end-of-message recognized */
break;
}
else
{
/* Transmission error; RFC tells us to ignore this, but:
* - the rest of the message is going to even more corrupt since we're sliding bits out of place
* If a message is corrupt, it should be dropped. Period.
*/
return 0;
}
}
length -= vrfy;
tmp += vrfy;
}
}
size = (count / 4) * 3 + (rem ? (rem - 1) : 0);
if (buff)
{
if (count > 0)
{
int i, qw = 0, tw = 0;
byte* data = buff;
length = strlen(tmp = string);
for (i = 0; i < length; i++)
{
register char ch = string[i];
register byte bits;
if (isspace(ch))
continue;
bits = 0;
if ((ch >= 'A') && (ch <= 'Z'))
{
bits = (byte) (ch - 'A');
}
else if ((ch >= 'a') && (ch <= 'z'))
{
bits = (byte) (ch - 'a' + 26);
}
else if ((ch >= '0') && (ch <= '9'))
{
bits = (byte) (ch - '0' + 52);
}
else if (ch=='+') {
bits = 62;
}
else if (ch=='/') {
bits = 63;
}
else if (ch == '=')
break;
switch (qw++)
{
case 0:
data[tw+0] = (bits << 2) & 0xfc;
break;
case 1:
data[tw+0] |= (bits >> 4) & 0x03;
data[tw+1] = (bits << 4) & 0xf0;
break;
case 2:
data[tw+1] |= (bits >> 2) & 0x0f;
data[tw+2] = (bits << 6) & 0xc0;
break;
case 3:
data[tw+2] |= bits & 0x3f;
break;
}
if (qw == 4)
{
qw = 0;
tw += 3;
}
}
}
}
}
}
return size;
}
#define SKIP '\202'
#define NOSKIP 'A'
const char hexmap[] = {
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ,
8 , 9 , SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, 10, 11, 12, 13, 14, 15, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP
};
int qpdec(const char* string, char* buff)
{
char *s;
char *result = buff;
int i;
char mid[3];
bool ok = true;
s = string;
while (*s != '\0') //loop through the entire string...
{
if (*s == '=') //woops, needs to be decoded...
{
for (i = 0; i < 3; i++) //is s more than 3 chars long...
{
if (s[i] == '\0')
{
return 0;
}
}
s++; //move past the "="
//let's put the hex part into mid...
for (i = 0; i < 2; i++)
{
if (hexmap[s[i]] == SKIP)
{
//we have an error, or a linebreak, in the encoding...
ok = false;
if (s[i] == '\r' && s[i + 1] == '\n')
{
s += 2;
//*(result++) = '\r';
//*(result++) = '\n';
break;
}
else
{
//we have an error in the encoding...
//s--;
}
}
mid[i] = s[i];
}
//now we just have to convert the hex string to an char...
if (ok)
{
int m;
s += 2;
m = hexmap[mid[0]];
m <<= 4;
m |= hexmap[mid[1]];
*(result++) = m;
}
}
else
{
if (*s != '\0') *(result++) = *(s++);
}
}
*(result++)=0;
return strlen(string);
}
【 在 freewizard (Enter HAPPY :: Reloaded :: Revolution) 的大作中提到: 】
: --- mailgate.pl.031122 Sun Nov 23 22:25:56 2003
: +++ mailgate.pl Sun Nov 23 22:27:17 2003
: @@ -46,7 +46,7 @@
: $_ = $MAIL[$index];
: last if ( $_ eq "\n" );
: chop;
: - if (/^(\S+): (.*)$/) {
: + if (/^(?:(\S+): ([^;]*))?;?\s*(?:(\S+)="(.*)")?(?:(\S+)=(.*))?$/) {
: $hhh = $Header{$1};
: if ( $1 eq "Received" && $hhh ) {
: $tmp = "$2";
: ...................
--
FROM yesterday