/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ #ifdef MOZ_ENDER_MIME #include "xp_core.h" #include "mprmime.h" #include "mimeenc.h" #include "libi18n.h" /*for converting csids to strings*/ #define CONTENT_TYPE_MPR_MIMEREL "Content-Type: multipart/related; " #define CONTENT_TYPE_TXT_MIMEREL "Content-Type: text/html; charset=" #define CONTENT_TYPE_MIMEREL "Content-Type: " #define CONTENT_ID_MIMEREL "Content-ID: " #define CONTENT_TRANS_MIMEREL "Content-Transfer-Encoding: " #define BASE64_MIMEREL "base64" #define BIT7_MIMEREL "7bit" #define BOUNDARYSTR_MIMEREL "boundary=" #define XMOZSTATUS_MIMEREL "X-Mozilla-Status: 8001" #define CONTENT_DISPOSITION_MIMEREL "Content-Disposition: inline; filename=" #define READ_BUFFER_LEN 255 /* prototypes */ static XP_Bool output_text_file(GenericMimeRelatedData *p_genmime, int16 p_index); static XP_Bool output_text_body(GenericMimeRelatedData *p_genmime, int16 p_index); static XP_Bool output_base64_file(GenericMimeRelatedData *p_genmime, int16 p_index); AttachmentFields * AttachmentFields_Init(char *p_pFilename, char *p_pDispositionName, char *p_pContentType, char *p_pContentId) { AttachmentFields *data = XP_NEW(AttachmentFields); if (!data || !p_pFilename || !p_pContentType || !p_pContentId) return 0; XP_MEMSET(data, 0, sizeof(*data)); data->m_pFilename = p_pFilename; data->m_pDispositionName = p_pDispositionName; data->m_pContentType = p_pContentType; if (!data->m_pDispositionName) data->m_pDispositionName = XP_STRDUP(p_pFilename); data->m_pContentId = p_pContentId; return data; } static XP_Bool attachmentfields_validate(AttachmentFields *p_fields) { if (!p_fields) return FALSE; if (!p_fields->m_pFilename) return FALSE; /*no filename is bad*/ if (!p_fields->m_pDispositionName) return FALSE; /*no disposition is bad*/ if (!p_fields->m_pContentType) return FALSE; /*no contenttype is bad*/ if (!p_fields->m_pContentId) return FALSE; /*no yayaya*/ return TRUE; } XP_Bool AttachmentFields_Destroy(AttachmentFields *p_fields) { if (!p_fields) return FALSE; XP_FREEIF(p_fields->m_pFilename); XP_FREEIF(p_fields->m_pDispositionName); XP_FREEIF(p_fields->m_pContentType); XP_FREEIF(p_fields); return TRUE; } /* p_pBoundarySpecifier will be deleted in Destroy method. */ GenericMimeRelatedData * GenericMime_Init(char *p_pBoundarySpecifier, int (*output_fn) (const char *, int32, void *), void *closure) { GenericMimeRelatedData *data = XP_NEW(GenericMimeRelatedData); if (!data) return 0; XP_MEMSET(data, 0, sizeof(*data)); data->m_pBoundarySpecifier = p_pBoundarySpecifier; data->write_buffer = output_fn; data->closure = closure; return data; } static XP_Bool genericmime_validate(GenericMimeRelatedData *p_genmime) { int i;/*counter*/ if (!p_genmime) return FALSE; if (!(p_genmime->m_iNumTextFiles + p_genmime->m_iNumBase64Files)) return FALSE; /*no files*/ for( i=0; im_iNumTextFiles; i++) { if (!p_genmime->m_pTextFiles[i]) return FALSE; /* no filename in position */ } return TRUE; } XP_Bool GenericMime_Destroy(GenericMimeRelatedData *p_gendata) { int i; if (!p_gendata) { XP_ASSERT(0); return FALSE; } for( i=0; im_iNumTextFiles; i++) { XP_FREE(p_gendata->m_pTextFiles[i]); } XP_FREEIF(p_gendata->m_pTextFiles); for( i=0; im_iNumBase64Files; i++) { XP_FREEIF(p_gendata->m_pBase64Files[i]); } XP_FREEIF(p_gendata->m_pBase64Files); XP_FREEIF(p_gendata->m_pCsids); XP_FREEIF(p_gendata->m_pBoundarySpecifier); XP_FREE(p_gendata); return TRUE; } static XP_Bool output_text_body(GenericMimeRelatedData *p_genmime, int16 p_index) { char readbuffer[READ_BUFFER_LEN]; /*buffer to store incomming data*/ int16 numread; /*number of bytes read in each pass*/ XP_File t_inputfile; /*file pointer for input file*/ (*p_genmime->write_buffer)("\n",1,p_genmime->closure); if( (t_inputfile = XP_FileOpen(p_genmime->m_pTextFiles[p_index],xpFileToPost,XP_FILE_READ)) != NULL ) { /* Attempt to read in READBUFLEN characters */ while (!feof( t_inputfile )) { numread = XP_FileRead( readbuffer, READ_BUFFER_LEN, t_inputfile ); if (ferror(t_inputfile)) { XP_ASSERT(FALSE); break; } (*p_genmime->write_buffer)(readbuffer,numread,p_genmime->closure); } XP_FileClose( t_inputfile ); (*p_genmime->write_buffer)("\n",1,p_genmime->closure); (*p_genmime->write_buffer)("\n",1,p_genmime->closure); } return TRUE; } static XP_Bool output_text_file(GenericMimeRelatedData *p_genmime, int16 p_index) { char *charSet; /*used by text attachments when retrieving the charset str identifier*/ if (p_genmime->m_pBoundarySpecifier) { (*p_genmime->write_buffer)(p_genmime->m_pBoundarySpecifier,strlen(p_genmime->m_pBoundarySpecifier),p_genmime->closure); (*p_genmime->write_buffer)("\n",1,p_genmime->closure); } (*p_genmime->write_buffer)(CONTENT_TYPE_TXT_MIMEREL,strlen(CONTENT_TYPE_TXT_MIMEREL),p_genmime->closure); charSet = (char *)INTL_CsidToCharsetNamePt(p_genmime->m_pCsids[p_index]); if (charSet) (*p_genmime->write_buffer)(charSet,strlen(charSet),p_genmime->closure); (*p_genmime->write_buffer)("\n",1,p_genmime->closure); (*p_genmime->write_buffer)(CONTENT_TRANS_MIMEREL,strlen(CONTENT_TRANS_MIMEREL),p_genmime->closure); (*p_genmime->write_buffer)(BIT7_MIMEREL,strlen(BIT7_MIMEREL),p_genmime->closure); (*p_genmime->write_buffer)("\n",1,p_genmime->closure); (*p_genmime->write_buffer)("\n",1,p_genmime->closure); return output_text_body(p_genmime,p_index); } static XP_Bool output_base64_file(GenericMimeRelatedData *p_genmime, int16 p_index) { char readbuffer[READ_BUFFER_LEN]; /*buffer to store incomming data*/ int16 numread; /*number of bytes read in each pass*/ XP_File t_inputfile; /*file pointer for input file*/ AttachmentFields *t_tempattach; /*temporary pointer for the attachment loop*/ MimeEncoderData *t_base64data; /*saving using base64 requires one of these*/ if (p_genmime->m_pBoundarySpecifier) { (*p_genmime->write_buffer)(p_genmime->m_pBoundarySpecifier,strlen(p_genmime->m_pBoundarySpecifier),p_genmime->closure); (*p_genmime->write_buffer)("\n",1,p_genmime->closure); } t_tempattach = p_genmime->m_pBase64Files[p_index]; if (!attachmentfields_validate(t_tempattach)) { XP_ASSERT(FALSE); return FALSE; } (*p_genmime->write_buffer)(CONTENT_TYPE_MIMEREL,strlen(CONTENT_TYPE_MIMEREL),p_genmime->closure); (*p_genmime->write_buffer)(t_tempattach->m_pContentType,strlen(t_tempattach->m_pContentType),p_genmime->closure); (*p_genmime->write_buffer)("\n",1,p_genmime->closure); (*p_genmime->write_buffer)(CONTENT_ID_MIMEREL,strlen(CONTENT_ID_MIMEREL),p_genmime->closure); (*p_genmime->write_buffer)("<",1,p_genmime->closure); (*p_genmime->write_buffer)(t_tempattach->m_pContentId ,strlen(t_tempattach->m_pContentId),p_genmime->closure); (*p_genmime->write_buffer)(">",1,p_genmime->closure); (*p_genmime->write_buffer)("\n",1,p_genmime->closure); (*p_genmime->write_buffer)(CONTENT_TRANS_MIMEREL,strlen(CONTENT_TRANS_MIMEREL),p_genmime->closure); (*p_genmime->write_buffer)(BASE64_MIMEREL,strlen(BASE64_MIMEREL),p_genmime->closure); (*p_genmime->write_buffer)("\n",1,p_genmime->closure); (*p_genmime->write_buffer)(CONTENT_DISPOSITION_MIMEREL,strlen(CONTENT_DISPOSITION_MIMEREL),p_genmime->closure); (*p_genmime->write_buffer)("\"",1,p_genmime->closure); /*begin quote*/ (*p_genmime->write_buffer)(t_tempattach->m_pDispositionName,strlen(t_tempattach->m_pDispositionName),p_genmime->closure); (*p_genmime->write_buffer)("\"",1,p_genmime->closure); /*end quote*/ (*p_genmime->write_buffer)("\n",1,p_genmime->closure); (*p_genmime->write_buffer)("\n",1,p_genmime->closure); if( (t_inputfile = XP_FileOpen( t_tempattach->m_pFilename, xpFileToPost,XP_FILE_READ_BIN )) != NULL ) { /* Attempt to read in READBUFLEN characters */ t_base64data = MimeB64EncoderInit(p_genmime->write_buffer,p_genmime->closure); if (!t_base64data) return FALSE; /* bad?*/ while (!feof( t_inputfile )) { numread = XP_FileRead( readbuffer, READ_BUFFER_LEN, t_inputfile ); if (ferror(t_inputfile)) { XP_ASSERT(FALSE); break; } MimeEncoderWrite(t_base64data,readbuffer,numread); } MimeEncoderDestroy(t_base64data,FALSE); XP_FileClose( t_inputfile ); (*p_genmime->write_buffer)("\n",1,p_genmime->closure); (*p_genmime->write_buffer)("\n",1,p_genmime->closure); } return TRUE; } XP_Bool GenericMime_Begin(GenericMimeRelatedData *p_genmime) { int16 i; /*counter*/ if (!genericmime_validate(p_genmime)) /*validation*/ { XP_ASSERT(FALSE); return FALSE; } if (p_genmime->m_iNumTextFiles == 1 && p_genmime->m_iNumBase64Files == 0) { return output_text_body(p_genmime,0); /*output only the body part*/ } (*p_genmime->write_buffer)(CONTENT_TYPE_MPR_MIMEREL,strlen(CONTENT_TYPE_MPR_MIMEREL),p_genmime->closure); (*p_genmime->write_buffer)(BOUNDARYSTR_MIMEREL,strlen(BOUNDARYSTR_MIMEREL),p_genmime->closure); (*p_genmime->write_buffer)("\"",1,p_genmime->closure); /*begin quote*/ if (p_genmime->m_pBoundarySpecifier) (*p_genmime->write_buffer)(p_genmime->m_pBoundarySpecifier,strlen(p_genmime->m_pBoundarySpecifier),p_genmime->closure); (*p_genmime->write_buffer)("\"",1,p_genmime->closure); /*end quote*/ (*p_genmime->write_buffer)("\n",1,p_genmime->closure); (*p_genmime->write_buffer)(XMOZSTATUS_MIMEREL,strlen(XMOZSTATUS_MIMEREL),p_genmime->closure); (*p_genmime->write_buffer)("\n",1,p_genmime->closure); (*p_genmime->write_buffer)("\n",1,p_genmime->closure); (*p_genmime->write_buffer)("\n",1,p_genmime->closure); for (i = 0; im_iNumTextFiles; i++) { output_text_file(p_genmime,i); } /* base64 encoding all files that need it.*/ for (i = 0; im_iNumBase64Files; i++) { if (!output_base64_file(p_genmime,i)) return FALSE; } if (p_genmime->m_pBoundarySpecifier) { (*p_genmime->write_buffer)(p_genmime->m_pBoundarySpecifier,strlen(p_genmime->m_pBoundarySpecifier),p_genmime->closure); (*p_genmime->write_buffer)("--",2,p_genmime->closure); } (*p_genmime->write_buffer)("\n",1,p_genmime->closure); return TRUE; } /* return number of text files after add. filename passed in will be deleted later by GenericMimeRelated Destroy function you are relinquishing ownership of the p_filename pointer. */ int GenericMime_AddTextFile(GenericMimeRelatedData *p_gendata, char *p_filename, int16 p_csid) { char **t_pfilenames; int16 *t_pcsids; if (!p_gendata || !p_filename) { XP_ASSERT(0); return -1; } t_pfilenames = p_gendata->m_pTextFiles; t_pcsids = p_gendata->m_pCsids; if ((!t_pfilenames || !t_pcsids) && p_gendata->m_iNumTextFiles) /*big problem*/ { XP_ASSERT(0); return -1; } p_gendata->m_iNumTextFiles = p_gendata->m_iNumTextFiles+1; p_gendata->m_pTextFiles = (char **)XP_ALLOC(p_gendata->m_iNumTextFiles * (sizeof (char *)) ); if (t_pfilenames) XP_MEMCPY(p_gendata->m_pTextFiles, t_pfilenames, sizeof(char *) * p_gendata->m_iNumTextFiles -1); p_gendata->m_pTextFiles[p_gendata->m_iNumTextFiles -1] = p_filename; p_gendata->m_pCsids = (int16 *)XP_ALLOC(p_gendata->m_iNumTextFiles * (sizeof (int16)) ); if (t_pcsids) XP_MEMCPY(p_gendata->m_pCsids, t_pcsids, sizeof(int16) * p_gendata->m_iNumTextFiles -1); p_gendata->m_pCsids[p_gendata->m_iNumTextFiles -1] = p_csid; return p_gendata->m_iNumTextFiles; } /* return number of text files after add. filename passed in will be deleted later by GenericMimeRelated Destroy function you are relinquishing ownership of the p_filename pointer. */ int GenericMime_AddBase64File(GenericMimeRelatedData *p_gendata, AttachmentFields *p_fields) { AttachmentFields **t_pfiles; if (!p_gendata || !p_fields) { XP_ASSERT(0); return -1; } t_pfiles = p_gendata->m_pBase64Files; if (!t_pfiles && p_gendata->m_iNumBase64Files) /*big problem*/ { XP_ASSERT(0); return -1; } p_gendata->m_iNumBase64Files = p_gendata->m_iNumBase64Files+1; p_gendata->m_pBase64Files = (AttachmentFields **)XP_ALLOC(p_gendata->m_iNumBase64Files * (sizeof (AttachmentFields *)) ); if (t_pfiles) XP_MEMCPY(p_gendata->m_pBase64Files, t_pfiles, sizeof(char *) * p_gendata->m_iNumBase64Files -1); p_gendata->m_pBase64Files[p_gendata->m_iNumBase64Files -1] = p_fields; return p_gendata->m_iNumBase64Files; } #endif /* MOZ_ENDER_MIME */