| Index: chrome/browser/net/quoted_printable.cc
|
| diff --git a/chrome/browser/net/quoted_printable.cc b/chrome/browser/net/quoted_printable.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b61246b2fbb4c44d1551fc815ad668d9ac37ec36
|
| --- /dev/null
|
| +++ b/chrome/browser/net/quoted_printable.cc
|
| @@ -0,0 +1,132 @@
|
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/net/quoted_printable.h"
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/string_util.h"
|
| +
|
| +namespace {
|
| +
|
| +const int kMaxCharPerLine = 76;
|
| +const char* const kEOL = "\r\n";
|
| +
|
| +const char kHexTable[] = "0123456789ABCDEF";
|
| +
|
| +} // namespace
|
| +
|
| +namespace chrome {
|
| +namespace browser {
|
| +namespace net {
|
| +
|
| +void QuotedPrintableEncode(const std::string& input, std::string* output) {
|
| + // The number of characters in the current line.
|
| + int char_count = 0;
|
| + for (std::string::const_iterator iter = input.begin();
|
| + iter != input.end(); ++iter) {
|
| + bool last_char = (iter + 1 == input.end());
|
| + char c = *iter;
|
| + // Whether this character can be inserted without encoding.
|
| + bool as_is = false;
|
| + // All printable ASCII characters can be included as is (but for =).
|
| + if (c >= '!' && c <= '~' && c != '=') {
|
| + as_is = true;
|
| + }
|
| +
|
| + // Space and tab characters can be included as is if they don't appear at
|
| + // the end of a line or at then end of the input.
|
| + if (!as_is && (c == '\t' || c == ' ') && !last_char &&
|
| + !IsEOL(iter + 1, input)) {
|
| + as_is = true;
|
| + }
|
| +
|
| + // End of line should be converted to CR-LF sequences.
|
| + if (!last_char) {
|
| + int eol_len = IsEOL(iter, input);
|
| + if (eol_len > 0) {
|
| + output->append(kEOL);
|
| + char_count = 0;
|
| + iter += (eol_len - 1); // -1 because we'll ++ in the for() above.
|
| + continue;
|
| + }
|
| + }
|
| +
|
| + // Insert a soft line break if necessary.
|
| + int min_chars_needed = as_is ? kMaxCharPerLine - 2 : kMaxCharPerLine - 4;
|
| + if (!last_char && char_count > min_chars_needed) {
|
| + output->append("=");
|
| + output->append(kEOL);
|
| + char_count = 0;
|
| + }
|
| +
|
| + // Finally, insert the actual character(s).
|
| + if (as_is) {
|
| + output->append(1, c);
|
| + char_count++;
|
| + } else {
|
| + output->append("=");
|
| + output->append(1, kHexTable[static_cast<int>((c >> 4) & 0xF)]);
|
| + output->append(1, kHexTable[static_cast<int>(c & 0x0F)]);
|
| + char_count += 3;
|
| + }
|
| + }
|
| +}
|
| +
|
| +bool QuotedPrintableDecode(const std::string& input, std::string* output) {
|
| + bool success = true;
|
| + for (std::string::const_iterator iter = input.begin();
|
| + iter!= input.end(); ++iter) {
|
| + char c = *iter;
|
| + if (c != '=') {
|
| + output->append(1, c);
|
| + continue;
|
| + }
|
| + if (input.end() - iter < 3) {
|
| + LOG(ERROR) << "unfinished = sequence in input string.";
|
| + success = false;
|
| + output->append(1, c);
|
| + continue;
|
| + }
|
| + char c2 = *(++iter);
|
| + char c3 = *(++iter);
|
| + if (c2 == '\r' && c3 == '\n') {
|
| + // Soft line break, ignored.
|
| + continue;
|
| + }
|
| +
|
| + if (!IsHexDigit(c2) || !IsHexDigit(c3)) {
|
| + LOG(ERROR) << "invalid = sequence, = followed by non hexa digit " <<
|
| + "chars: " << c2 << " " << c3;
|
| + success = false;
|
| + // Just insert the chars as is.
|
| + output->append("=");
|
| + output->append(1, c2);
|
| + output->append(1, c3);
|
| + continue;
|
| + }
|
| +
|
| + int i1 = HexDigitToInt(c2);
|
| + int i2 = HexDigitToInt(c3);
|
| + char r = static_cast<char>(((i1 << 4) & 0xF0) | (i2 & 0x0F));
|
| + output->append(1, r);
|
| + }
|
| + return success;
|
| +}
|
| +
|
| +int IsEOL(const std::string::const_iterator& iter, const std::string& input) {
|
| + if (*iter == '\n')
|
| + return 1; // Single LF.
|
| +
|
| + if (*iter == '\r') {
|
| + if ((iter + 1) == input.end() || *(iter + 1) != '\n')
|
| + return 1; // Single CR (Commodore and Old Macs).
|
| + return 2; // CR-LF.
|
| + }
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +} // namespace net
|
| +} // namespace browser
|
| +} // namespace chrome
|
|
|