Back to index

enigmail  1.4.3
nsEnigMimeWriter.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public
00005  * License Version 1.1 (the "MPL"); you may not use this file
00006  * except in compliance with the MPL. You may obtain a copy of
00007  * the MPL at http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the MPL is distributed on an "AS
00010  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
00011  * implied. See the MPL for the specific language governing
00012  * rights and limitations under the MPL.
00013  *
00014  * The Original Code is Enigmail.
00015  *
00016  * The Initial Developer of the Original Code is Ramalingam Saravanan.
00017  * Portions created by Ramalingam Saravanan <sarava@sarava.net> are
00018  * Copyright (C) 2002 Ramalingam Saravanan. All Rights Reserved.
00019  *
00020  * Contributor(s):
00021  * Patrick Brunschwig <patrick@mozilla-enigmail.org>
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  * ***** END LICENSE BLOCK ***** */
00035 
00036 // Logging of debug output
00037 // The following define statement should occur before any include statements
00038 #define FORCE_PR_LOG       /* Allow logging even in release build */
00039 
00040 #include "enigmail.h"
00041 #include "prlog.h"
00042 #include "nsCOMPtr.h"
00043 #include "nsIThread.h"
00044 #include "nsIInputStream.h"
00045 
00046 #include "nsEnigMimeWriter.h"
00047 
00048 #ifdef PR_LOGGING
00049 PRLogModuleInfo* gEnigMimeWriterLog = NULL;
00050 #endif
00051 
00052 #define ERROR_LOG(args)    PR_LOG(gEnigMimeWriterLog,PR_LOG_ERROR,args)
00053 #define WARNING_LOG(args)  PR_LOG(gEnigMimeWriterLog,PR_LOG_WARNING,args)
00054 #define DEBUG_LOG(args)    PR_LOG(gEnigMimeWriterLog,PR_LOG_DEBUG,args)
00055 
00056 static const PRUint32 kCharMax = 1024;
00057 
00059 
00060 // nsEnigMimeWriter implementation
00061 
00062 // nsISupports implementation
00063 NS_IMPL_THREADSAFE_ISUPPORTS3(nsEnigMimeWriter,
00064                               nsIEnigMimeWriter,
00065                               nsIRequestObserver,
00066                               nsIStreamListener)
00067 
00068 
00069 // nsEnigMimeWriter implementation
00070 nsEnigMimeWriter::nsEnigMimeWriter()
00071   : mStream(nsnull),
00072     mForceCRLF(PR_FALSE),
00073 
00074     mClosed(PR_FALSE),
00075     mLastCR(PR_FALSE),
00076 
00077     mByteCount(0)
00078 {
00079     NS_INIT_ISUPPORTS();
00080 
00081 #ifdef PR_LOGGING
00082   if (gEnigMimeWriterLog == nsnull) {
00083     gEnigMimeWriterLog = PR_NewLogModule("nsEnigMimeWriter");
00084   }
00085 #endif
00086 
00087 #ifdef FORCE_PR_LOG
00088   nsresult rv;
00089   nsCOMPtr<nsIThread> myThread;
00090   rv = ENIG_GET_THREAD(myThread);
00091   DEBUG_LOG(("nsEnigMimeWriter:: <<<<<<<<< CTOR(%p): myThread=%p\n",
00092          this, myThread.get()));
00093 #endif
00094 }
00095 
00096 
00097 nsEnigMimeWriter::~nsEnigMimeWriter()
00098 {
00099   nsresult rv;
00100 #ifdef FORCE_PR_LOG
00101   nsCOMPtr<nsIThread> myThread;
00102   rv = ENIG_GET_THREAD(myThread);
00103   DEBUG_LOG(("nsEnigMimeWriter:: >>>>>>>>> DTOR(%p): myThread=%p\n",
00104          this, myThread.get()));
00105 #endif
00106   mStream = nsnull;
00107 }
00108 
00109 
00111 // nsIEnigMimeWriter methods
00113 
00114 NS_IMETHODIMP
00115 nsEnigMimeWriter::Init(nsIOutputStream* aStream,
00116                          EMBool forceCRLF)
00117 {
00118   DEBUG_LOG(("nsEnigMimeWriter::Init: %d\n", forceCRLF));
00119 
00120   if (!aStream)
00121     return NS_ERROR_NULL_POINTER;
00122 
00123   mStream = aStream;
00124 
00125   mForceCRLF = forceCRLF;
00126 
00127   return NS_OK;
00128 }
00129 
00130 
00131 NS_IMETHODIMP
00132 nsEnigMimeWriter::Write(const char* buf, PRUint32 count)
00133 {
00134   nsresult rv;
00135 
00136   DEBUG_LOG(("nsEnigMimeWriter::Write: %d\n", count));
00137 
00138   if (!mForceCRLF)
00139     return WriteStream(buf, count);
00140 
00141   PRUint32 offset = 0;
00142   for (PRUint32 j=0; j<count; j++) {
00143     if (buf[j] == '\n') {
00144 
00145       if (mLastCR) {
00146         rv = WriteStream(&buf[offset], j-offset+1);
00147         if (NS_FAILED(rv)) return rv;
00148 
00149       } else {
00150         rv = WriteStream(&buf[offset], j-offset);
00151         if (NS_FAILED(rv)) return rv;
00152 
00153         rv = WriteStream("\r\n", 2);
00154         if (NS_FAILED(rv)) return rv;
00155       }
00156 
00157       offset = j+1;
00158 
00159     } else if (mLastCR) {
00160       rv = WriteStream(&buf[offset], j-offset);
00161       if (NS_FAILED(rv)) return rv;
00162 
00163       rv = WriteStream("\r\n", 2);
00164       if (NS_FAILED(rv)) return rv;
00165 
00166       offset = j;
00167     }
00168 
00169     mLastCR = (buf[j] == '\r');
00170   }
00171 
00172   if (offset < count) {
00173     rv = WriteStream(&buf[offset], count-offset);
00174     if (NS_FAILED(rv)) return rv;
00175   }
00176 
00177   return NS_OK;
00178 }
00179 
00180 
00181 nsresult
00182 nsEnigMimeWriter::WriteStream(const char* buf, PRUint32 count)
00183 {
00184   DEBUG_LOG(("nsEnigMimeWriter::WriteStream: %d\n", count));
00185   PRUint32 writeCount;
00186 
00187   if (!mStream)
00188     return NS_ERROR_NOT_INITIALIZED;
00189 
00190   while (count > 0) {
00191     nsresult rv = mStream->Write(buf, count, &writeCount);
00192     if (NS_FAILED(rv) || (writeCount != count))
00193       return NS_ERROR_FAILURE;
00194 
00195     mByteCount += writeCount;
00196 
00197     count -= writeCount;
00198     buf += writeCount;
00199   }
00200 
00201   return NS_OK;
00202 }
00203 
00204 
00205 NS_IMETHODIMP
00206 nsEnigMimeWriter::GetBytesWritten(PRUint32* _retval)
00207 {
00208   NS_ENSURE_ARG(_retval);
00209   DEBUG_LOG(("nsEnigMimeWriter::GetBytesWritten: %d\n", mByteCount));
00210 
00211   *_retval = mByteCount;
00212   return NS_OK;
00213 }
00214 
00215 
00216 NS_IMETHODIMP
00217 nsEnigMimeWriter::Close()
00218 {
00219   nsresult rv;
00220 
00221   DEBUG_LOG(("nsEnigMimeWriter::Close: \n"));
00222 
00223   if (mClosed)
00224     return NS_OK;
00225 
00226   if (mLastCR) {
00227     rv = WriteStream("\n", 1);
00228     if (NS_FAILED(rv)) return rv;
00229   }
00230 
00231   mClosed = PR_TRUE;
00232 
00233   mStream = nsnull;
00234 
00235   return NS_OK;
00236 }
00237 
00239 // nsIRequestObserver methods
00241 
00242 NS_IMETHODIMP
00243 nsEnigMimeWriter::OnStartRequest(nsIRequest *aRequest,
00244                                  nsISupports *aContext)
00245 {
00246   DEBUG_LOG(("nsEnigMimeWriter::OnStartRequest:\n"));
00247 
00248   return NS_OK;
00249 }
00250 
00251 NS_IMETHODIMP
00252 nsEnigMimeWriter::OnStopRequest(nsIRequest* aRequest,
00253                                 nsISupports* aContext,
00254                                 nsresult aStatus)
00255 {
00256   DEBUG_LOG(("nsEnigMimeWriter::OnStopRequest:\n"));
00257 
00258   return NS_OK;
00259 }
00260 
00262 // nsIStreamWriter method
00264 
00265 NS_IMETHODIMP
00266 nsEnigMimeWriter::OnDataAvailable(nsIRequest* aRequest,
00267                                   nsISupports* aContext,
00268                                   nsIInputStream *aInputStream,
00269                                   PRUint32 aSourceOffset,
00270                                   PRUint32 aLength)
00271 {
00272   nsresult rv = NS_OK;
00273 
00274   DEBUG_LOG(("nsEnigMimeWriter::OnDataAVailable: %d\n", aLength));
00275 
00276   if (!mStream)
00277     return NS_ERROR_NOT_INITIALIZED;
00278 
00279   char buf[kCharMax];
00280   PRUint32 readCount, readMax;
00281 
00282   while (aLength > 0) {
00283     readMax = (aLength < kCharMax) ? aLength : kCharMax;
00284     rv = aInputStream->Read((char *) buf, readMax, &readCount);
00285 
00286     if (NS_FAILED(rv)){
00287       ERROR_LOG(("nsEnigMimeWriter::OnDataAvailable: Error in reading from input stream, %x\n", rv));
00288       return rv;
00289     }
00290 
00291     if (readCount <= 0)
00292       break;
00293 
00294     aLength -= readCount;
00295     aSourceOffset += readCount;
00296 
00297     rv = Write(buf, readCount);
00298     if (NS_FAILED(rv)) return rv;
00299   }
00300 
00301   return NS_OK;
00302 }