www.pudn.com > popmail.zip > msg_part.c
/* * Eucalyptus * by Paul A. Schifferer * * Module: msg_part.c * Support functions for message parts * * Copyright © 1997-9 Isengard Developments * All rights reserved. */ #include#include #include "eucalyptus.h" MsgPart *msgpart_new(void) { MsgPart *part; if(part = g_malloc0(sizeof(MsgPart))) { part->Type = CONTENTTYPE_TEXT | CONTENTSUBTYPE_TEXT_PLAIN; part->Filename = g_strdup(""); part->Name = g_strdup(""); part->Label = g_strdup(""); part->Boundary = g_strdup(""); } return part; } void msgpart_free(MsgPart *part) { if(!part) return; // gtk_widget_destroy(part->Button); if(part->Headers) mailmsg_free_header(part->Headers); part->Headers = NULL; g_free(part->Filename); g_free(part->Name); g_free(part->Label); g_free(part->Boundary); g_free(part); } gboolean msgpart_process(MailMsg *msg, MsgPart *part, guint32 flags) { gboolean success = FALSE; if(!msg || !msg->Folder || !part) return FALSE; if(((msg->ContentTypeCode & CONTENTTYPE_MASK) == CONTENTTYPE_MULTIPART) && ((msg->ContentTypeCode & CONTENTSUBTYPE_MASK) == CONTENTSUBTYPE_MULTIPART_ENCRYPTED) && ((part->Type & CONTENTTYPE_MASK) == CONTENTTYPE_APPLICATION) && ((part->Type & CONTENTSUBTYPE_MASK) == CONTENTSUBTYPE_APPLICATION_OCTETSTREAM)) { if(!euc_request(msg->Window, _("Eucalyptus encrypted message"), _("This message is encrypted.....blah blah blah FIXME"), euc_yes_no_buttons, 1, 0)) { success = mailmsg_decrypt(msg); } } else { gchar *tmpname; tmpname = mailmsg_get_temp_name(msg); if(success = msgpart_save(tmpname, msg, part, flags)) { g_free(part->Filename); part->Filename = g_strdup(tmpname); } g_free(tmpname); } return success; } gboolean msgpart_save(gchar *fname, MailMsg *msg, MsgPart *part, gint32 flags) { gboolean success = TRUE; gchar *msgname; FILE *fp, *tmp_fp; if(!fname || !msg || !msg->Folder || !part || !g_list_length(msg->Parts.List)) return FALSE; busy_pointer(msg->Window, TRUE); msgname = mailmsg_get_full_path(msg); if(fp = fopen(msgname, "r")) { gchar text[1024]; // open new file if(tmp_fp = fopen(fname, "w")) { HdrNode *cte; gint32 triplet; glong qpos, equals, part_num, uuco unt, hcount = 0, content_code = CONTENTTYPE_TEXT, binary_column = 0, binary_address = 0; gint16 binary_data[16] = {0,}; gchar uufile[101], *boundary = NULL; gchar content_encoding = 0; gboolean uublock = FALSE, lastequals = FALSE, bufferedeol, html = FALSE, nomoredata = FALSE; // get header out of the way while(fgets(text, sizeof(text) - 1, fp)) { if((flags & SMPF_SAVEHEADERS) && (msg->PartCount == 1)) { if(flags & SMPF_CONVERTTABS) parse_convert_tabs(text, sizeof(text), prefs.TabWidth); if(flags & SMPF_BRIEFHEADERS) { switch(hcount++) { case 0: // from fprintf(tmp_fp, " From: %s\r\n", msg->Index.From); break; case 1: // subject fprintf(tmp_fp, "Subject: %s\r\n", msg->Index.Subject); break; case 2: // date fprintf(tmp_fp, " Date: %s\r\n", msg->t.Date); break; } } else fprintf(tmp_fp, text); } if((*text == '\n') || (*text == '\r') || !*text) break; } /* Check for multipart. */ if((msg->ContentTypeCode & CONTENTTYPE_MASK) == CONTENTTYPE_MULTIPART) { boundary = part->Boundary; part_num = 0; content_code = part->Type; // get opening boundary string while(fgets(text, sizeof(text) - 1, fp)) { if(!strncmp(text, "--", 2) && !strncmp(text + 2, boundary, strlen(boundary))) break; } while(part_num != part->Number) { if(fgets(text, sizeof(text) - 1, fp)) { if(!strncmp(text, "--", 2) && !strncmp(text + 2, boundary, strlen(boundary))) { part_num++; } } } // get header out of the way if(flags & SMPF_SAVEHEADERS) { while(fgets(text, sizeof(text) - 1, fp)) { if(flags & SMPF_CONVERTTABS) parse_convert_tabs(text, sizeof(text), prefs.TabWidth); fprintf(tmp_fp, text); if((*text == '\n') || (*text == '\r') || !*text) break; } } else { while(fgets(text, sizeof(text) - 1, fp)) { if((*text == '\n') || (*text == '\r') || !*text) break; } } if(cte = header_find_tag("Content-Transfer-Encoding", part->Headers, CHTF_CASECONV)) content_encoding = content_transfer_encoding_verify(cte->Data); triplet = 0; qpos = 0; equals = 0; bufferedeol = FALSE; } else { content_code = msg->ContentTypeCode; if(cte = header_find_tag("Content-Transfer-Encoding", msg->Headers, CHTF_CASECONV)) content_encoding = content_transfer_encoding_verify(cte->Data); } memset(text, 0, sizeof(text)); while(fgets(text, sizeof(text) - 1, fp)) { glong pos, x, i, q = 0, colors[11] = {0, 32, 33, 34, 35, 36, 37, 37, 37, 37, 37}, c, paramct = 0, nofill = 0, blockq = 0; gchar cstr[20], token[62], *p; if((msg->ContentTypeCode & CONTENTTYPE_MASK) == CONTENTTYPE_MULTIPART) { if(!strncmp(text, "--", 2) && !strncmp(text + 2, boundary, strlen(boundary))) break; pos = 0; } if(flags & SMPF_NODECODING) { glong x = 0; gchar *c; if(bufferedeol) fprintf(tmp_fp, "\r\n"); bufferedeol = FALSE; if(c = strchr(text, '\n')) { *c = '\0'; bufferedeol = TRUE; } if(c = strchr(text, '\r')) { *c = '\0'; bufferedeol = TRUE; } while(text[x]) { switch(text[x]) { case '\t': if(flags & SMPF_CONVERTTABS) { glong i; for(i=0; i ContentFlags |= MMCF_ISUUENCODED; break; } } if((!strncasecmp(text, "end", 3) || !strcmp(text, "\r\n") || !strcmp(text, "\r") || !strcmp(text, "\n")) && uublock) { // end of uuencoded data gchar output[256]; if(fgets(text, sizeof(text) - 1, fp)) { if(!strncasecmp(text, "size ", 5)) uucount = atol(text + 5); } uublock = FALSE; // Flush(tmp_fp); if(flags & SMPF_FORDISPLAY) { // fprintf(tmp_fp, "\033[1m"); } fprintf(tmp_fp, "Encoded data (suppressed), filename=\"%s\", %ld bytes.\r\n", uufile, uucount); fprintf(tmp_fp, "Select \"UUdecode\" from Contents menu to decode.\r\n"); if(flags & SMPF_FORDISPLAY) { // fprintf(tmp_fp, "\033[0m"); } break; } if(uublock) { header_remove_whitespace(text, RWSF_NOATOMS); uucount += strlen(text); break; } if(flags & SMPF_CONVERTTABS) parse_convert_tabs(text, sizeof(text), prefs.TabWidth); for(i=0; i From", 5)) q = 0; if(flags & SMPF_FORDISPLAY) { if(q == 0) q = MIN(blockq, 10); // fprintf(tmp_fp, "\033[0;%ldm", colors[q]); } #if 0 if(blockq) { glong j; for(j=0; j "); } #endif // write the actual text bold = ital = under = 0; url = FALSE; i = 0; while(text[i]) { switch(c = text[i]) { case '\t': if(flags & SMPF_CONVERTTABS) { glong j; for(j=0; j '; j++) { if(j < sizeof(token) - 1) *p++ = tolower(c); } *p = '\0'; if(c == 0) break; if(strcmp(token, "/param") == 0) { paramct--; fputc('>', tmp_fp); } else if(paramct > 0) { // process the parameters } else { if(strcmp(token, "nofill") == 0) { nofill++; } else if(strcmp(token, "/nofill") == 0) { nofill--; } else if(strcmp(token, "bold") == 0) { if(flags & SMPF_FORDISPLAY) { // fprintf(tmp_fp, "\033[1m"); } } else if(strcmp(token, "/bold") == 0) { if(flags & SMPF_FORDISPLAY) { // fprintf(tmp_fp, "\033[22m"); } } else if(strcmp(token, "italic") == 0) { if(flags & SMPF_FORDISPLAY) { // fprintf(tmp_fp, "\033[3m"); } } else if(strcmp(token, "/italic") == 0) { if(flags & SMPF_FORDISPLAY) { // fprintf(tmp_fp, "\033[23m"); } } else if(strcmp(token, "underline") == 0) { if(flags & SMPF_FORDISPLAY) { // fprintf(tmp_fp, "\033[4m"); } } else if(strcmp(token, "/underline") == 0) { if(flags & SMPF_FORDISPLAY) { // fprintf(tmp_fp, "\033[24m"); } } else if(strcmp(token, "fixed") == 0) { } else if(strcmp(token, "/fixed") == 0) { } else if(strcmp(token, "excerpt") == 0) { } else if(strcmp(token, "/excerpt") == 0) { } else { // putc('?', stdout); // fputs(token, stdout); if(strcmp(token, "param") == 0) { paramct++; fputc(' ', tmp_fp); lastequals = FALSE; goto nextc; } } } } } #if 0 else if(content_code == (CONTENTTYPE_TEXT | CONTENTSUBTYPE_TEXT_HTML)) { glong j; gchar *e, *parms; memset(token, 0, sizeof(token) - 1); for(j = 0, p = token; (c = text[++i]) && (c != '>'); j++) { if(j < sizeof(token) - 1) *p++ = tolower(c); } *p = '\0'; if(c == 0) break; if(e = strchr(token, ' ')) { *e = '\0'; parms = e + 1; } else parms = ""; if(strcmp(token, "html") == 0) { html = TRUE; } else if(strcmp(token, "/html") == 0) { html = FALSE; } else if(strcmp(token, "blockquote") == 0) { if(html) { blockq++; fprintf(tmp_fp, "\n\n"); } } else if(strcmp(token, "/blockquote") == 0) { if(html) { blockq--; fprintf(tmp_fp, "\n\n"); } } else if(strcmp(token, "pre") == 0) { if(html) { nofill++; fprintf(tmp_fp, "\n\n"); } } else if(strcmp(token, "/pre") == 0) { if(html) { nofill--; fprintf(tmp_fp, "\n\n"); } } else if(strcmp(token, "b") == 0) { if(html) { if(flags & SMPF_FORDISPLAY) { // fprintf(tmp_fp, "\033[1m"); } } } else if(strcmp(token, "/b") == 0) { if(html) { if(flags & SMPF_FORDISPLAY) { // fprintf(tmp_fp, "\033[22m"); } } } else if(strcmp(token, "i") == 0) { if(html) { if(flags & SMPF_FORDISPLAY) { // fprintf(tmp_fp, "\033[3m"); } } } else if(strcmp(token, "/i") == 0) { if(html) { if(flags & SMPF_FORDISPLAY) { // fprintf(tmp_fp, "\033[23m"); } } } else if(strcmp(token, "u") == 0) { if(html) { if(flags & SMPF_FORDISPLAY) { // fprintf(tmp_fp, "\033[4m"); } } } else if(strcmp(token, "/u") == 0) { if(html) { if(flags & SMPF_FORDISPLAY) { // fprintf(tmp_fp, "\033[24m"); } } } else if(strcmp(token, "p") == 0) { if(html) { fprintf(tmp_fp, "\n\n"); eol = TRUE; } } else if(strcmp(token, "/p") == 0) { } else if(strcmp(token, "br") == 0) { if(html) { fprintf(tmp_fp, "\n"); eol = TRUE; } } else { // putc('?', stdout); // fputs(token, stdout); } } #endif else { fputc('<', tmp_fp); } break; case '&': #if 0 if(content_code == (CONTENTTYPE_TEXT | CONTENTSUBTYPE_TEXT_HTML)) { gchar *e; if(e = strchr(text + i, ';')) { glong l; gchar *ent; *e = '\0'; ent = text + i + 1; l = strlen(ent); i += l + 1; if(!html) break; if(!strcasecmp(ent, "nbsp")) fputc(' ', tmp_fp); else if(!strcasecmp(ent, "copy")) fputc((gchar)'©', tmp_fp); else if(!strcasecmp(ent, "amp")) fputc('&', tmp_fp); else if(!strcasecmp(ent, "gt")) fputc('>', tmp_fp); else if(!strcasecmp(ent, "lt")) fputc('<', tmp_fp); else if(ent[0] == '#') { fputc(atoi(ent + 1), tmp_fp); } else { fprintf(tmp_fp, "&%s;", ent); } break; } } #endif fputc('&', tmp_fp); break; case '=': if(content_encoding == ENCODING_QUOTEDPRINTABLE) { lastequals = TRUE; i++; if((text[i] == '\r') || (text[i] == '\n')) { if(text[i + 1] == '\n') { i++; eol = FALSE; } lastequals = FALSE; break; } } default: def_char2: if(!text[i]) break; if((content_encoding == ENCODING_QUOTEDPRINTABLE) && lastequals) { glong val; gchar hex[3] = {0,}; hex[0] = text[i++]; if(text[i]) hex[1] = text[i]; hex[2] = 0; if(isxdigit(hex[0]) && isxdigit(hex[1])) { val = strtol(hex, NULL, 16); if(val) fputc(val, tmp_fp); } } else { if(content_code == (CONTENTTYPE_TEXT | CONTENTSUBTYPE_TEXT_ENRICHED)) { if(((c == '\n') || (c == '\r')) && (nofill <= 0) && (paramct <= 0)) { while(text[i] == '\n') { fprintf(tmp_fp, "\n"); i++; eol = TRUE; } i--; } fputc(c, tmp_fp); } #if 0 else if(content_code == (CONTENTTYPE_TEXT | CONTENTSUBTYPE_TEXT_HTML)) { if(!html) { lastequals = FALSE; break; } if(((c == '\n') || (c == '\r')) && (nofill <= 0)) { while((text[i] == '\n') || (text[i] == '\r')) i++; fputc(' ', tmp_fp); i--; eol = TRUE; } else fputc(c, tmp_fp); } #endif else { switch(text[i]) { case '*': if(flags & SMPF_FORDISPLAY) { if(!bold) { if((text[i + 1] != '*') && !url) { if(check_style_char(text + i + 1, '*')) { // fprintf(tmp_fp, "\033[1m"); bold++; break; } } fputc(text[i], tmp_fp); break; } if((text[i + 1] != ' ') && (text[i + 1] != '\n') && (text[i + 1] != '\r') && (text[i + 1] != '\t')) { fprintf(tmp_fp, " "); } else { // fprintf(tmp_fp, "\033[22m"); bold = 0; } break; } fputc(text[i], tmp_fp); break; case '_': if(flags & SMPF_FORDISPLAY) { if(!under) { if((text[i + 1] != '_') && !url) { if(check_style_char(text + i + 1, '_')) { // fprintf(tmp_fp, "\033[4m"); under++; break; } } fputc(text[i], tmp_fp); break; } if((text[i + 1] != ' ') && (text[i + 1] != '\n') && (text[i + 1] != '\r') && (text[i + 1] != '\t')) { fprintf(tmp_fp, " "); } else { // fprintf(tmp_fp, "\033[24m"); under = 0; } break; } fputc(text[i], tmp_fp); break; case '/': if(flags & SMPF_FORDISPLAY) { if(!ital) { if((text[i + 1] != '/') && !url) { if(check_style_char(text + i + 1, '/')) { // fprintf(tmp_fp, "\033[3m"); ital++; break; } } fputc(text[i], tmp_fp); break; } if((text[i + 1] != ' ') && (text[i + 1] != '\n') && (text[i + 1] != '\r') && (text[i + 1] != '\t')) { fprintf(tmp_fp, " "); } else { // fprintf(tmp_fp, "\033[23m"); ital = 0; } break; } fputc(text[i], tmp_fp); break; case ' ': if(/* bold || ital || under || */ url) { // reset attributes and restore quoting color if(flags & SMPF_FORDISPLAY) { // fprintf(tmp_fp, "\033[0;%ldm ", colors[q]); } } else fputc(' ', tmp_fp); // bold = ital = under = 0; url = FALSE; break; case 'h': case 'f': case 'm': if(flags & SMPF_FORDISPLAY) { if(!strncmp(text + i, "http://", 7) || !strncmp(text + i, "ftp://", 6) || !strncmp(text + i, "mailto:", 7)) { if(flags & SMPF_FORDISPLAY) { // fprintf(tmp_fp, "\033[33m"); } url = TRUE; } } fputc(text[i], tmp_fp); break; case '>': case ']': if(url) { if(flags & SMPF_FORDISPLAY) { // fprintf(tmp_fp, "\033[0;%ldm%c", colors[q], text[i]); } } else fputc(text[i], tmp_fp); url = FALSE; break; case '\r': case '\n': eol = TRUE; default: fputc(text[i], tmp_fp); break; } } } lastequals = FALSE; break; } nextc: i++; } if((content_code == (CONTENTTYPE_TEXT | CONTENTSUBTYPE_TEXT_PLAIN)) && eol) { // shut off any formatting codes if(flags & SMPF_FORDISPLAY) { // fprintf(tmp_fp, "\033[0m"); } } eol = FALSE; break; case ENCODING_BASE64: x = 0; triplet = 0; qpos = 0; while(text[x]) { if(base64_valid(text[x])) { if(text[x] == '=') { equals++; nomoredata = TRUE; } else triplet |= (base64_get_value(text[x]) << ((3 - qpos) * 6)); qpos++; } if(qpos == 4) { fputc((triplet & 0xFF0000) >> 16, tmp_fp); if(equals < 2) fputc((triplet & 0xFF00) >> 8, tmp_fp); if(!equals) fputc((triplet & 0xFF), tmp_fp); triplet = 0; qpos = 0; } x++; } break; } memset(text, 0, sizeof(text)); } if(content_code == (CONTENTTYPE_APPLICATION | CONTENTSUBTYPE_APPLICATION_PGPENCRYPTED)) { fprintf(tmp_fp, _("This message is encrypted. To view its contents\nselect Decrypt from the Security menu.")); } fclose(tmp_fp); } else success = FALSE; fclose(fp); } else success = FALSE; busy_pointer(msg->Window, FALSE); return success; } glong msgpart_get_image(MsgPart *part) { glong image = IMAGE_PART_TEXT; if(!part) return(IMAGE_PART_TEXT); switch(part->Type & CONTENTTYPE_MASK) { case CONTENTTYPE_IMAGE: switch(part->Type & CONTENTSUBTYPE_MASK) { case CONTENTSUBTYPE_IMAGE_JPEG: image = IMAGE_PART_IMAGEJPEG; break; case CONTENTSUBTYPE_IMAGE_GIF: image = IMAGE_PART_IMAGEGIF; break; default: break; } break; case CONTENTTYPE_AUDIO: image = IMAGE_PART_AUDIO; break; case CONTENTTYPE_VIDEO: image = IMAGE_PART_VIDEO; break; case CONTENTTYPE_APPLICATION: switch(part->Type & CONTENTSUBTYPE_MASK) { case CONTENTSUBTYPE_APPLICATION_PGPENCRYPTED: image = IMAGE_PART_APPLICATIONPGPENCRYPTED; break; case CONTENTSUBTYPE_APPLICATION_PGPSIGNATURE: image = IMAGE_PART_APPLICATIONPGPSIGNATURE; break; case CONTENTSUBTYPE_APPLICATION_PGPKEYS: image = IMAGE_PART_APPLICATIONPGPKEYS; break; case CONTENTSUBTYPE_APPLICATION_POSTSCRIPT: image = IMAGE_PART_APPLICATIONPOSTSCRIPT; break; default: image = IMAGE_PART_APPLICATIONOCTETSTREAM; break; } break; case CONTENTTYPE_MULTIPART: switch(part->Type & CONTENTSUBTYPE_MASK) { case CONTENTSUBTYPE_MULTIPART_ALTERNATIVE: image = IMAGE_PART_MULTIPARTALTERNATIVE; break; case CONTENTSUBTYPE_MULTIPART_PARALLEL: image = IMAGE_PART_MULTIPARTPARALLEL; break; case CONTENTSUBTYPE_MULTIPART_REPORT: image = IMAGE_PART_MULTIPARTREPORT; break; case CONTENTSUBTYPE_MULTIPART_SIGNED: image = IMAGE_PART_MULTIPARTSIGNED; break; case CONTENTSUBTYPE_MULTIPART_ENCRYPTED: image = IMAGE_PART_MULTIPARTENCRYPTED; break; case CONTENTSUBTYPE_MULTIPART_TRANSPORT: image = IMAGE_PART_MULTIPARTTRANSPORT; break; default: image = IMAGE_PART_MULTIPART; break; } break; case CONTENTTYPE_MESSAGE: switch(part->Type & CONTENTSUBTYPE_MASK) { case CONTENTSUBTYPE_MESSAGE_RFC822: image = IMAGE_PART_MESSAGERFC822; break; case CONTENTSUBTYPE_MESSAGE_PARTIAL: image = IMAGE_PART_MESSAGEPARTIAL; break; case CONTENTSUBTYPE_MESSAGE_EXTERNALBODY: image = IMAGE_PART_MESSAGEEXTERNALBODY; break; default: image = IMAGE_PART_MESSAGE; break; } break; default: switch(part->Type & CONTENTSUBTYPE_MASK) { case CONTENTSUBTYPE_TEXT_ENRICHED: image = IMAGE_PART_TEXTENRICHED; break; case CONTENTSUBTYPE_TEXT_HTML: image = IMAGE_PART_TEXTHTML; break; default: image = IMAGE_PART_TEXT; break; } break; } return(image); }