intl/uconv/util/nsUCSupport.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "nsUCSupport.h"
     7 #include "nsUnicodeDecodeHelper.h"
     8 #include "nsUnicodeEncodeHelper.h"
     9 #include <algorithm>
    11 #define DEFAULT_BUFFER_CAPACITY 16
    13 // XXX review the buffer growth limitation code
    15 //----------------------------------------------------------------------
    16 // Class nsBasicDecoderSupport [implementation]
    18 nsBasicDecoderSupport::nsBasicDecoderSupport()
    19   : mErrBehavior(kOnError_Recover)
    20 {
    21 }
    23 nsBasicDecoderSupport::~nsBasicDecoderSupport()
    24 {
    25 }
    27 //----------------------------------------------------------------------
    28 // Interface nsISupports [implementation]
    30 #ifdef DEBUG
    31 NS_IMPL_ISUPPORTS(nsBasicDecoderSupport,
    32                   nsIUnicodeDecoder,
    33                   nsIBasicDecoder)
    34 #else
    35 NS_IMPL_ISUPPORTS(nsBasicDecoderSupport, nsIUnicodeDecoder)
    36 #endif
    38 //----------------------------------------------------------------------
    39 // Interface nsIUnicodeDecoder [implementation]
    41 void
    42 nsBasicDecoderSupport::SetInputErrorBehavior(int32_t aBehavior)
    43 {
    44   NS_ABORT_IF_FALSE(aBehavior == kOnError_Recover || aBehavior == kOnError_Signal,
    45                     "Unknown behavior for SetInputErrorBehavior");
    46   mErrBehavior = aBehavior;
    47 }
    49 char16_t
    50 nsBasicDecoderSupport::GetCharacterForUnMapped()
    51 {
    52   return char16_t(0xfffd); // Unicode REPLACEMENT CHARACTER
    53 }
    55 //----------------------------------------------------------------------
    56 // Class nsBufferDecoderSupport [implementation]
    58 nsBufferDecoderSupport::nsBufferDecoderSupport(uint32_t aMaxLengthFactor)
    59   : nsBasicDecoderSupport(),
    60     mMaxLengthFactor(aMaxLengthFactor)
    61 {
    62   mBufferCapacity = DEFAULT_BUFFER_CAPACITY;
    63   mBuffer = new char[mBufferCapacity];
    65   Reset();
    66 }
    68 nsBufferDecoderSupport::~nsBufferDecoderSupport()
    69 {
    70   delete [] mBuffer;
    71 }
    73 void nsBufferDecoderSupport::FillBuffer(const char ** aSrc, int32_t aSrcLength)
    74 {
    75   int32_t bcr = std::min(mBufferCapacity - mBufferLength, aSrcLength);
    76   memcpy(mBuffer + mBufferLength, *aSrc, bcr);
    77   mBufferLength += bcr;
    78   (*aSrc) += bcr;
    79 }
    81 //----------------------------------------------------------------------
    82 // Subclassing of nsBasicDecoderSupport class [implementation]
    84 NS_IMETHODIMP nsBufferDecoderSupport::Convert(const char * aSrc,
    85                                               int32_t * aSrcLength,
    86                                               char16_t * aDest,
    87                                               int32_t * aDestLength)
    88 {
    89   // we do all operations using pointers internally
    90   const char * src = aSrc;
    91   const char * srcEnd = aSrc + *aSrcLength;
    92   char16_t * dest = aDest;
    93   char16_t * destEnd = aDest + *aDestLength;
    95   int32_t bcr, bcw; // byte counts for read & write;
    96   nsresult res = NS_OK;
    98   // do we have some residual data from the last conversion?
    99   if (mBufferLength > 0) {
   100     if (dest == destEnd) {
   101       res = NS_OK_UDEC_MOREOUTPUT;
   102     } else {
   103       for (;;) {
   104         // we need new data to add to the buffer
   105         if (src == srcEnd) {
   106           res = NS_OK_UDEC_MOREINPUT;
   107           break;
   108         }
   110         // fill that buffer
   111         int32_t buffLen = mBufferLength;  // initial buffer length
   112         FillBuffer(&src, srcEnd - src);
   114         // convert that buffer
   115         bcr = mBufferLength;
   116         bcw = destEnd - dest;
   117         res = ConvertNoBuff(mBuffer, &bcr, dest, &bcw);
   118         dest += bcw;
   120         // Detect invalid input character
   121         if (res == NS_ERROR_ILLEGAL_INPUT && mErrBehavior == kOnError_Signal) {
   122           break;
   123         }
   125         if ((res == NS_OK_UDEC_MOREINPUT) && (bcw == 0)) {
   126           res = NS_ERROR_UNEXPECTED;
   127 #if defined(DEBUG_yokoyama) || defined(DEBUG_ftang)
   128           NS_ERROR("This should not happen. Internal buffer may be corrupted.");
   129 #endif
   130           break;
   131         } else {
   132           if (bcr < buffLen) {
   133             // we didn't convert that residual data - unfill the buffer
   134             src -= mBufferLength - buffLen;
   135             mBufferLength = buffLen;
   136 #if defined(DEBUG_yokoyama) || defined(DEBUG_ftang)
   137             NS_ERROR("This should not happen. Internal buffer may be corrupted.");
   138 #endif
   139           } else {
   140             // the buffer and some extra data was converted - unget the rest
   141             src -= mBufferLength - bcr;
   142             mBufferLength = 0;
   143             res = NS_OK;
   144           }
   145           break;
   146         }
   147       }
   148     }
   149   }
   151   if (res == NS_OK) {
   152     bcr = srcEnd - src;
   153     bcw = destEnd - dest;
   154     res = ConvertNoBuff(src, &bcr, dest, &bcw);
   155     src += bcr;
   156     dest += bcw;
   158     // if we have partial input, store it in our internal buffer.
   159     if (res == NS_OK_UDEC_MOREINPUT) {
   160       bcr = srcEnd - src;
   161       // make sure buffer is large enough
   162       if (bcr > mBufferCapacity) {
   163           // somehow we got into an error state and the buffer is growing out
   164           // of control
   165           res = NS_ERROR_UNEXPECTED;
   166       } else {
   167           FillBuffer(&src, bcr);
   168       }
   169     }
   170   }
   172   *aSrcLength   -= srcEnd - src;
   173   *aDestLength  -= destEnd - dest;
   174   return res;
   175 }
   177 NS_IMETHODIMP nsBufferDecoderSupport::Reset()
   178 {
   179   mBufferLength = 0;
   180   return NS_OK;
   181 }
   183 NS_IMETHODIMP nsBufferDecoderSupport::GetMaxLength(const char* aSrc,
   184                                                    int32_t aSrcLength,
   185                                                    int32_t* aDestLength)
   186 {
   187   NS_ASSERTION(mMaxLengthFactor != 0, "Must override GetMaxLength!");
   188   *aDestLength = aSrcLength * mMaxLengthFactor;
   189   return NS_OK;
   190 }
   192 //----------------------------------------------------------------------
   193 // Class nsTableDecoderSupport [implementation]
   195 nsTableDecoderSupport::nsTableDecoderSupport(uScanClassID aScanClass,
   196                                              uShiftInTable * aShiftInTable,
   197                                              uMappingTable  * aMappingTable,
   198                                              uint32_t aMaxLengthFactor)
   199 : nsBufferDecoderSupport(aMaxLengthFactor)
   200 {
   201   mScanClass = aScanClass;
   202   mShiftInTable = aShiftInTable;
   203   mMappingTable = aMappingTable;
   204 }
   206 nsTableDecoderSupport::~nsTableDecoderSupport()
   207 {
   208 }
   210 //----------------------------------------------------------------------
   211 // Subclassing of nsBufferDecoderSupport class [implementation]
   213 NS_IMETHODIMP nsTableDecoderSupport::ConvertNoBuff(const char * aSrc,
   214                                                    int32_t * aSrcLength,
   215                                                    char16_t * aDest,
   216                                                    int32_t * aDestLength)
   217 {
   218   return nsUnicodeDecodeHelper::ConvertByTable(aSrc, aSrcLength,
   219                                                aDest, aDestLength,
   220                                                mScanClass,
   221                                                mShiftInTable, mMappingTable,
   222                                                mErrBehavior == kOnError_Signal);
   223 }
   225 //----------------------------------------------------------------------
   226 // Class nsMultiTableDecoderSupport [implementation]
   228 nsMultiTableDecoderSupport::nsMultiTableDecoderSupport(
   229                             int32_t aTableCount,
   230                             const uRange * aRangeArray,
   231                             uScanClassID * aScanClassArray,
   232                             uMappingTable ** aMappingTable,
   233                             uint32_t aMaxLengthFactor)
   234 : nsBufferDecoderSupport(aMaxLengthFactor)
   235 {
   236   mTableCount = aTableCount;
   237   mRangeArray = aRangeArray;
   238   mScanClassArray = aScanClassArray;
   239   mMappingTable = aMappingTable;
   240 }
   242 nsMultiTableDecoderSupport::~nsMultiTableDecoderSupport()
   243 {
   244 }
   246 //----------------------------------------------------------------------
   247 // Subclassing of nsBufferDecoderSupport class [implementation]
   249 NS_IMETHODIMP nsMultiTableDecoderSupport::ConvertNoBuff(const char * aSrc,
   250                                                         int32_t * aSrcLength,
   251                                                         char16_t * aDest,
   252                                                         int32_t * aDestLength)
   253 {
   254   return nsUnicodeDecodeHelper::ConvertByMultiTable(aSrc, aSrcLength,
   255                                                     aDest, aDestLength,
   256                                                     mTableCount, mRangeArray,
   257                                                     mScanClassArray,
   258                                                     mMappingTable,
   259                                                     mErrBehavior == kOnError_Signal);
   260 }
   262 //----------------------------------------------------------------------
   263 // Class nsOneByteDecoderSupport [implementation]
   265 nsOneByteDecoderSupport::nsOneByteDecoderSupport(
   266                          uMappingTable  * aMappingTable)
   267   : nsBasicDecoderSupport()
   268   , mMappingTable(aMappingTable)
   269   , mFastTableCreated(false)
   270   , mFastTableMutex("nsOneByteDecoderSupport mFastTableMutex")
   271 {
   272 }
   274 nsOneByteDecoderSupport::~nsOneByteDecoderSupport()
   275 {
   276 }
   278 //----------------------------------------------------------------------
   279 // Subclassing of nsBasicDecoderSupport class [implementation]
   281 NS_IMETHODIMP nsOneByteDecoderSupport::Convert(const char * aSrc,
   282                                               int32_t * aSrcLength,
   283                                               char16_t * aDest,
   284                                               int32_t * aDestLength)
   285 {
   286   if (!mFastTableCreated) {
   287     // Probably better to make this non-lazy and get rid of the mutex
   288     mozilla::MutexAutoLock autoLock(mFastTableMutex);
   289     if (!mFastTableCreated) {
   290       nsresult res = nsUnicodeDecodeHelper::CreateFastTable(
   291                          mMappingTable, mFastTable, ONE_BYTE_TABLE_SIZE);
   292       if (NS_FAILED(res)) return res;
   293       mFastTableCreated = true;
   294     }
   295   }
   297   return nsUnicodeDecodeHelper::ConvertByFastTable(aSrc, aSrcLength,
   298                                                    aDest, aDestLength,
   299                                                    mFastTable,
   300                                                    ONE_BYTE_TABLE_SIZE,
   301                                                    mErrBehavior == kOnError_Signal);
   302 }
   304 NS_IMETHODIMP nsOneByteDecoderSupport::GetMaxLength(const char * aSrc,
   305                                                     int32_t aSrcLength,
   306                                                     int32_t * aDestLength)
   307 {
   308   // single byte to Unicode converter
   309   *aDestLength = aSrcLength;
   310   return NS_OK_UDEC_EXACTLENGTH;
   311 }
   313 NS_IMETHODIMP nsOneByteDecoderSupport::Reset()
   314 {
   315   // nothing to reset, no internal state in this case
   316   return NS_OK;
   317 }
   319 //----------------------------------------------------------------------
   320 // Class nsBasicEncoder [implementation]
   321 nsBasicEncoder::nsBasicEncoder()
   322 {
   323 }
   325 nsBasicEncoder::~nsBasicEncoder()
   326 {
   327 }
   329 //----------------------------------------------------------------------
   330 // Interface nsISupports [implementation]
   332 NS_IMPL_ADDREF(nsBasicEncoder)
   333 NS_IMPL_RELEASE(nsBasicEncoder)
   334 #ifdef DEBUG
   335 NS_IMPL_QUERY_INTERFACE(nsBasicEncoder,
   336                         nsIUnicodeEncoder,
   337                         nsIBasicEncoder)
   338 #else
   339 NS_IMPL_QUERY_INTERFACE(nsBasicEncoder,
   340                         nsIUnicodeEncoder)
   341 #endif
   342 //----------------------------------------------------------------------
   343 // Class nsEncoderSupport [implementation]
   345 nsEncoderSupport::nsEncoderSupport(uint32_t aMaxLengthFactor) :
   346   mMaxLengthFactor(aMaxLengthFactor)
   347 {
   348   mBufferCapacity = DEFAULT_BUFFER_CAPACITY;
   349   mBuffer = new char[mBufferCapacity];
   351   mErrBehavior = kOnError_Signal;
   352   mErrChar = 0;
   354   Reset();
   355 }
   357 nsEncoderSupport::~nsEncoderSupport()
   358 {
   359   delete [] mBuffer;
   360 }
   362 NS_IMETHODIMP nsEncoderSupport::ConvertNoBuff(const char16_t * aSrc,
   363                                               int32_t * aSrcLength,
   364                                               char * aDest,
   365                                               int32_t * aDestLength)
   366 {
   367   // we do all operations using pointers internally
   368   const char16_t * src = aSrc;
   369   const char16_t * srcEnd = aSrc + *aSrcLength;
   370   char * dest = aDest;
   371   char * destEnd = aDest + *aDestLength;
   373   int32_t bcr, bcw; // byte counts for read & write;
   374   nsresult res;
   376   for (;;) {
   377     bcr = srcEnd - src;
   378     bcw = destEnd - dest;
   379     res = ConvertNoBuffNoErr(src, &bcr, dest, &bcw);
   380     src += bcr;
   381     dest += bcw;
   383     if (res == NS_ERROR_UENC_NOMAPPING) {
   384       if (mErrBehavior == kOnError_Replace) {
   385         const char16_t buff[] = {mErrChar};
   386         bcr = 1;
   387         bcw = destEnd - dest;
   388         src--; // back the input: maybe the guy won't consume consume anything.
   389         res = ConvertNoBuffNoErr(buff, &bcr, dest, &bcw);
   390         src += bcr;
   391         dest += bcw;
   392         if (res != NS_OK) break;
   393       } else if (mErrBehavior == kOnError_CallBack) {
   394         bcw = destEnd - dest;
   395         src--;
   396         res = mErrEncoder->Convert(*src, dest, &bcw);
   397         dest += bcw;
   398         // if enought output space then the last char was used
   399         if (res != NS_OK_UENC_MOREOUTPUT) src++;
   400         if (res != NS_OK) break;
   401       } else break;
   402     }
   403     else break;
   404   }
   406   *aSrcLength   -= srcEnd - src;
   407   *aDestLength  -= destEnd - dest;
   408   return res;
   409 }
   411 NS_IMETHODIMP nsEncoderSupport::FinishNoBuff(char * aDest,
   412                                              int32_t * aDestLength)
   413 {
   414   *aDestLength = 0;
   415   return NS_OK;
   416 }
   418 nsresult nsEncoderSupport::FlushBuffer(char ** aDest, const char * aDestEnd)
   419 {
   420   int32_t bcr, bcw; // byte counts for read & write;
   421   nsresult res = NS_OK;
   422   char * dest = *aDest;
   424   if (mBufferStart < mBufferEnd) {
   425     bcr = mBufferEnd - mBufferStart;
   426     bcw = aDestEnd - dest;
   427     if (bcw < bcr) bcr = bcw;
   428     memcpy(dest, mBufferStart, bcr);
   429     dest += bcr;
   430     mBufferStart += bcr;
   432     if (mBufferStart < mBufferEnd) res = NS_OK_UENC_MOREOUTPUT;
   433   }
   435   *aDest = dest;
   436   return res;
   437 }
   440 //----------------------------------------------------------------------
   441 // Interface nsIUnicodeEncoder [implementation]
   443 NS_IMETHODIMP nsEncoderSupport::Convert(const char16_t * aSrc,
   444                                         int32_t * aSrcLength,
   445                                         char * aDest,
   446                                         int32_t * aDestLength)
   447 {
   448   // we do all operations using pointers internally
   449   const char16_t * src = aSrc;
   450   const char16_t * srcEnd = aSrc + *aSrcLength;
   451   char * dest = aDest;
   452   char * destEnd = aDest + *aDestLength;
   454   int32_t bcr, bcw; // byte counts for read & write;
   455   nsresult res;
   457   res = FlushBuffer(&dest, destEnd);
   458   if (res == NS_OK_UENC_MOREOUTPUT) goto final;
   460   bcr = srcEnd - src;
   461   bcw = destEnd - dest;
   462   res = ConvertNoBuff(src, &bcr, dest, &bcw);
   463   src += bcr;
   464   dest += bcw;
   465   if ((res == NS_OK_UENC_MOREOUTPUT) && (dest < destEnd)) {
   466     // convert exactly one character into the internal buffer
   467     // at this point, there should be at least a char in the input
   468     for (;;) {
   469       bcr = 1;
   470       bcw = mBufferCapacity;
   471       res = ConvertNoBuff(src, &bcr, mBuffer, &bcw);
   473       if (res == NS_OK_UENC_MOREOUTPUT) {
   474         delete [] mBuffer;
   475         mBufferCapacity *= 2;
   476         mBuffer = new char [mBufferCapacity];
   477       } else {
   478         src += bcr;
   479         mBufferStart = mBufferEnd = mBuffer;
   480         mBufferEnd += bcw;
   481         break;
   482       }
   483     }
   485     res = FlushBuffer(&dest, destEnd);
   486   }
   488 final:
   489   *aSrcLength   -= srcEnd - src;
   490   *aDestLength  -= destEnd - dest;
   491   return res;
   492 }
   494 NS_IMETHODIMP nsEncoderSupport::Finish(char * aDest, int32_t * aDestLength)
   495 {
   496   // we do all operations using pointers internally
   497   char * dest = aDest;
   498   char * destEnd = aDest + *aDestLength;
   500   int32_t bcw; // byte count for write;
   501   nsresult res;
   503   res = FlushBuffer(&dest, destEnd);
   504   if (res == NS_OK_UENC_MOREOUTPUT) goto final;
   506   // do the finish into the internal buffer.
   507   for (;;) {
   508     bcw = mBufferCapacity;
   509     res = FinishNoBuff(mBuffer, &bcw);
   511     if (res == NS_OK_UENC_MOREOUTPUT) {
   512       delete [] mBuffer;
   513       mBufferCapacity *= 2;
   514       mBuffer = new char [mBufferCapacity];
   515     } else {
   516       mBufferStart = mBufferEnd = mBuffer;
   517       mBufferEnd += bcw;
   518       break;
   519     }
   520   }
   522   res = FlushBuffer(&dest, destEnd);
   524 final:
   525   *aDestLength  -= destEnd - dest;
   526   return res;
   527 }
   529 NS_IMETHODIMP nsEncoderSupport::Reset()
   530 {
   531   mBufferStart = mBufferEnd = mBuffer;
   532   return NS_OK;
   533 }
   535 NS_IMETHODIMP nsEncoderSupport::SetOutputErrorBehavior(
   536                                 int32_t aBehavior,
   537                                 nsIUnicharEncoder * aEncoder,
   538                                 char16_t aChar)
   539 {
   540   if (aBehavior == kOnError_CallBack && !aEncoder)
   541     return NS_ERROR_NULL_POINTER;
   543   mErrEncoder = aEncoder;
   544   mErrBehavior = aBehavior;
   545   mErrChar = aChar;
   546   return NS_OK;
   547 }
   549 NS_IMETHODIMP
   550 nsEncoderSupport::GetMaxLength(const char16_t * aSrc,
   551                                int32_t aSrcLength,
   552                                int32_t * aDestLength)
   553 {
   554   *aDestLength = aSrcLength * mMaxLengthFactor;
   555   return NS_OK;
   556 }
   559 //----------------------------------------------------------------------
   560 // Class nsTableEncoderSupport [implementation]
   562 nsTableEncoderSupport::nsTableEncoderSupport(uScanClassID aScanClass,
   563                                              uShiftOutTable * aShiftOutTable,
   564                                              uMappingTable  * aMappingTable,
   565                                              uint32_t aMaxLengthFactor)
   566 : nsEncoderSupport(aMaxLengthFactor)
   567 {
   568   mScanClass = aScanClass;
   569   mShiftOutTable = aShiftOutTable,
   570   mMappingTable = aMappingTable;
   571 }
   573 nsTableEncoderSupport::nsTableEncoderSupport(uScanClassID aScanClass,
   574                                              uMappingTable  * aMappingTable,
   575                                              uint32_t aMaxLengthFactor)
   576 : nsEncoderSupport(aMaxLengthFactor)
   577 {
   578   mScanClass = aScanClass;
   579   mShiftOutTable = nullptr;
   580   mMappingTable = aMappingTable;
   581 }
   583 nsTableEncoderSupport::~nsTableEncoderSupport()
   584 {
   585 }
   587 //----------------------------------------------------------------------
   588 // Subclassing of nsEncoderSupport class [implementation]
   590 NS_IMETHODIMP nsTableEncoderSupport::ConvertNoBuffNoErr(
   591                                      const char16_t * aSrc,
   592                                      int32_t * aSrcLength,
   593                                      char * aDest,
   594                                      int32_t * aDestLength)
   595 {
   596   return nsUnicodeEncodeHelper::ConvertByTable(aSrc, aSrcLength,
   597                                                aDest, aDestLength,
   598                                                mScanClass,
   599                                                mShiftOutTable, mMappingTable);
   600 }
   602 //----------------------------------------------------------------------
   603 // Class nsMultiTableEncoderSupport [implementation]
   605 nsMultiTableEncoderSupport::nsMultiTableEncoderSupport(
   606                             int32_t aTableCount,
   607                             uScanClassID * aScanClassArray,
   608                             uShiftOutTable ** aShiftOutTable,
   609                             uMappingTable  ** aMappingTable,
   610                             uint32_t aMaxLengthFactor)
   611 : nsEncoderSupport(aMaxLengthFactor)
   612 {
   613   mTableCount = aTableCount;
   614   mScanClassArray = aScanClassArray;
   615   mShiftOutTable = aShiftOutTable;
   616   mMappingTable = aMappingTable;
   617 }
   619 nsMultiTableEncoderSupport::~nsMultiTableEncoderSupport()
   620 {
   621 }
   623 //----------------------------------------------------------------------
   624 // Subclassing of nsEncoderSupport class [implementation]
   626 NS_IMETHODIMP nsMultiTableEncoderSupport::ConvertNoBuffNoErr(
   627                                           const char16_t * aSrc,
   628                                           int32_t * aSrcLength,
   629                                           char * aDest,
   630                                           int32_t * aDestLength)
   631 {
   632   return nsUnicodeEncodeHelper::ConvertByMultiTable(aSrc, aSrcLength,
   633                                                     aDest, aDestLength,
   634                                                     mTableCount,
   635                                                     mScanClassArray,
   636                                                     mShiftOutTable,
   637                                                     mMappingTable);
   638 }

mercurial