Sat, 03 Jan 2015 20:18:00 +0100
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 }