1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Use of this source code is governed by a BSD-style license that can be 3dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// found in the LICENSE file. 4dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/net/quoted_printable.h" 6dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 7dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/logging.h" 8dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/string_util.h" 9dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace { 11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst int kMaxCharPerLine = 76; 13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst char* const kEOL = "\r\n"; 14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst char kHexTable[] = "0123456789ABCDEF"; 16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} // namespace 18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace chrome { 20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace browser { 21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace net { 22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid QuotedPrintableEncode(const std::string& input, std::string* output) { 24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // The number of characters in the current line. 25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int char_count = 0; 26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen for (std::string::const_iterator iter = input.begin(); 27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen iter != input.end(); ++iter) { 28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool last_char = (iter + 1 == input.end()); 29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen char c = *iter; 30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Whether this character can be inserted without encoding. 31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool as_is = false; 32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // All printable ASCII characters can be included as is (but for =). 33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (c >= '!' && c <= '~' && c != '=') { 34dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen as_is = true; 35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Space and tab characters can be included as is if they don't appear at 38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // the end of a line or at then end of the input. 39dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!as_is && (c == '\t' || c == ' ') && !last_char && 40dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen !IsEOL(iter + 1, input)) { 41dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen as_is = true; 42dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 44dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // End of line should be converted to CR-LF sequences. 45dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!last_char) { 46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int eol_len = IsEOL(iter, input); 47dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (eol_len > 0) { 48dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen output->append(kEOL); 49dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen char_count = 0; 50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen iter += (eol_len - 1); // -1 because we'll ++ in the for() above. 51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen continue; 52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Insert a soft line break if necessary. 56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int min_chars_needed = as_is ? kMaxCharPerLine - 2 : kMaxCharPerLine - 4; 57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!last_char && char_count > min_chars_needed) { 58dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen output->append("="); 59dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen output->append(kEOL); 60dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen char_count = 0; 61dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 62dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 63dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Finally, insert the actual character(s). 64dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (as_is) { 65dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen output->append(1, c); 66dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen char_count++; 67dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen output->append("="); 69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen output->append(1, kHexTable[static_cast<int>((c >> 4) & 0xF)]); 70dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen output->append(1, kHexTable[static_cast<int>(c & 0x0F)]); 71dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen char_count += 3; 72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool QuotedPrintableDecode(const std::string& input, std::string* output) { 77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool success = true; 78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen for (std::string::const_iterator iter = input.begin(); 79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen iter!= input.end(); ++iter) { 80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen char c = *iter; 81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (c != '=') { 82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen output->append(1, c); 83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen continue; 84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (input.end() - iter < 3) { 86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen LOG(ERROR) << "unfinished = sequence in input string."; 87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen success = false; 88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen output->append(1, c); 89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen continue; 90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen char c2 = *(++iter); 92dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen char c3 = *(++iter); 93dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (c2 == '\r' && c3 == '\n') { 94dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Soft line break, ignored. 95dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen continue; 96dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 98dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!IsHexDigit(c2) || !IsHexDigit(c3)) { 99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen LOG(ERROR) << "invalid = sequence, = followed by non hexa digit " << 100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen "chars: " << c2 << " " << c3; 101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen success = false; 102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Just insert the chars as is. 103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen output->append("="); 104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen output->append(1, c2); 105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen output->append(1, c3); 106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen continue; 107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int i1 = HexDigitToInt(c2); 110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int i2 = HexDigitToInt(c3); 111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen char r = static_cast<char>(((i1 << 4) & 0xF0) | (i2 & 0x0F)); 112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen output->append(1, r); 113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return success; 115dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 116dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint IsEOL(const std::string::const_iterator& iter, const std::string& input) { 118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (*iter == '\n') 119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return 1; // Single LF. 120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (*iter == '\r') { 122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if ((iter + 1) == input.end() || *(iter + 1) != '\n') 123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return 1; // Single CR (Commodore and Old Macs). 124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return 2; // CR-LF. 125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return 0; 128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 130dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} // namespace net 131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} // namespace browser 132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} // namespace chrome 133