Back to index

lightning-sunbird  0.9+nobinonly
nsImportTranslator.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "ImportOutFile.h"
00039 #include "nsImportTranslator.h"
00040 
00041 #include "ImportCharSet.h"
00042 
00043 
00044 PRBool nsImportTranslator::ConvertToFile( const PRUint8 * pIn, PRUint32 inLen, ImportOutFile *pOutFile, PRUint32 *pProcessed) 
00045 { 
00046        if (pProcessed)
00047               *pProcessed = inLen;
00048        return( pOutFile->WriteData( pIn, inLen));
00049 }
00050 
00051 void CMHTranslator::ConvertBuffer( const PRUint8 * pIn, PRUint32 inLen, PRUint8 * pOut)
00052 {
00053        while (inLen) {
00054               if (!ImportCharSet::IsUSAscii( *pIn) || ImportCharSet::Is822SpecialChar( *pIn) || ImportCharSet::Is822CtlChar( *pIn) ||
00055                      (*pIn == ImportCharSet::cSpaceChar) || (*pIn == '*') || (*pIn == '\'') ||
00056                      (*pIn == '%')) {
00057                      // needs to be encode as %hex val
00058                      *pOut = '%'; pOut++;
00059                      ImportCharSet::ByteToHex( *pIn, pOut);
00060                      pOut += 2;
00061               }
00062               else {
00063                      *pOut = *pIn;
00064                      pOut++;
00065               }
00066               pIn++; inLen--;
00067        }
00068        *pOut = 0;
00069 }
00070 
00071 PRBool CMHTranslator::ConvertToFile( const PRUint8 * pIn, PRUint32 inLen, ImportOutFile *pOutFile, PRUint32 *pProcessed)
00072 {
00073        PRUint8              hex[2];
00074        while (inLen) {
00075               if (!ImportCharSet::IsUSAscii( *pIn) || ImportCharSet::Is822SpecialChar( *pIn) || ImportCharSet::Is822CtlChar( *pIn) ||
00076                      (*pIn == ImportCharSet::cSpaceChar) || (*pIn == '*') || (*pIn == '\'') ||
00077                      (*pIn == '%')) {
00078                      // needs to be encode as %hex val
00079                      if (!pOutFile->WriteByte( '%'))
00080                             return( PR_FALSE);
00081                      ImportCharSet::ByteToHex( *pIn, hex);
00082                      if (!pOutFile->WriteData( hex, 2))
00083                             return( PR_FALSE);
00084               }
00085               else {
00086                      if (!pOutFile->WriteByte( *pIn))
00087                             return( PR_FALSE);
00088               }
00089               pIn++; inLen--;
00090        }
00091 
00092        if (pProcessed)
00093               *pProcessed = inLen;
00094 
00095        return( PR_TRUE);
00096 }
00097 
00098 
00099 PRBool C2047Translator::ConvertToFileQ( const PRUint8 * pIn, PRUint32 inLen, ImportOutFile *pOutFile, PRUint32 *pProcessed)
00100 {
00101        if (!inLen)
00102               return( PR_TRUE);
00103 
00104        int           maxLineLen = 64;
00105        int           curLineLen = m_startLen;
00106        PRBool startLine = PR_TRUE;
00107 
00108        PRUint8       hex[2];
00109        while (inLen) {
00110               if (startLine) {
00111                      if (!pOutFile->WriteStr( " =?"))
00112                             return( PR_FALSE);
00113                      if (!pOutFile->WriteStr( m_charset.get()))
00114                             return( PR_FALSE);
00115                      if (!pOutFile->WriteStr( "?q?"))
00116                             return( PR_FALSE);
00117                      curLineLen += (6 + m_charset.Length());
00118                      startLine = PR_FALSE;
00119               }
00120 
00121               if (!ImportCharSet::IsUSAscii( *pIn) || ImportCharSet::Is822SpecialChar( *pIn) || ImportCharSet::Is822CtlChar( *pIn) ||
00122                      (*pIn == ImportCharSet::cSpaceChar) || (*pIn == '?') || (*pIn == '=')) {
00123                      // needs to be encode as =hex val
00124                      if (!pOutFile->WriteByte( '='))
00125                             return( PR_FALSE);
00126                      ImportCharSet::ByteToHex( *pIn, hex);
00127                      if (!pOutFile->WriteData( hex, 2))
00128                             return( PR_FALSE);
00129                      curLineLen += 3;
00130               }
00131               else {
00132                      if (!pOutFile->WriteByte( *pIn))
00133                             return( PR_FALSE);
00134                      curLineLen++;
00135               }
00136               pIn++; inLen--;
00137               if (curLineLen > maxLineLen) {
00138                      if (!pOutFile->WriteStr( "?="))
00139                             return( PR_FALSE);
00140                      if (inLen) {
00141                             if (!pOutFile->WriteStr( "\x0D\x0A "))
00142                                    return( PR_FALSE);
00143                      }
00144 
00145                      startLine = PR_TRUE;
00146                      curLineLen = 0;
00147               }
00148        }
00149 
00150        if (!startLine) {
00151               // end the encoding!
00152               if (!pOutFile->WriteStr( "?="))
00153                      return( PR_FALSE);
00154        }
00155 
00156        if (pProcessed)
00157               *pProcessed = inLen;
00158 
00159        return( PR_TRUE);
00160 }
00161 
00162 PRBool C2047Translator::ConvertToFile( const PRUint8 * pIn, PRUint32 inLen, ImportOutFile *pOutFile, PRUint32 *pProcessed)
00163 {
00164        if (m_useQuotedPrintable)
00165               return( ConvertToFileQ( pIn, inLen, pOutFile, pProcessed));
00166 
00167        if (!inLen)
00168               return( PR_TRUE);
00169 
00170        int                  maxLineLen = 64;
00171        int                  curLineLen = m_startLen;
00172        PRBool        startLine = PR_TRUE;
00173        int                  encodeMax;
00174        PRUint8 *     pEncoded = new PRUint8[maxLineLen * 2];
00175 
00176        while (inLen) {
00177               if (startLine) {
00178                      if (!pOutFile->WriteStr( " =?")) {
00179                             delete [] pEncoded;
00180                             return( PR_FALSE);
00181                      }
00182                      if (!pOutFile->WriteStr( m_charset.get())) {
00183                             delete [] pEncoded;
00184                             return( PR_FALSE);
00185                      }
00186                      if (!pOutFile->WriteStr( "?b?")) {
00187                             delete [] pEncoded;
00188                             return( PR_FALSE);
00189                      }
00190                      curLineLen += (6 + m_charset.Length());
00191                      startLine = PR_FALSE;
00192               }
00193               encodeMax = maxLineLen - curLineLen;
00194               encodeMax *= 3;
00195               encodeMax /= 4;
00196               if ((PRUint32)encodeMax > inLen)
00197                      encodeMax = (int)inLen;
00198 
00199               // encode the line, end the line
00200               // then continue. Update curLineLen, pIn, startLine, and inLen
00201               UMimeEncode::ConvertBuffer( pIn, encodeMax, pEncoded, maxLineLen, maxLineLen, "\x0D\x0A");
00202 
00203               if (!pOutFile->WriteStr( (const char *)pEncoded)) {
00204                      delete [] pEncoded;
00205                      return( PR_FALSE);
00206               }
00207 
00208               pIn += encodeMax;
00209               inLen -= encodeMax;
00210               startLine = PR_TRUE;
00211               curLineLen = 0;
00212               if (!pOutFile->WriteStr( "?=")) {
00213                      delete [] pEncoded;
00214                      return( PR_FALSE);
00215               }
00216               if (inLen) {
00217                      if (!pOutFile->WriteStr( "\x0D\x0A ")) {
00218                             delete [] pEncoded;
00219                             return( PR_FALSE);
00220                      }
00221               }
00222        }
00223 
00224        delete [] pEncoded;
00225 
00226        if (pProcessed)
00227               *pProcessed = inLen;
00228 
00229        return( PR_TRUE);
00230 }
00231 
00232 
00233 PRUint32      UMimeEncode::GetBufferSize( PRUint32 inBytes)
00234 {
00235        // it takes 4 base64 bytes to represent 3 regular bytes
00236        inBytes += 3;
00237        inBytes /= 3;
00238        inBytes *= 4;
00239        // This should be plenty, but just to be safe
00240        inBytes += 4;
00241 
00242        // now allow for end of line characters
00243        inBytes += ((inBytes + 39) / 40) * 4;
00244 
00245        return( inBytes);
00246 }
00247 
00248 static PRUint8 gBase64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00249 
00250 PRUint32 UMimeEncode::ConvertBuffer( const PRUint8 * pIn, PRUint32 inLen, PRUint8 * pOut, PRUint32 maxLen, PRUint32 firstLineLen, const char * pEolStr)
00251 {
00252 
00253        PRUint32      pos = 0;
00254        PRUint32      len = 0;
00255        PRUint32      lineLen = 0;
00256        PRUint32      maxLine = firstLineLen;
00257        int    eolLen = 0;
00258        if (pEolStr)
00259               eolLen = strlen( pEolStr);
00260 
00261        while ((pos + 2) < inLen) {
00262               // Encode 3 bytes
00263               *pOut = gBase64[*pIn >> 2];
00264               pOut++; len++; lineLen++;
00265               *pOut = gBase64[(((*pIn) & 0x3)<< 4) | (((*(pIn + 1)) & 0xF0) >> 4)];
00266               pIn++; pOut++; len++; lineLen++;
00267               *pOut = gBase64[(((*pIn) & 0xF) << 2) | (((*(pIn + 1)) & 0xC0) >>6)];
00268               pIn++; pOut++; len++; lineLen++;
00269               *pOut = gBase64[(*pIn) & 0x3F];
00270               pIn++; pOut++; len++; lineLen++;
00271               pos += 3;
00272               if (lineLen >= maxLine) {
00273                      lineLen = 0;
00274                      maxLine = maxLen;
00275                      if (pEolStr) {
00276                             memcpy( pOut, pEolStr, eolLen);
00277                             pOut += eolLen;
00278                             len += eolLen;
00279                      }
00280               }
00281        }
00282 
00283        if ((pos < inLen) && ((lineLen + 3) > maxLine)) {
00284               lineLen = 0;
00285               maxLine = maxLen;
00286               if (pEolStr) {
00287                      memcpy( pOut, pEolStr, eolLen);
00288                      pOut += eolLen;
00289                      len += eolLen;
00290               }
00291        }
00292 
00293        if (pos < inLen) {
00294               // Get the last few bytes!
00295               *pOut = gBase64[*pIn >> 2];
00296               pOut++; len++;
00297               pos++;
00298               if (pos < inLen) {
00299                      *pOut = gBase64[(((*pIn) & 0x3)<< 4) | (((*(pIn + 1)) & 0xF0) >> 4)];
00300                      pIn++; pOut++; pos++; len++;
00301                      if (pos < inLen) {
00302                             // Should be dead code!! (Then why is it here doofus?)
00303                             *pOut = gBase64[(((*pIn) & 0xF) << 2) | (((*(pIn + 1)) & 0xC0) >>6)];
00304                             pIn++; pOut++; len++;
00305                             *pOut = gBase64[(*pIn) & 0x3F];
00306                             pos++; pOut++; len++;
00307                      }
00308                      else {
00309                             *pOut = gBase64[(((*pIn) & 0xF) << 2)];
00310                             pOut++; len++;
00311                             *pOut = '=';
00312                             pOut++; len++;
00313                      }
00314               }
00315               else {
00316                      *pOut = gBase64[(((*pIn) & 0x3)<< 4)];
00317                      pOut++; len++;
00318                      *pOut = '=';
00319                      pOut++; len++;
00320                      *pOut = '=';
00321                      pOut++; len++;
00322               }      
00323        }
00324 
00325        *pOut = 0;
00326 
00327        return( len);
00328 }