You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
790 lines
17 KiB
790 lines
17 KiB
// Folder class - provides a wrapper of c-client |
|
#include <stdio.h> |
|
#include "mclass.h" |
|
|
|
static const char *enctable[] = ENCODING; |
|
static const char *bodytype[] = BODYTYPE; |
|
|
|
struct FileType { |
|
const char *ext; |
|
short type; |
|
const char *subtype; |
|
const char *charset; |
|
}; |
|
|
|
const struct FileType defaultTextFileType = |
|
{ 0, TYPETEXT, "PLAIN", "US-ASCII" }; |
|
|
|
const struct FileType defaultBinFileType = |
|
{ 0, TYPEAPPLICATION, "OCTET-STREAM", 0 }; |
|
|
|
const struct FileType fInfo[] = { |
|
{ "Z", TYPEAPPLICATION, "X-COMPRESS", 0 }, |
|
{ "ai", TYPEAPPLICATION, "PostScript", 0 }, |
|
{ "aif", TYPEAUDIO, "X-AIFF", 0 }, |
|
{ "aifc", TYPEAUDIO, "X-AIFF", 0 }, |
|
{ "aiff", TYPEAUDIO, "X-AIFF", 0 }, |
|
{ "au", TYPEAUDIO, "BASIC", 0 }, |
|
{ "avi", TYPEVIDEO, "X-MSVIDEO", 0 }, |
|
{ "cpio", TYPEAPPLICATION, "X-CPIO", 0 }, |
|
{ "csh", TYPEAPPLICATION, "X-CSH", 0 }, |
|
{ "dvi", TYPEAPPLICATION, "X-DVI", 0 }, |
|
{ "eps", TYPEAPPLICATION, "POSTSCRIPT", 0 }, |
|
{ "fif", TYPEAPPLICATION, "FRACTALS", 0 }, |
|
{ "gif", TYPEIMAGE, "GIF", 0 }, |
|
{ "gtar", TYPEAPPLICATION, "X-GTAR", 0 }, |
|
{ "gz", TYPEAPPLICATION, "X-GZIP", 0 }, |
|
{ "htm", TYPETEXT, "HTML", "US-ASCII" }, |
|
{ "html", TYPETEXT, "HTML", "US-ASCII" }, |
|
{ "ief", TYPEIMAGE, "IEF", 0 }, |
|
{ "jpg", TYPEIMAGE, "JPEG", 0 }, |
|
{ "latex", TYPEAPPLICATION, "X-LATEX", 0 }, |
|
{ "man", TYPEAPPLICATION, "X-TROFF-MAN", 0 }, |
|
{ "me", TYPEAPPLICATION, "X-TROFF-ME", 0 }, |
|
{ "mov", TYPEVIDEO, "QUICKTIME", 0 }, |
|
{ "movie", TYPEVIDEO, "X-SGI-MOVIE", 0 }, |
|
{ "mpe", TYPEVIDEO, "MPEG", 0 }, |
|
{ "mpeg", TYPEVIDEO, "MPEG", 0 }, |
|
{ "mpg", TYPEVIDEO, "MPEG", 0 }, |
|
{ "ms", TYPEAPPLICATION, "X-TROFF-MS", 0 }, |
|
{ "pbm", TYPEIMAGE, "X-PORTABLE-BITMAP", 0 }, |
|
{ "pgm", TYPEIMAGE, "X-PORTABLE-GRAYMAP", 0 }, |
|
{ "png", TYPEIMAGE, "PNG", 0 }, |
|
{ "pnm", TYPEIMAGE, "X-PORTABLE-ANYMAP", 0 }, |
|
{ "ppm", TYPEIMAGE, "X-PORTABLE-PIXMAP", 0 }, |
|
{ "ps", TYPEAPPLICATION, "POSTSCRIPT", 0 }, |
|
{ "qt", TYPEVIDEO, "QUCIKTIME", 0 }, |
|
{ "ras", TYPEIMAGE, "X-CMU-RASTER", 0 }, |
|
{ "rft", TYPEAPPLICATION, "X-RTF", 0 }, |
|
{ "rgb", TYPEIMAGE, "X-RGB", 0 }, |
|
{ "sgml", TYPETEXT, "SGML", "US-ASCII" }, |
|
{ "sh", TYPEAPPLICATION, "X-SH", 0 }, |
|
{ "shar", TYPEAPPLICATION, "X-SHAR", 0 }, |
|
{ "snd", TYPEAUDIO, "BASIC", 0 }, |
|
{ "t", TYPEAPPLICATION, "X-TROFF", 0 }, |
|
{ "tar", TYPEAPPLICATION, "X-TAR", 0 }, |
|
{ "tcl", TYPEAPPLICATION, "X-TCL", 0 }, |
|
{ "tex", TYPEAPPLICATION, "X-TEX", 0 }, |
|
{ "texi", TYPEAPPLICATION, "X-TEXINFO", 0 }, |
|
{ "texinfo", TYPEAPPLICATION, "X-TEXINFO", 0 }, |
|
{ "text", TYPETEXT, "PLAIN", "US-ASCII" }, |
|
{ "tif", TYPEIMAGE, "TIFF", 0 }, |
|
{ "tiff", TYPEIMAGE, "TIFF", 0 }, |
|
{ "tr", TYPEAPPLICATION, "X-TROFF", 0 }, |
|
{ "troff", TYPEAPPLICATION, "X-TROFF", 0 }, |
|
{ "txt", TYPETEXT, "PLAIN", "US-ASCII" }, |
|
{ "vrml", TYPEMODEL, "VRML", 0 }, |
|
{ "wav", TYPEAUDIO, "X-WAV", 0 }, |
|
{ "xbm", TYPEIMAGE, "X-XBITMAP", 0 }, |
|
{ "xpm", TYPEIMAGE, "X-XPIXMAP", 0 }, |
|
{ "xwd", TYPEIMAGE, "X-XWINDOWDUMP", 0 }, |
|
{ "zip", TYPEAPPLICATION, "X-ZIP-COMPRESSED", 0 } |
|
}; |
|
|
|
#define NUMTYPES 60 |
|
|
|
/* This must be called before any attempt to access the wrapper class! */ |
|
void initCC() |
|
{ |
|
#include <linkage.c> |
|
} |
|
|
|
long createFolder(char *mbox) |
|
{ |
|
return mail_create(0, mbox); |
|
} |
|
|
|
/* Folder::Folder(char *mbox) |
|
{ |
|
}*/ |
|
|
|
long Folder::open(const char *s) |
|
{ |
|
char file[L_FILE]; |
|
|
|
strcpy(file, s); |
|
return (stream = mail_open(0, file, NIL))? T : NIL; |
|
} |
|
|
|
long Folder::create(const char *mbox) |
|
{ |
|
char file[L_FILE]; |
|
|
|
strcpy(file, mbox); |
|
if (mail_create(0, file)) |
|
if (open(file)) |
|
return T; |
|
return NIL; |
|
} |
|
|
|
Folder::~Folder() |
|
{ |
|
if (stream) |
|
close(0); |
|
} |
|
|
|
void Folder::close(long ops) |
|
{ |
|
stream = mail_close_full(stream, ops); |
|
} |
|
|
|
long Folder::status(long ops) |
|
{ |
|
return mail_status(stream, MBOX(stream), ops); |
|
} |
|
|
|
Message *Folder::getMsg(ULONG msgno) |
|
{ |
|
if (msgno < 1 || msgno > stream->nmsgs) |
|
return 0; |
|
return new Message(stream, msgno); |
|
} |
|
|
|
// moves a local message to a remote mailbox |
|
/*long Folder::moveDiff(char *mbox, ULONG msgno) |
|
{ |
|
long v; |
|
char *a; |
|
char *b; |
|
char *msg; |
|
STRING s; |
|
|
|
a = cpystr(fetchHeader(msgno)); |
|
b = cpystr(fetchText(msgno)); |
|
msg = (char *)malloc(strlen(a) + strlen(b) + 1); |
|
strcat(msg, a); |
|
strcat(msg, b); |
|
mail_string_init(&s, msg, strlen(msg)); |
|
mail_create(0, mbox); |
|
v = mail_append(0, mbox, &s); |
|
free(a); |
|
free(b); |
|
free(msg); |
|
return 1; |
|
}*/ |
|
|
|
long Folder::rename(const char *mbox) |
|
{ |
|
char file[L_FILE]; |
|
|
|
strcpy(file, mbox); |
|
return mail_rename(stream, MBOX(stream), file); |
|
} |
|
|
|
long Folder::remove() |
|
{ |
|
return mail_delete(stream, MBOX(stream)); |
|
} |
|
|
|
long Folder::putMsg(Message *msg) |
|
{ |
|
STRING bs; |
|
ULONG len; |
|
char *b; |
|
long rv; |
|
|
|
printf("putMsg()\n"); |
|
if (!(b = msg->toSTRING(&len))) { |
|
printf("toSTRING failed\n"); |
|
return NIL; |
|
} |
|
//printf("%.*s\n\nLength = %ld",(int)len, b, (int)len); |
|
INIT(&bs, mail_string, (void *)b, len); |
|
rv = mail_append_full(stream, MBOX(stream), F_SEEN, 0, &bs); |
|
fs_give((void **)&b); |
|
return rv; |
|
} |
|
|
|
|
|
Message::Message(MAILSTREAM *s, ULONG msgnb) |
|
{ |
|
mode = M_READONLY; |
|
msgno = msgnb; |
|
ms = s; |
|
env = mail_fetchstructure(ms, msgnb, &body); |
|
} |
|
|
|
// Use only when composing a new message |
|
Message::Message() |
|
{ |
|
msgno = 0; |
|
mode = M_WRITABLE; |
|
body = mail_newbody(); |
|
body->nested.part = 0; |
|
env = mail_newenvelope(); |
|
setDate(); |
|
} |
|
|
|
Message::~Message() |
|
{ |
|
if (mode == M_WRITABLE) { |
|
if (body) |
|
mail_free_body(&body); |
|
if (env) |
|
mail_free_envelope(&env); |
|
} |
|
} |
|
|
|
Message *Message::reply() const { |
|
Message *m = new Message; |
|
|
|
m->setInReplyTo(env->message_id); |
|
return m; |
|
} |
|
|
|
const char *Message::getText(ULONG *len) const |
|
{ |
|
if (!len) |
|
return 0; |
|
switch(body->type) { |
|
case TYPETEXT: |
|
return (const char *)mail_fetchtext_full(ms, msgno, len, 0); |
|
break; |
|
case TYPEMULTIPART: |
|
return (const char *)mail_fetchbody(ms, msgno, "1", len); |
|
break; |
|
} |
|
return 0; |
|
} |
|
|
|
const char *Message::getHeader() const |
|
{ |
|
return (const char *)mail_fetchheader(ms, msgno); |
|
} |
|
|
|
void Message::getDate(char *date) const |
|
{ |
|
MESSAGECACHE *m = mail_elt(ms, msgno); |
|
|
|
sprintf(date, "%d/%d %d:%d", m->day, m->month, m->hours, m->minutes); |
|
} |
|
|
|
void Message::getFrom(char *from) const |
|
{ |
|
mail_fetchfrom(from, ms, msgno, L_FROM); |
|
} |
|
|
|
void Message::getSubject(char *subj) const |
|
{ |
|
mail_fetchsubject(subj, ms, msgno, L_SUBJECT); |
|
} |
|
char Message::getFlag() const |
|
{ |
|
//mail_fetchstructure(ms, msgno, 0); |
|
MESSAGECACHE *mc = mail_elt(ms, msgno); |
|
|
|
/* Highest to lowest priority to be shown */ |
|
if (mc->deleted) |
|
return 'D'; |
|
if (mc->answered) |
|
return 'A'; |
|
if (mc->recent) |
|
return 'N'; |
|
if (!mc->seen) |
|
return 'U'; |
|
|
|
// Seen |
|
return ' '; |
|
} |
|
|
|
void Message::setFlag(char *flag) |
|
{ |
|
char seq[10]; // should be more than enuff |
|
|
|
sprintf(seq, "%ld", msgno); |
|
mail_setflag(ms, seq, flag); |
|
} |
|
|
|
void Message::clearFlag(char *flag) |
|
{ |
|
char seq[10]; |
|
|
|
sprintf(seq, "%ld", msgno); |
|
mail_clearflag(ms, seq, flag); |
|
} |
|
|
|
void Message::getAddress(ADDRESS *ad, char *buf) const |
|
{ |
|
char tmp[100]; |
|
char email[70]; |
|
ADDRESS *a = ad; |
|
|
|
buf[0] = '\0'; |
|
while (a) { |
|
if (a->host) |
|
sprintf(email, "%s@%s", a->mailbox, a->host); |
|
else |
|
sprintf(email, "%s", a->mailbox); |
|
if (a->personal) |
|
sprintf(tmp, "%s <%s>, ", a->personal, email); |
|
else |
|
sprintf(tmp, "%s, ", email); |
|
strcat(buf, tmp); |
|
a = a->next; |
|
} |
|
/* To get rid of the last "," */ |
|
if (strlen(buf)) |
|
buf[strlen(buf) - 2] = '\0'; |
|
} |
|
|
|
void Message::setDate() |
|
{ |
|
env->date = (char *)fs_get(80); |
|
rfc822_date(env->date); |
|
} |
|
|
|
void Message::setTo(const char *to) |
|
{ |
|
char *tmp = (char *)fs_get(strlen(to) + 1); |
|
strcpy(tmp, to); |
|
rfc822_parse_adrlist(&(env->to), tmp, "localhost"); |
|
fs_give((void **)&tmp); |
|
} |
|
|
|
void Message::setFrom(const char *from) |
|
{ |
|
char *tmp; |
|
if (!from) { |
|
env->from = mail_newaddr(); |
|
env->from->personal = cpystr(getName()); |
|
env->from->mailbox = cpystr(getlogin()); |
|
env->from->host = cpystr(getHostName()); |
|
env->return_path = mail_newaddr(); |
|
env->return_path->personal = cpystr(getName()); |
|
env->return_path->mailbox = cpystr(getlogin()); |
|
env->return_path->host = cpystr(getHostName()); |
|
} else { |
|
tmp = (char *)fs_get(strlen(from) + 1); |
|
strcpy(tmp, from); |
|
rfc822_parse_adrlist(&(env->from), tmp, "localhost"); |
|
rfc822_parse_adrlist(&(env->return_path), tmp, "localhost"); |
|
fs_give((void **)&tmp); |
|
} |
|
} |
|
|
|
void Message::setCc(const char *cc) |
|
{ |
|
if (!cc) |
|
return; |
|
char *tmp = (char *)fs_get(strlen(cc) + 1); |
|
strcpy(tmp, cc); |
|
rfc822_parse_adrlist(&(env->cc), tmp, "localhost"); |
|
fs_give((void **)&tmp); |
|
} |
|
|
|
void Message::setBcc(const char *bcc) |
|
{ |
|
if (!bcc) |
|
return; |
|
char *tmp = (char *)fs_get(strlen(bcc) + 1); |
|
strcpy(tmp, bcc); |
|
rfc822_parse_adrlist(&(env->bcc), tmp, "localhost"); |
|
fs_give((void **)&tmp); |
|
} |
|
|
|
void Message::setSubject(const char *subj) |
|
{ |
|
env->subject = cpystr(subj); |
|
} |
|
|
|
// Use this only when the message is *NON-MULTIPART TEXT* message |
|
void Message::setText(const char *text) |
|
{ |
|
BODY *b; |
|
|
|
if (body->type != TYPEMULTIPART) |
|
b = body; |
|
else // Go to Part I |
|
b = &body->nested.part->body; |
|
b->type = TYPETEXT; |
|
b->encoding = ENC7BIT; |
|
b->contents.text.data = cpystr(text); |
|
b->contents.text.size = strlen(text); |
|
} |
|
|
|
void Message::setCharset(const char *charset) |
|
{ |
|
BODY *b; |
|
|
|
if (body->type != TYPEMULTIPART) |
|
b = body; |
|
else // Go to Part I |
|
b = &body->nested.part->body; |
|
setBodyParameter(b, "CHARSET", charset); |
|
} |
|
|
|
long Message::sendSMTP(const char *h) |
|
{ |
|
SENDSTREAM *ss; |
|
char *host = cpystr(h); |
|
char *list[] = { host, 0 }; |
|
|
|
if (!(ss = smtp_open(list, T))) |
|
return NIL; |
|
if (smtp_mail(ss, "MAIL", env, body)) { |
|
smtp_close(ss); |
|
return T; |
|
} |
|
smtp_close(ss); |
|
return NIL; |
|
} |
|
|
|
long Message::sendMTA(const char *m) |
|
{ |
|
long rv = NIL; |
|
FILE *f = popen(m, "w"); |
|
if (export(f)) |
|
rv = T; |
|
pclose(f); |
|
return rv; |
|
} |
|
|
|
static long dump(void *stream, char *s) |
|
{ |
|
FILE *f = (FILE *)stream; |
|
return (fprintf(f, s) < 0)? NIL : T; |
|
} |
|
|
|
long Message::export(FILE *f) |
|
{ |
|
char t[5000]; |
|
|
|
return f? rfc822_output(t, env, body, dump, f, 0) : NIL; |
|
} |
|
|
|
char *Message::toSTRING(ULONG *len) |
|
{ |
|
char t[5000]; |
|
char *tmpfile; |
|
FILE *tmp; |
|
ULONG size; |
|
char *s; |
|
|
|
// use tmp file as buffer |
|
tmpfile = tempnam(0, "KMAIL"); |
|
printf("Tmpfile %s\n", tmpfile); |
|
if (!(tmp = fopen(tmpfile, "w+b"))) { |
|
printf("Can't open tmp file\n"); |
|
return NIL; |
|
} |
|
chmod(tmpfile, S_IRUSR | S_IWUSR); |
|
switch(mode) { |
|
case M_WRITABLE: |
|
if (!rfc822_output(t, env, body, dump, tmp, 0)) { |
|
printf("rfc822_output failed\n"); |
|
return NIL; |
|
} |
|
break; |
|
case M_READONLY: |
|
char *h = mail_fetchheader_full(ms, msgno, 0, &size, FT_PREFETCHTEXT); |
|
fwrite((void *)h, 1, size, tmp); |
|
h = mail_fetchtext_full(ms, msgno, &size, 0); |
|
fwrite((void *)h, 1, size, tmp); |
|
break; |
|
} |
|
*len = size = ftell(tmp); |
|
rewind(tmp); |
|
s = (char *)fs_get(size); |
|
if (size != fread((void *)s, 1, size, tmp)) { |
|
printf("Fread failed\n"); |
|
*len = 0; |
|
fs_give((void **)&s); |
|
} |
|
fclose(tmp); |
|
unlink(tmpfile); |
|
free(tmpfile); |
|
return s; |
|
} |
|
|
|
// This function returns the number of attachments |
|
// (excluding the normal text part). |
|
// For non-multipart message the number returned is always 0 |
|
ULONG Message::numAttch() |
|
{ |
|
ULONG n = 0L; |
|
PART *next; |
|
|
|
if (body->type != TYPEMULTIPART) |
|
return 0L; |
|
next = body->nested.part; |
|
/* traverse the list */ |
|
while (next) { |
|
next = next->next; |
|
n++; |
|
} |
|
// -1 because the first test part is excluded |
|
return n - 1; |
|
} |
|
|
|
BODY *Message::getBodyPart(ULONG ptno) |
|
{ |
|
if (body->type != TYPEMULTIPART) |
|
return 0; |
|
|
|
PART *next = body->nested.part; |
|
ULONG ctr = 1; |
|
|
|
while (ctr < ptno && next) { |
|
next = next->next; |
|
ctr++; |
|
} |
|
if (ctr == ptno) |
|
return &next->body; |
|
return 0; // incorrect body part |
|
} |
|
|
|
Attachment *Message::getAttch(ULONG ptno) |
|
{ |
|
BODY *ptr; |
|
Attachment *a; |
|
PARAMETER *p; |
|
char sec[10]; |
|
char *txt; |
|
ULONG len; |
|
|
|
//printf("Get Body\n"); |
|
if ((ptr = getBodyPart(ptno + 1))) |
|
a = new Attachment; |
|
else |
|
return 0; |
|
// Copy info |
|
//printf("Copy Info\n"); |
|
//printf("Set type\n"); |
|
a->setType(ptr->type); |
|
//printf("Set Desc\n"); |
|
a->setDescription((const char *)ptr->description); |
|
//printf("Set Subtype\n"); |
|
if (ptr->subtype) |
|
a->setSubtype((const char *)ptr->subtype); |
|
//printf("Set Encoding\n"); |
|
a->setEncoding(ptr->encoding); |
|
// Get various attributes |
|
p = ptr->parameter; |
|
mdebug("Set para\n"); |
|
while (p) |
|
{ |
|
char *tmp = cpystr(p->attribute); |
|
if (!strcmp("NAME", ucase(tmp))) |
|
a->setFilename((const char *)p->value); |
|
else if (!strcmp("CHARSET", ucase(tmp))) |
|
a->setCharset((const char *)p->value); |
|
fs_give((void **)&tmp); |
|
p = p->next; |
|
} |
|
// Decode the data |
|
mdebug("Decoding...\n"); |
|
sprintf(sec, "%ld", ptno + 1); |
|
txt = mail_fetchbody(ms, msgno, sec, &len); |
|
switch(ptr->encoding) { |
|
void *da; |
|
case ENCBASE64: |
|
da = rfc822_base64((unsigned char *)txt, len, &len); |
|
a->setData(da, len); |
|
break; |
|
case ENCQUOTEDPRINTABLE: |
|
da = rfc822_qprint((unsigned char *)txt, len, &len); |
|
a->setData(da, len); |
|
break; |
|
default: // Can't do anything |
|
break; |
|
} |
|
return a; |
|
} |
|
|
|
void setBodyParameter(BODY *b, const char *att, const char *value) |
|
{ |
|
PARAMETER *p = b->parameter; |
|
|
|
if (!b->parameter) |
|
p = b->parameter = mail_newbody_parameter(); |
|
while (p->next) |
|
p = p->next; |
|
p->attribute = cpystr(att); |
|
p->value = cpystr(value); |
|
} |
|
|
|
void Message::attach(Attachment *a) |
|
{ |
|
PART *part; |
|
BODY *b; |
|
|
|
if (!a) |
|
return; |
|
body->type = TYPEMULTIPART; |
|
body->subtype = cpystr("MIXED"); |
|
// If text part not present create it |
|
if (!body->nested.part) |
|
part = body->nested.part = mail_newbody_part(); |
|
// Now skip to the tail of the linked list |
|
while (part->next) |
|
part = part->next; |
|
// Create this part |
|
part->next = mail_newbody_part(); |
|
b = &part->next->body; |
|
b->type = a->type; |
|
b->encoding = a->encoding; |
|
b->subtype = cpystr(a->subtype); |
|
b->id = 0; // Nothing right now |
|
b->description = cpystr(a->description); |
|
// set up the parameters |
|
if (a->charset) |
|
setBodyParameter(b, "CHARSET", a->charset); |
|
if (a->filename) |
|
setBodyParameter(b, "NAME", a->filename); |
|
b->contents.text.data = (char *)a->data; |
|
b->contents.text.size = a->length; |
|
|
|
// Set to NULL to avoid freeing the memory twice. |
|
a->data = 0; |
|
} |
|
|
|
void printa(ADDRESS *a, char *title) |
|
{ |
|
printf("------------- ADDRESS %s--------------\n", title); |
|
ADDRESS *next = a; |
|
while (next) { |
|
printf("Personal: <%s> ", next->personal); |
|
printf("Mailbox: <%s> ", next->mailbox); |
|
printf("Host: <%s> ", next->host); |
|
printf("Error: <%s>\n", next->error); |
|
next = next->next; |
|
} |
|
} |
|
|
|
void printb(BODY *b) |
|
{ |
|
PARAMETER *p; |
|
printf("------------- BODY --------------\n"); |
|
printf("Body Type: %s\n", bodytype[b->type]); |
|
printf("Encoding: %s\n", enctable[b->encoding]); |
|
printf("Subtype: %s\n", b->subtype); |
|
printf("Description: %s\n", b->description); |
|
printf("Body Content ID: %s\n", b->id); |
|
p = b->parameter; |
|
while (p) |
|
{ |
|
printf("\tAttribute: %s\n", p->attribute); |
|
printf("\tValue: %s\n", p->value); |
|
p = p->next; |
|
} |
|
} |
|
|
|
void printe(ENVELOPE *e) |
|
{ |
|
printf("-----------------ENVELOPE---------------------\n"); |
|
printa(e->return_path, "Return Path"); |
|
printa(e->from, "From"); |
|
printa(e->sender, "Sender"); |
|
printa(e->reply_to, "Reply-To"); |
|
printa(e->to, "To"); |
|
printa(e->cc, "Cc"); |
|
printa(e->bcc, "Bcc"); |
|
printf("Remail: %s\n", e->remail); |
|
printf("Date: %s\n", e->date); |
|
printf("Subject: %s\n", e->subject); |
|
printf("In Reply To ID: %s\n", e->in_reply_to); |
|
printf("Message ID: %s\n", e->message_id); |
|
printf("Newsgroups: %s\n", e->newsgroups); |
|
printf("Follow-up to: %s\n", e->followup_to); |
|
printf("References: %s\n", e->references); |
|
} |
|
|
|
void Message::debug() |
|
{ |
|
PART *next = body->nested.part; |
|
printf("==================================================\n"); |
|
printe(env); |
|
printb(body); |
|
while (next) { |
|
printb(&next->body); |
|
next = next->next; |
|
} |
|
printf("==================================================\n"); |
|
} |
|
|
|
Attachment::Attachment() |
|
{ |
|
// Set up some default values |
|
type = TYPEAPPLICATION; |
|
subtype = cpystr("OCTET-STREAM"); |
|
description = 0; |
|
filename = 0; |
|
charset = 0; |
|
encoding = ENCBASE64; |
|
length = (ulong)0; |
|
data = 0; |
|
} |
|
|
|
Attachment::~Attachment() |
|
{ |
|
if (filename) |
|
fs_give((void **)&filename); |
|
if (description) |
|
fs_give((void **)&description); |
|
if (subtype) |
|
fs_give((void **)&subtype); |
|
if (charset) |
|
fs_give((void **)&charset); |
|
if (data) |
|
fs_give((void **)&data); |
|
} |
|
|
|
static int cmp(const void *key, const void *data) |
|
{ |
|
struct FileType *t = (struct FileType *)data; |
|
return strcmp((CCHAR)key, t->ext); |
|
} |
|
|
|
// It tries to guess the type of the file by its extension, and setup the |
|
// appropriate data structure |
|
long Attachment::guess(CCHAR filename) |
|
{ |
|
char *ext; |
|
char ext2[10]; |
|
const char *b; |
|
const struct FileType *f = 0; |
|
short t; |
|
|
|
t = fileType(filename); |
|
if (!t) |
|
return NIL; |
|
if (!(b = basename(filename))) |
|
return NIL; |
|
mdebug("Basename = <%s>\n", b); |
|
ext = strrchr(b, '.'); |
|
mdebug("Extension = <%s>\n", ext); |
|
if (ext++) { |
|
strcpy(ext2, ext); |
|
f = (struct FileType *)bsearch(lcase(ext2), fInfo, NUMTYPES, sizeof(FileType), cmp); |
|
} |
|
// Unknown extension or no extension at all |
|
if (!f) { |
|
mdebug("<<<<<<Unknown/No extension>>>>>>>>\n"); |
|
switch(t) { |
|
case TEXT: |
|
f = &defaultTextFileType; |
|
break; |
|
case BINARY: |
|
f = &defaultBinFileType; |
|
break; |
|
case BADFILE: |
|
return NIL; |
|
break; |
|
} |
|
} |
|
setFilename(b); |
|
setType(f->type); |
|
setSubtype(f->subtype); |
|
setCharset(f->charset); |
|
// Since this is an attachment we treat everything as binary |
|
/*if (f->charset) |
|
setEncoding(ENC7BIT); |
|
else*/ |
|
setEncoding(ENCBINARY); |
|
// doesn't matter if the data type is data or binary |
|
// C-client will take care of the encoding |
|
data = readFile(filename, &length); |
|
mdebug("Size of data: %ld\n", length); |
|
return data? T : NIL; |
|
} |
|
|
|
|