/* -*- 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.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ #include "stdio.h" #include "nsMimeRebuffer.h" #include "nsMimeEmitter.h" #include "plstr.h" #include "nsEmitterUtils.h" #include "nsMailHeaders.h" #include "nscore.h" /* * This function will be used by the factory to generate an * mime object class object.... */ nsresult NS_NewMimeEmitter(nsIMimeEmitter ** aInstancePtrResult) { /* note this new macro for assertions...they can take a string describing the assertion */ nsresult result = NS_OK; NS_PRECONDITION(nsnull != aInstancePtrResult, "nsnull ptr"); if (nsnull != aInstancePtrResult) { nsMimeEmitter *obj = new nsMimeEmitter(); if (obj) return obj->QueryInterface(nsIMimeEmitter::GetIID(), (void**) aInstancePtrResult); else return NS_ERROR_OUT_OF_MEMORY; /* we couldn't allocate the object */ } else return NS_ERROR_NULL_POINTER; /* aInstancePtrResult was NULL....*/ } /* * The following macros actually implement addref, release and * query interface for our component. */ NS_IMPL_ADDREF(nsMimeEmitter) NS_IMPL_RELEASE(nsMimeEmitter) NS_IMPL_QUERY_INTERFACE(nsMimeEmitter, nsIMimeEmitter::GetIID()); /* we need to pass in the interface ID of this interface */ /* * nsIMimeEmitter definitions.... */ nsMimeEmitter::nsMimeEmitter() { /* the following macro is used to initialize the ref counting data */ NS_INIT_REFCNT(); mOutStream = NULL; mBufferMgr = NULL; mTotalWritten = 0; mTotalRead = 0; mDocHeader = PR_FALSE; mAttachContentType = NULL; #ifdef DEBUG_rhp mLogFile = NULL; /* Temp file to put generated HTML into. */ mReallyOutput = PR_FALSE; #endif } nsMimeEmitter::~nsMimeEmitter(void) { if (mBufferMgr) delete mBufferMgr; } // Set the output stream for processed data. nsresult nsMimeEmitter::SetOutputStream(nsINetOStream *outStream) { return NS_OK; } // Note - these is setup only...you should not write // anything to the stream since these may be image data // output streams, etc... nsresult nsMimeEmitter::Initialize(nsINetOStream *outStream) { mOutStream = outStream; // Create rebuffering object mBufferMgr = new MimeRebuffer(); // Counters for output stream mTotalWritten = 0; mTotalRead = 0; #ifdef DEBUG_rhp PR_Delete("C:\\email.html"); mLogFile = PR_Open("C:\\email.html", PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, 493); #endif /* DEBUG */ return NS_OK; } // Note - this is teardown only...you should not write // anything to the stream since these may be image data // output streams, etc... nsresult nsMimeEmitter::Complete() { #ifdef DEBUG_rhp mReallyOutput = PR_FALSE; #endif // If we are here and still have data to write, we should try // to flush it...if we try and fail, we should probably return // an error! PRUint32 written; if (mBufferMgr->GetSize() > 0) Write("", 0, &written); printf("TOTAL WRITTEN = %d\n", mTotalWritten); printf("LEFTOVERS = %d\n", mBufferMgr->GetSize()); #ifdef DEBUG_rhp if (mLogFile) PR_Close(mLogFile); #endif return NS_OK; } // Header handling routines. nsresult nsMimeEmitter::StartHeader(PRBool rootMailHeader, PRBool headerOnly, const char *msgID, const char *outCharset) { #ifdef DEBUG_rhp mReallyOutput = PR_TRUE; #endif mDocHeader = rootMailHeader; if (mDocHeader) { if ( (!headerOnly) && (outCharset) && (*outCharset) ) { UtilityWrite(""); } UtilityWrite("
"); } else UtilityWrite("
"); return NS_OK; } nsresult nsMimeEmitter::AddHeaderField(const char *field, const char *value) { #ifdef DEBUG_rhp mReallyOutput = PR_TRUE; #endif if ( (!field) || (!value) ) return NS_OK; char *newValue = nsEscapeHTML(value); if (!newValue) return NS_OK; UtilityWrite(""); UtilityWrite(""); UtilityWrite(""); UtilityWrite(""); PR_FREEIF(newValue); return NS_OK; } nsresult nsMimeEmitter::EndHeader() { #ifdef DEBUG_rhp mReallyOutput = PR_TRUE; #endif UtilityWrite("
"); UtilityWrite("
"); UtilityWrite(""); UtilityWrite(field); UtilityWrite(":"); UtilityWrite(""); UtilityWrite("
"); UtilityWrite("
"); UtilityWrite(newValue); UtilityWrite("
"); return NS_OK; } nsresult nsMimeEmitter::ProcessContentType(const char *ct) { if (mAttachContentType) { PR_FREEIF(mAttachContentType); mAttachContentType = NULL; } if ( (!ct) || (!*ct) ) return NS_OK; char *slash = PL_strchr(ct, '/'); if (!slash) mAttachContentType = PL_strdup(ct); else { PRInt32 size = (PL_strlen(ct) + 4 + 1); mAttachContentType = (char *)PR_MALLOC( size ); if (!mAttachContentType) return NS_ERROR_OUT_OF_MEMORY; memset(mAttachContentType, 0, size); PL_strcpy(mAttachContentType, ct); char *newSlash = PL_strchr(mAttachContentType, '/'); *newSlash = '\0'; PL_strcat(mAttachContentType, "%2F"); PL_strcat(mAttachContentType, (slash + 1)); } return NS_OK; } // Attachment handling routines nsresult nsMimeEmitter::StartAttachment(const char *name, const char *contentType, const char *url) { #ifdef DEBUG_rhp mReallyOutput = PR_TRUE; #endif PR_FREEIF(mAttachContentType); mAttachContentType = NULL; ProcessContentType(contentType); UtilityWrite("
"); UtilityWrite(""); UtilityWrite(""); UtilityWrite(""); UtilityWrite(""); UtilityWrite(""); UtilityWrite("
"); if (mAttachContentType) { UtilityWrite(""); } UtilityWrite(""); UtilityWrite(name); if (mAttachContentType) UtilityWrite(""); UtilityWrite(""); UtilityWrite(""); return NS_OK; } nsresult nsMimeEmitter::AddAttachmentField(const char *field, const char *value) { #ifdef DEBUG_rhp mReallyOutput = PR_TRUE; #endif // Don't let bad things happen if ( (!value) || (!*value) ) return NS_OK; char *newValue = nsEscapeHTML(value); PRBool linkIt = (!PL_strcmp(HEADER_X_MOZILLA_PART_URL, field)); // // For now, let's not output the long URL field, but when prefs are // working this will change. // if (linkIt) return NS_OK; UtilityWrite(""); UtilityWrite(""); UtilityWrite(""); UtilityWrite(""); PR_FREEIF(newValue); return NS_OK; } nsresult nsMimeEmitter::EndAttachment() { #ifdef DEBUG_rhp mReallyOutput = PR_TRUE; #endif PR_FREEIF(mAttachContentType); UtilityWrite("
"); UtilityWrite("
"); UtilityWrite(""); UtilityWrite(field); UtilityWrite(":"); UtilityWrite(""); UtilityWrite("
"); UtilityWrite("
"); if (linkIt) { UtilityWrite(""); } UtilityWrite(newValue); if (linkIt) UtilityWrite(""); UtilityWrite("
"); UtilityWrite("
"); UtilityWrite("
"); UtilityWrite("
"); return NS_OK; } // Attachment handling routines nsresult nsMimeEmitter::StartBody(PRBool bodyOnly, const char *msgID, const char *outCharset) { #ifdef DEBUG_rhp mReallyOutput = PR_TRUE; #endif if ((bodyOnly) && (outCharset) && (*outCharset)) { UtilityWrite(""); } return NS_OK; } nsresult nsMimeEmitter::WriteBody(const char *buf, PRUint32 size, PRUint32 *amountWritten) { #ifdef DEBUG_rhp mReallyOutput = PR_TRUE; #endif Write(buf, size, amountWritten); return NS_OK; } nsresult nsMimeEmitter::EndBody() { #ifdef DEBUG_rhp mReallyOutput = PR_FALSE; #endif return NS_OK; } //////////////////////////////////////////////////////////////////////////////// // These are routines necessary for the C based routines in libmime // to access the new world streams. //////////////////////////////////////////////////////////////////////////////// nsresult nsMimeEmitter::Write(const char *buf, PRUint32 size, PRUint32 *amountWritten) { unsigned int written = 0; PRUint32 rc, aReadyCount = 0; #ifdef DEBUG_rhp if ((mLogFile) && (mReallyOutput)) PR_Write(mLogFile, buf, size); #endif // // Make sure that the buffer we are "pushing" into has enough room // for the write operation. If not, we have to buffer, return, and get // it on the next time through // *amountWritten = 0; rc = mOutStream->WriteReady(&aReadyCount); // First, handle any old buffer data... if (mBufferMgr->GetSize() > 0) { if (aReadyCount >= mBufferMgr->GetSize()) { rc += mOutStream->Write(mBufferMgr->GetBuffer(), mBufferMgr->GetSize(), &written); mTotalWritten += written; mBufferMgr->ReduceBuffer(written); } else { rc += mOutStream->Write(mBufferMgr->GetBuffer(), aReadyCount, &written); mTotalWritten += written; mBufferMgr->ReduceBuffer(written); mBufferMgr->IncreaseBuffer(buf, size); return rc; } } // Now, deal with the new data the best way possible... rc = mOutStream->WriteReady(&aReadyCount); if (aReadyCount >= size) { rc += mOutStream->Write(buf, size, &written); mTotalWritten += written; *amountWritten = written; return rc; } else { rc += mOutStream->Write(buf, aReadyCount, &written); mTotalWritten += written; mBufferMgr->IncreaseBuffer(buf+written, (size-written)); *amountWritten = written; return rc; } } nsresult nsMimeEmitter::UtilityWrite(const char *buf) { PRInt32 tmpLen = PL_strlen(buf); PRUint32 written; Write(buf, tmpLen, &written); #ifdef DEBUG // Write("\r\n", 2, &written); #endif return NS_OK; }