editor/libeditor/text/nsInternetCiter.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.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6
michael@0 7 #include "nsAString.h"
michael@0 8 #include "nsCOMPtr.h"
michael@0 9 #include "nsCRT.h"
michael@0 10 #include "nsDebug.h"
michael@0 11 #include "nsDependentSubstring.h"
michael@0 12 #include "nsError.h"
michael@0 13 #include "nsILineBreaker.h"
michael@0 14 #include "nsInternetCiter.h"
michael@0 15 #include "nsLWBrkCIID.h"
michael@0 16 #include "nsServiceManagerUtils.h"
michael@0 17 #include "nsString.h"
michael@0 18 #include "nsStringIterator.h"
michael@0 19
michael@0 20 const char16_t gt ('>');
michael@0 21 const char16_t space (' ');
michael@0 22 const char16_t nbsp (0xa0);
michael@0 23 const char16_t nl ('\n');
michael@0 24 const char16_t cr('\r');
michael@0 25
michael@0 26 /** Mail citations using the Internet style: > This is a citation
michael@0 27 */
michael@0 28
michael@0 29 nsresult
michael@0 30 nsInternetCiter::GetCiteString(const nsAString& aInString, nsAString& aOutString)
michael@0 31 {
michael@0 32 aOutString.Truncate();
michael@0 33 char16_t uch = nl;
michael@0 34
michael@0 35 // Strip trailing new lines which will otherwise turn up
michael@0 36 // as ugly quoted empty lines.
michael@0 37 nsReadingIterator <char16_t> beginIter,endIter;
michael@0 38 aInString.BeginReading(beginIter);
michael@0 39 aInString.EndReading(endIter);
michael@0 40 while(beginIter!= endIter &&
michael@0 41 (*endIter == cr ||
michael@0 42 *endIter == nl))
michael@0 43 {
michael@0 44 --endIter;
michael@0 45 }
michael@0 46
michael@0 47 // Loop over the string:
michael@0 48 while (beginIter != endIter)
michael@0 49 {
michael@0 50 if (uch == nl)
michael@0 51 {
michael@0 52 aOutString.Append(gt);
michael@0 53 // No space between >: this is ">>> " style quoting, for
michael@0 54 // compatibility with RFC 2646 and format=flowed.
michael@0 55 if (*beginIter != gt)
michael@0 56 aOutString.Append(space);
michael@0 57 }
michael@0 58
michael@0 59 uch = *beginIter;
michael@0 60 ++beginIter;
michael@0 61
michael@0 62 aOutString += uch;
michael@0 63 }
michael@0 64
michael@0 65 if (uch != nl)
michael@0 66 aOutString += nl;
michael@0 67
michael@0 68 return NS_OK;
michael@0 69 }
michael@0 70
michael@0 71 nsresult
michael@0 72 nsInternetCiter::StripCitesAndLinebreaks(const nsAString& aInString,
michael@0 73 nsAString& aOutString,
michael@0 74 bool aLinebreaksToo,
michael@0 75 int32_t* aCiteLevel)
michael@0 76 {
michael@0 77 if (aCiteLevel)
michael@0 78 *aCiteLevel = 0;
michael@0 79
michael@0 80 aOutString.Truncate();
michael@0 81 nsReadingIterator <char16_t> beginIter,endIter;
michael@0 82 aInString.BeginReading(beginIter);
michael@0 83 aInString.EndReading(endIter);
michael@0 84 while (beginIter!= endIter) // loop over lines
michael@0 85 {
michael@0 86 // Clear out cites first, at the beginning of the line:
michael@0 87 int32_t thisLineCiteLevel = 0;
michael@0 88 while (beginIter!= endIter && (*beginIter == gt || nsCRT::IsAsciiSpace(*beginIter)))
michael@0 89 {
michael@0 90 if (*beginIter == gt) ++thisLineCiteLevel;
michael@0 91 ++beginIter;
michael@0 92 }
michael@0 93
michael@0 94 // Now copy characters until line end:
michael@0 95 while (beginIter != endIter && (*beginIter != '\r' && *beginIter != '\n'))
michael@0 96 {
michael@0 97 aOutString.Append(*beginIter);
michael@0 98 ++beginIter;
michael@0 99 }
michael@0 100 if (aLinebreaksToo)
michael@0 101 aOutString.Append(char16_t(' '));
michael@0 102 else
michael@0 103 aOutString.Append(char16_t('\n')); // DOM linebreaks, not NS_LINEBREAK
michael@0 104 // Skip over any more consecutive linebreak-like characters:
michael@0 105 while (beginIter != endIter && (*beginIter == '\r' || *beginIter == '\n'))
michael@0 106 ++beginIter;
michael@0 107
michael@0 108 // Done with this line -- update cite level
michael@0 109 if (aCiteLevel && (thisLineCiteLevel > *aCiteLevel))
michael@0 110 *aCiteLevel = thisLineCiteLevel;
michael@0 111 }
michael@0 112 return NS_OK;
michael@0 113 }
michael@0 114
michael@0 115 nsresult
michael@0 116 nsInternetCiter::StripCites(const nsAString& aInString, nsAString& aOutString)
michael@0 117 {
michael@0 118 return StripCitesAndLinebreaks(aInString, aOutString, false, 0);
michael@0 119 }
michael@0 120
michael@0 121 static void AddCite(nsAString& aOutString, int32_t citeLevel)
michael@0 122 {
michael@0 123 for (int32_t i = 0; i < citeLevel; ++i)
michael@0 124 aOutString.Append(gt);
michael@0 125 if (citeLevel > 0)
michael@0 126 aOutString.Append(space);
michael@0 127 }
michael@0 128
michael@0 129 static inline void
michael@0 130 BreakLine(nsAString& aOutString, uint32_t& outStringCol,
michael@0 131 uint32_t citeLevel)
michael@0 132 {
michael@0 133 aOutString.Append(nl);
michael@0 134 if (citeLevel > 0)
michael@0 135 {
michael@0 136 AddCite(aOutString, citeLevel);
michael@0 137 outStringCol = citeLevel + 1;
michael@0 138 }
michael@0 139 else
michael@0 140 outStringCol = 0;
michael@0 141 }
michael@0 142
michael@0 143 static inline bool IsSpace(char16_t c)
michael@0 144 {
michael@0 145 return (nsCRT::IsAsciiSpace(c) || (c == nl) || (c == cr) || (c == nbsp));
michael@0 146 }
michael@0 147
michael@0 148 nsresult
michael@0 149 nsInternetCiter::Rewrap(const nsAString& aInString,
michael@0 150 uint32_t aWrapCol, uint32_t aFirstLineOffset,
michael@0 151 bool aRespectNewlines,
michael@0 152 nsAString& aOutString)
michael@0 153 {
michael@0 154 // There shouldn't be returns in this string, only dom newlines.
michael@0 155 // Check to make sure:
michael@0 156 #ifdef DEBUG
michael@0 157 int32_t cr = aInString.FindChar(char16_t('\r'));
michael@0 158 NS_ASSERTION((cr < 0), "Rewrap: CR in string gotten from DOM!\n");
michael@0 159 #endif /* DEBUG */
michael@0 160
michael@0 161 aOutString.Truncate();
michael@0 162
michael@0 163 nsresult rv;
michael@0 164 nsCOMPtr<nsILineBreaker> lineBreaker = do_GetService(NS_LBRK_CONTRACTID, &rv);
michael@0 165 NS_ENSURE_SUCCESS(rv, rv);
michael@0 166
michael@0 167 // Loop over lines in the input string, rewrapping each one.
michael@0 168 uint32_t length;
michael@0 169 uint32_t posInString = 0;
michael@0 170 uint32_t outStringCol = 0;
michael@0 171 uint32_t citeLevel = 0;
michael@0 172 const nsPromiseFlatString &tString = PromiseFlatString(aInString);
michael@0 173 length = tString.Length();
michael@0 174 #ifdef DEBUG_wrapping
michael@0 175 int loopcount = 0;
michael@0 176 #endif
michael@0 177 while (posInString < length)
michael@0 178 {
michael@0 179 #ifdef DEBUG_wrapping
michael@0 180 printf("Outer loop: '%s'\n",
michael@0 181 NS_LossyConvertUTF16toASCII(Substring(tString, posInString,
michael@0 182 length-posInString)).get());
michael@0 183 printf("out string is now: '%s'\n",
michael@0 184 NS_LossyConvertUTF16toASCII(aOutString).get());
michael@0 185
michael@0 186 #endif
michael@0 187
michael@0 188 // Get the new cite level here since we're at the beginning of a line
michael@0 189 uint32_t newCiteLevel = 0;
michael@0 190 while (posInString < length && tString[posInString] == gt)
michael@0 191 {
michael@0 192 ++newCiteLevel;
michael@0 193 ++posInString;
michael@0 194 while (posInString < length && tString[posInString] == space)
michael@0 195 ++posInString;
michael@0 196 }
michael@0 197 if (posInString >= length)
michael@0 198 break;
michael@0 199
michael@0 200 // Special case: if this is a blank line, maintain a blank line
michael@0 201 // (retain the original paragraph breaks)
michael@0 202 if (tString[posInString] == nl && !aOutString.IsEmpty())
michael@0 203 {
michael@0 204 if (aOutString.Last() != nl)
michael@0 205 aOutString.Append(nl);
michael@0 206 AddCite(aOutString, newCiteLevel);
michael@0 207 aOutString.Append(nl);
michael@0 208
michael@0 209 ++posInString;
michael@0 210 outStringCol = 0;
michael@0 211 continue;
michael@0 212 }
michael@0 213
michael@0 214 // If the cite level has changed, then start a new line with the
michael@0 215 // new cite level (but if we're at the beginning of the string,
michael@0 216 // don't bother).
michael@0 217 if (newCiteLevel != citeLevel && posInString > newCiteLevel+1
michael@0 218 && outStringCol != 0)
michael@0 219 {
michael@0 220 BreakLine(aOutString, outStringCol, 0);
michael@0 221 }
michael@0 222 citeLevel = newCiteLevel;
michael@0 223
michael@0 224 // Prepend the quote level to the out string if appropriate
michael@0 225 if (outStringCol == 0)
michael@0 226 {
michael@0 227 AddCite(aOutString, citeLevel);
michael@0 228 outStringCol = citeLevel + (citeLevel ? 1 : 0);
michael@0 229 }
michael@0 230 // If it's not a cite, and we're not at the beginning of a line in
michael@0 231 // the output string, add a space to separate new text from the
michael@0 232 // previous text.
michael@0 233 else if (outStringCol > citeLevel)
michael@0 234 {
michael@0 235 aOutString.Append(space);
michael@0 236 ++outStringCol;
michael@0 237 }
michael@0 238
michael@0 239 // find the next newline -- don't want to go farther than that
michael@0 240 int32_t nextNewline = tString.FindChar(nl, posInString);
michael@0 241 if (nextNewline < 0) nextNewline = length;
michael@0 242
michael@0 243 // For now, don't wrap unquoted lines at all.
michael@0 244 // This is because the plaintext edit window has already wrapped them
michael@0 245 // by the time we get them for rewrap, yet when we call the line
michael@0 246 // breaker, it will refuse to break backwards, and we'll end up
michael@0 247 // with a line that's too long and gets displayed as a lone word
michael@0 248 // on a line by itself. Need special logic to detect this case
michael@0 249 // and break it ourselves without resorting to the line breaker.
michael@0 250 if (citeLevel == 0)
michael@0 251 {
michael@0 252 aOutString.Append(Substring(tString, posInString,
michael@0 253 nextNewline-posInString));
michael@0 254 outStringCol += nextNewline - posInString;
michael@0 255 if (nextNewline != (int32_t)length)
michael@0 256 {
michael@0 257 aOutString.Append(nl);
michael@0 258 outStringCol = 0;
michael@0 259 }
michael@0 260 posInString = nextNewline+1;
michael@0 261 continue;
michael@0 262 }
michael@0 263
michael@0 264 // Otherwise we have to use the line breaker and loop
michael@0 265 // over this line of the input string to get all of it:
michael@0 266 while ((int32_t)posInString < nextNewline)
michael@0 267 {
michael@0 268 #ifdef DEBUG_wrapping
michael@0 269 if (++loopcount > 1000)
michael@0 270 NS_ASSERTION(false, "possible infinite loop in nsInternetCiter\n");
michael@0 271
michael@0 272 printf("Inner loop: '%s'\n",
michael@0 273 NS_LossyConvertUTF16toASCII(Substring(tString, posInString,
michael@0 274 nextNewline-posInString)).get());
michael@0 275 #endif
michael@0 276
michael@0 277 // Skip over initial spaces:
michael@0 278 while ((int32_t)posInString < nextNewline
michael@0 279 && nsCRT::IsAsciiSpace(tString[posInString]))
michael@0 280 ++posInString;
michael@0 281
michael@0 282 // If this is a short line, just append it and continue:
michael@0 283 if (outStringCol + nextNewline - posInString <= aWrapCol-citeLevel-1)
michael@0 284 {
michael@0 285 // If this short line is the final one in the in string,
michael@0 286 // then we need to include the final newline, if any:
michael@0 287 if (nextNewline+1 == (int32_t)length && tString[nextNewline-1] == nl)
michael@0 288 ++nextNewline;
michael@0 289
michael@0 290 // Trim trailing spaces:
michael@0 291 int32_t lastRealChar = nextNewline;
michael@0 292 while ((uint32_t)lastRealChar > posInString
michael@0 293 && nsCRT::IsAsciiSpace(tString[lastRealChar-1]))
michael@0 294 --lastRealChar;
michael@0 295
michael@0 296 aOutString += Substring(tString,
michael@0 297 posInString, lastRealChar - posInString);
michael@0 298 outStringCol += lastRealChar - posInString;
michael@0 299 posInString = nextNewline + 1;
michael@0 300 continue;
michael@0 301 }
michael@0 302
michael@0 303 int32_t eol = posInString + aWrapCol - citeLevel - outStringCol;
michael@0 304 // eol is the prospective end of line.
michael@0 305 // We'll first look backwards from there for a place to break.
michael@0 306 // If it's already less than our current position,
michael@0 307 // then our line is already too long, so break now.
michael@0 308 if (eol <= (int32_t)posInString)
michael@0 309 {
michael@0 310 BreakLine(aOutString, outStringCol, citeLevel);
michael@0 311 continue; // continue inner loop, with outStringCol now at bol
michael@0 312 }
michael@0 313
michael@0 314 int32_t breakPt = 0;
michael@0 315 rv = NS_ERROR_BASE;
michael@0 316 if (lineBreaker)
michael@0 317 {
michael@0 318 breakPt = lineBreaker->Prev(tString.get() + posInString,
michael@0 319 length - posInString, eol + 1 - posInString);
michael@0 320 if (breakPt == NS_LINEBREAKER_NEED_MORE_TEXT)
michael@0 321 {
michael@0 322 // if we couldn't find a breakpoint looking backwards,
michael@0 323 // and we're not starting a new line, then end this line
michael@0 324 // and loop around again:
michael@0 325 if (outStringCol > citeLevel + 1)
michael@0 326 {
michael@0 327 BreakLine(aOutString, outStringCol, citeLevel);
michael@0 328 continue; // continue inner loop, with outStringCol now at bol
michael@0 329 }
michael@0 330
michael@0 331 // Else try looking forwards:
michael@0 332 breakPt = lineBreaker->Next(tString.get() + posInString,
michael@0 333 length - posInString, eol - posInString);
michael@0 334 if (breakPt == NS_LINEBREAKER_NEED_MORE_TEXT) rv = NS_ERROR_BASE;
michael@0 335 else rv = NS_OK;
michael@0 336 }
michael@0 337 else rv = NS_OK;
michael@0 338 }
michael@0 339 // If rv is okay, then breakPt is the place to break.
michael@0 340 // If we get out here and rv is set, something went wrong with line
michael@0 341 // breaker. Just break the line, hard.
michael@0 342 if (NS_FAILED(rv))
michael@0 343 {
michael@0 344 #ifdef DEBUG_akkana
michael@0 345 printf("nsInternetCiter: LineBreaker not working -- breaking hard\n");
michael@0 346 #endif
michael@0 347 breakPt = eol;
michael@0 348 }
michael@0 349
michael@0 350 // Special case: maybe we should have wrapped last time.
michael@0 351 // If the first breakpoint here makes the current line too long,
michael@0 352 // then if we already have text on the current line,
michael@0 353 // break and loop around again.
michael@0 354 // If we're at the beginning of the current line, though,
michael@0 355 // don't force a break since the long word might be a url
michael@0 356 // and breaking it would make it unclickable on the other end.
michael@0 357 const int SLOP = 6;
michael@0 358 if (outStringCol + breakPt > aWrapCol + SLOP
michael@0 359 && outStringCol > citeLevel+1)
michael@0 360 {
michael@0 361 BreakLine(aOutString, outStringCol, citeLevel);
michael@0 362 continue;
michael@0 363 }
michael@0 364
michael@0 365 nsAutoString sub (Substring(tString, posInString, breakPt));
michael@0 366 // skip newlines or whitespace at the end of the string
michael@0 367 int32_t subend = sub.Length();
michael@0 368 while (subend > 0 && IsSpace(sub[subend-1]))
michael@0 369 --subend;
michael@0 370 sub.Left(sub, subend);
michael@0 371 aOutString += sub;
michael@0 372 outStringCol += sub.Length();
michael@0 373 // Advance past the whitespace which caused the wrap:
michael@0 374 posInString += breakPt;
michael@0 375 while (posInString < length && IsSpace(tString[posInString]))
michael@0 376 ++posInString;
michael@0 377
michael@0 378 // Add a newline and the quote level to the out string
michael@0 379 if (posInString < length) // not for the last line, though
michael@0 380 BreakLine(aOutString, outStringCol, citeLevel);
michael@0 381
michael@0 382 } // end inner loop within one line of aInString
michael@0 383 #ifdef DEBUG_wrapping
michael@0 384 printf("---------\nEnd inner loop: out string is now '%s'\n-----------\n",
michael@0 385 NS_LossyConvertUTF16toASCII(aOutString).get());
michael@0 386 #endif
michael@0 387 } // end outer loop over lines of aInString
michael@0 388
michael@0 389 #ifdef DEBUG_wrapping
michael@0 390 printf("Final out string is now: '%s'\n",
michael@0 391 NS_LossyConvertUTF16toASCII(aOutString).get());
michael@0 392
michael@0 393 #endif
michael@0 394 return NS_OK;
michael@0 395 }
michael@0 396
michael@0 397

mercurial