PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/webview/native/Source/WebCore/loader/TextResourceDecoder.cpp

https://bitbucket.org/rbair/rbair-controls-8
C++ | 684 lines | 536 code | 67 blank | 81 comment | 293 complexity | 25ebf32247294658e61d70152dc090b5 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, GPL-2.0, LGPL-2.0
  1. /*
  2. Copyright (C) 1999 Lars Knoll (knoll@mpi-hd.mpg.de)
  3. Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights reserved.
  4. Copyright (C) 2005, 2006, 2007 Alexey Proskuryakov (ap@nypop.com)
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Library General Public
  7. License as published by the Free Software Foundation; either
  8. version 2 of the License, or (at your option) any later version.
  9. This library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Library General Public License for more details.
  13. You should have received a copy of the GNU Library General Public License
  14. along with this library; see the file COPYING.LIB. If not, write to
  15. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  16. Boston, MA 02110-1301, USA.
  17. */
  18. #include "config.h"
  19. #include "TextResourceDecoder.h"
  20. #include "DOMImplementation.h"
  21. #include "HTMLMetaCharsetParser.h"
  22. #include "HTMLNames.h"
  23. #include "TextCodec.h"
  24. #include "TextEncoding.h"
  25. #include "TextEncodingDetector.h"
  26. #include "TextEncodingRegistry.h"
  27. #include <wtf/ASCIICType.h>
  28. #include <wtf/StringExtras.h>
  29. using namespace WTF;
  30. namespace WebCore {
  31. using namespace HTMLNames;
  32. static inline bool bytesEqual(const char* p, char b0, char b1)
  33. {
  34. return p[0] == b0 && p[1] == b1;
  35. }
  36. static inline bool bytesEqual(const char* p, char b0, char b1, char b2)
  37. {
  38. return p[0] == b0 && p[1] == b1 && p[2] == b2;
  39. }
  40. static inline bool bytesEqual(const char* p, char b0, char b1, char b2, char b3, char b4)
  41. {
  42. return p[0] == b0 && p[1] == b1 && p[2] == b2 && p[3] == b3 && p[4] == b4;
  43. }
  44. static inline bool bytesEqual(const char* p, char b0, char b1, char b2, char b3, char b4, char b5)
  45. {
  46. return p[0] == b0 && p[1] == b1 && p[2] == b2 && p[3] == b3 && p[4] == b4 && p[5] == b5;
  47. }
  48. static inline bool bytesEqual(const char* p, char b0, char b1, char b2, char b3, char b4, char b5, char b6, char b7)
  49. {
  50. return p[0] == b0 && p[1] == b1 && p[2] == b2 && p[3] == b3 && p[4] == b4 && p[5] == b5 && p[6] == b6 && p[7] == b7;
  51. }
  52. // You might think we should put these find functions elsewhere, perhaps with the
  53. // similar functions that operate on UChar, but arguably only the decoder has
  54. // a reason to process strings of char rather than UChar.
  55. static int find(const char* subject, size_t subjectLength, const char* target)
  56. {
  57. size_t targetLength = strlen(target);
  58. if (targetLength > subjectLength)
  59. return -1;
  60. for (size_t i = 0; i <= subjectLength - targetLength; ++i) {
  61. bool match = true;
  62. for (size_t j = 0; j < targetLength; ++j) {
  63. if (subject[i + j] != target[j]) {
  64. match = false;
  65. break;
  66. }
  67. }
  68. if (match)
  69. return i;
  70. }
  71. return -1;
  72. }
  73. static TextEncoding findTextEncoding(const char* encodingName, int length)
  74. {
  75. Vector<char, 64> buffer(length + 1);
  76. memcpy(buffer.data(), encodingName, length);
  77. buffer[length] = '\0';
  78. return buffer.data();
  79. }
  80. class KanjiCode {
  81. public:
  82. enum Type { ASCII, JIS, EUC, SJIS, UTF16, UTF8 };
  83. static enum Type judge(const char* str, int length);
  84. static const int ESC = 0x1b;
  85. static const unsigned char sjisMap[256];
  86. static int ISkanji(int code)
  87. {
  88. if (code >= 0x100)
  89. return 0;
  90. return sjisMap[code & 0xff] & 1;
  91. }
  92. static int ISkana(int code)
  93. {
  94. if (code >= 0x100)
  95. return 0;
  96. return sjisMap[code & 0xff] & 2;
  97. }
  98. };
  99. const unsigned char KanjiCode::sjisMap[256] = {
  100. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  101. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  102. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  103. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  104. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  105. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  106. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  107. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  108. 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  109. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  110. 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  111. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  112. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  113. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  114. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  115. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0
  116. };
  117. /*
  118. * EUC-JP is
  119. * [0xa1 - 0xfe][0xa1 - 0xfe]
  120. * 0x8e[0xa1 - 0xfe](SS2)
  121. * 0x8f[0xa1 - 0xfe][0xa1 - 0xfe](SS3)
  122. *
  123. * Shift_Jis is
  124. * [0x81 - 0x9f, 0xe0 - 0xef(0xfe?)][0x40 - 0x7e, 0x80 - 0xfc]
  125. *
  126. * Shift_Jis Hankaku Kana is
  127. * [0xa1 - 0xdf]
  128. */
  129. /*
  130. * KanjiCode::judge() is based on judge_jcode() from jvim
  131. * http://hp.vector.co.jp/authors/VA003457/vim/
  132. *
  133. * Special Thanks to Kenichi Tsuchida
  134. */
  135. enum KanjiCode::Type KanjiCode::judge(const char* str, int size)
  136. {
  137. enum Type code;
  138. int i;
  139. int bfr = false; /* Kana Moji */
  140. int bfk = 0; /* EUC Kana */
  141. int sjis = 0;
  142. int euc = 0;
  143. const unsigned char* ptr = reinterpret_cast<const unsigned char*>(str);
  144. code = ASCII;
  145. i = 0;
  146. while (i < size) {
  147. if (ptr[i] == ESC && (size - i >= 3)) {
  148. if (bytesEqual(str + i + 1, '$', 'B')
  149. || bytesEqual(str + i + 1, '(', 'B')
  150. || bytesEqual(str + i + 1, '$', '@')
  151. || bytesEqual(str + i + 1, '(', 'J')) {
  152. code = JIS;
  153. goto breakBreak;
  154. }
  155. if (bytesEqual(str + i + 1, '(', 'I') || bytesEqual(str + i + 1, ')', 'I')) {
  156. code = JIS;
  157. i += 3;
  158. } else {
  159. i++;
  160. }
  161. bfr = false;
  162. bfk = 0;
  163. } else {
  164. if (ptr[i] < 0x20) {
  165. bfr = false;
  166. bfk = 0;
  167. /* ?? check kudokuten ?? && ?? hiragana ?? */
  168. if ((i >= 2) && (ptr[i - 2] == 0x81)
  169. && (0x41 <= ptr[i - 1] && ptr[i - 1] <= 0x49)) {
  170. code = SJIS;
  171. sjis += 100; /* kudokuten */
  172. } else if ((i >= 2) && (ptr[i - 2] == 0xa1)
  173. && (0xa2 <= ptr[i - 1] && ptr[i - 1] <= 0xaa)) {
  174. code = EUC;
  175. euc += 100; /* kudokuten */
  176. } else if ((i >= 2) && (ptr[i - 2] == 0x82) && (0xa0 <= ptr[i - 1])) {
  177. sjis += 40; /* hiragana */
  178. } else if ((i >= 2) && (ptr[i - 2] == 0xa4) && (0xa0 <= ptr[i - 1])) {
  179. euc += 40; /* hiragana */
  180. }
  181. } else {
  182. /* ?? check hiragana or katana ?? */
  183. if ((size - i > 1) && (ptr[i] == 0x82) && (0xa0 <= ptr[i + 1])) {
  184. sjis++; /* hiragana */
  185. } else if ((size - i > 1) && (ptr[i] == 0x83)
  186. && (0x40 <= ptr[i + 1] && ptr[i + 1] <= 0x9f)) {
  187. sjis++; /* katakana */
  188. } else if ((size - i > 1) && (ptr[i] == 0xa4) && (0xa0 <= ptr[i + 1])) {
  189. euc++; /* hiragana */
  190. } else if ((size - i > 1) && (ptr[i] == 0xa5) && (0xa0 <= ptr[i + 1])) {
  191. euc++; /* katakana */
  192. }
  193. if (bfr) {
  194. if ((i >= 1) && (0x40 <= ptr[i] && ptr[i] <= 0xa0) && ISkanji(ptr[i - 1])) {
  195. code = SJIS;
  196. goto breakBreak;
  197. } else if ((i >= 1) && (0x81 <= ptr[i - 1] && ptr[i - 1] <= 0x9f) && ((0x40 <= ptr[i] && ptr[i] < 0x7e) || (0x7e < ptr[i] && ptr[i] <= 0xfc))) {
  198. code = SJIS;
  199. goto breakBreak;
  200. } else if ((i >= 1) && (0xfd <= ptr[i] && ptr[i] <= 0xfe) && (0xa1 <= ptr[i - 1] && ptr[i - 1] <= 0xfe)) {
  201. code = EUC;
  202. goto breakBreak;
  203. } else if ((i >= 1) && (0xfd <= ptr[i - 1] && ptr[i - 1] <= 0xfe) && (0xa1 <= ptr[i] && ptr[i] <= 0xfe)) {
  204. code = EUC;
  205. goto breakBreak;
  206. } else if ((i >= 1) && (ptr[i] < 0xa0 || 0xdf < ptr[i]) && (0x8e == ptr[i - 1])) {
  207. code = SJIS;
  208. goto breakBreak;
  209. } else if (ptr[i] <= 0x7f) {
  210. code = SJIS;
  211. goto breakBreak;
  212. } else {
  213. if (0xa1 <= ptr[i] && ptr[i] <= 0xa6) {
  214. euc++; /* sjis hankaku kana kigo */
  215. } else if (0xa1 <= ptr[i] && ptr[i] <= 0xdf) {
  216. ; /* sjis hankaku kana */
  217. } else if (0xa1 <= ptr[i] && ptr[i] <= 0xfe) {
  218. euc++;
  219. } else if (0x8e == ptr[i]) {
  220. euc++;
  221. } else if (0x20 <= ptr[i] && ptr[i] <= 0x7f) {
  222. sjis++;
  223. }
  224. bfr = false;
  225. bfk = 0;
  226. }
  227. } else if (0x8e == ptr[i]) {
  228. if (size - i <= 1) {
  229. ;
  230. } else if (0xa1 <= ptr[i + 1] && ptr[i + 1] <= 0xdf) {
  231. /* EUC KANA or SJIS KANJI */
  232. if (bfk == 1) {
  233. euc += 100;
  234. }
  235. bfk++;
  236. i++;
  237. } else {
  238. /* SJIS only */
  239. code = SJIS;
  240. goto breakBreak;
  241. }
  242. } else if (0x81 <= ptr[i] && ptr[i] <= 0x9f) {
  243. /* SJIS only */
  244. code = SJIS;
  245. if ((size - i >= 1)
  246. && ((0x40 <= ptr[i + 1] && ptr[i + 1] <= 0x7e)
  247. || (0x80 <= ptr[i + 1] && ptr[i + 1] <= 0xfc))) {
  248. goto breakBreak;
  249. }
  250. } else if (0xfd <= ptr[i] && ptr[i] <= 0xfe) {
  251. /* EUC only */
  252. code = EUC;
  253. if ((size - i >= 1)
  254. && (0xa1 <= ptr[i + 1] && ptr[i + 1] <= 0xfe)) {
  255. goto breakBreak;
  256. }
  257. } else if (ptr[i] <= 0x7f) {
  258. ;
  259. } else {
  260. bfr = true;
  261. bfk = 0;
  262. }
  263. }
  264. i++;
  265. }
  266. }
  267. if (code == ASCII) {
  268. if (sjis > euc) {
  269. code = SJIS;
  270. } else if (sjis < euc) {
  271. code = EUC;
  272. }
  273. }
  274. breakBreak:
  275. return (code);
  276. }
  277. TextResourceDecoder::ContentType TextResourceDecoder::determineContentType(const String& mimeType)
  278. {
  279. if (equalIgnoringCase(mimeType, "text/css"))
  280. return CSS;
  281. if (equalIgnoringCase(mimeType, "text/html"))
  282. return HTML;
  283. if (DOMImplementation::isXMLMIMEType(mimeType))
  284. return XML;
  285. return PlainText;
  286. }
  287. const TextEncoding& TextResourceDecoder::defaultEncoding(ContentType contentType, const TextEncoding& specifiedDefaultEncoding)
  288. {
  289. // Despite 8.5 "Text/xml with Omitted Charset" of RFC 3023, we assume UTF-8 instead of US-ASCII
  290. // for text/xml. This matches Firefox.
  291. if (contentType == XML)
  292. return UTF8Encoding();
  293. if (!specifiedDefaultEncoding.isValid())
  294. return Latin1Encoding();
  295. return specifiedDefaultEncoding;
  296. }
  297. TextResourceDecoder::TextResourceDecoder(const String& mimeType, const TextEncoding& specifiedDefaultEncoding, bool usesEncodingDetector)
  298. : m_contentType(determineContentType(mimeType))
  299. , m_encoding(defaultEncoding(m_contentType, specifiedDefaultEncoding))
  300. , m_source(DefaultEncoding)
  301. , m_hintEncoding(0)
  302. , m_checkedForBOM(false)
  303. , m_checkedForCSSCharset(false)
  304. , m_checkedForHeadCharset(false)
  305. , m_useLenientXMLDecoding(false)
  306. , m_sawError(false)
  307. , m_usesEncodingDetector(usesEncodingDetector)
  308. {
  309. }
  310. TextResourceDecoder::~TextResourceDecoder()
  311. {
  312. }
  313. void TextResourceDecoder::setEncoding(const TextEncoding& encoding, EncodingSource source)
  314. {
  315. // In case the encoding didn't exist, we keep the old one (helps some sites specifying invalid encodings).
  316. if (!encoding.isValid())
  317. return;
  318. // When encoding comes from meta tag (i.e. it cannot be XML files sent via XHR),
  319. // treat x-user-defined as windows-1252 (bug 18270)
  320. if (source == EncodingFromMetaTag && strcasecmp(encoding.name(), "x-user-defined") == 0)
  321. m_encoding = "windows-1252";
  322. else if (source == EncodingFromMetaTag || source == EncodingFromXMLHeader || source == EncodingFromCSSCharset)
  323. m_encoding = encoding.closestByteBasedEquivalent();
  324. else
  325. m_encoding = encoding;
  326. m_codec.clear();
  327. m_source = source;
  328. }
  329. // Returns the position of the encoding string.
  330. static int findXMLEncoding(const char* str, int len, int& encodingLength)
  331. {
  332. int pos = find(str, len, "encoding");
  333. if (pos == -1)
  334. return -1;
  335. pos += 8;
  336. // Skip spaces and stray control characters.
  337. while (pos < len && str[pos] <= ' ')
  338. ++pos;
  339. // Skip equals sign.
  340. if (pos >= len || str[pos] != '=')
  341. return -1;
  342. ++pos;
  343. // Skip spaces and stray control characters.
  344. while (pos < len && str[pos] <= ' ')
  345. ++pos;
  346. // Skip quotation mark.
  347. if (pos >= len)
  348. return - 1;
  349. char quoteMark = str[pos];
  350. if (quoteMark != '"' && quoteMark != '\'')
  351. return -1;
  352. ++pos;
  353. // Find the trailing quotation mark.
  354. int end = pos;
  355. while (end < len && str[end] != quoteMark)
  356. ++end;
  357. if (end >= len)
  358. return -1;
  359. encodingLength = end - pos;
  360. return pos;
  361. }
  362. // true if there is more to parse
  363. static inline bool skipWhitespace(const char*& pos, const char* dataEnd)
  364. {
  365. while (pos < dataEnd && (*pos == '\t' || *pos == ' '))
  366. ++pos;
  367. return pos != dataEnd;
  368. }
  369. size_t TextResourceDecoder::checkForBOM(const char* data, size_t len)
  370. {
  371. // Check for UTF-16/32 or UTF-8 BOM mark at the beginning, which is a sure sign of a Unicode encoding.
  372. // We let it override even a user-chosen encoding.
  373. ASSERT(!m_checkedForBOM);
  374. size_t lengthOfBOM = 0;
  375. size_t bufferLength = m_buffer.size();
  376. size_t buf1Len = bufferLength;
  377. size_t buf2Len = len;
  378. const unsigned char* buf1 = reinterpret_cast<const unsigned char*>(m_buffer.data());
  379. const unsigned char* buf2 = reinterpret_cast<const unsigned char*>(data);
  380. unsigned char c1 = buf1Len ? (--buf1Len, *buf1++) : buf2Len ? (--buf2Len, *buf2++) : 0;
  381. unsigned char c2 = buf1Len ? (--buf1Len, *buf1++) : buf2Len ? (--buf2Len, *buf2++) : 0;
  382. unsigned char c3 = buf1Len ? (--buf1Len, *buf1++) : buf2Len ? (--buf2Len, *buf2++) : 0;
  383. unsigned char c4 = buf2Len ? (--buf2Len, *buf2++) : 0;
  384. // Check for the BOM.
  385. if (c1 == 0xFF && c2 == 0xFE) {
  386. if (c3 != 0 || c4 != 0) {
  387. setEncoding(UTF16LittleEndianEncoding(), AutoDetectedEncoding);
  388. lengthOfBOM = 2;
  389. } else {
  390. setEncoding(UTF32LittleEndianEncoding(), AutoDetectedEncoding);
  391. lengthOfBOM = 4;
  392. }
  393. } else if (c1 == 0xEF && c2 == 0xBB && c3 == 0xBF) {
  394. setEncoding(UTF8Encoding(), AutoDetectedEncoding);
  395. lengthOfBOM = 3;
  396. } else if (c1 == 0xFE && c2 == 0xFF) {
  397. setEncoding(UTF16BigEndianEncoding(), AutoDetectedEncoding);
  398. lengthOfBOM = 2;
  399. } else if (c1 == 0 && c2 == 0 && c3 == 0xFE && c4 == 0xFF) {
  400. setEncoding(UTF32BigEndianEncoding(), AutoDetectedEncoding);
  401. lengthOfBOM = 4;
  402. }
  403. if (lengthOfBOM || bufferLength + len >= 4)
  404. m_checkedForBOM = true;
  405. return lengthOfBOM;
  406. }
  407. bool TextResourceDecoder::checkForCSSCharset(const char* data, size_t len, bool& movedDataToBuffer)
  408. {
  409. if (m_source != DefaultEncoding && m_source != EncodingFromParentFrame) {
  410. m_checkedForCSSCharset = true;
  411. return true;
  412. }
  413. size_t oldSize = m_buffer.size();
  414. m_buffer.grow(oldSize + len);
  415. memcpy(m_buffer.data() + oldSize, data, len);
  416. movedDataToBuffer = true;
  417. if (m_buffer.size() <= 8) // strlen("@charset") == 8
  418. return false;
  419. const char* dataStart = m_buffer.data();
  420. const char* dataEnd = dataStart + m_buffer.size();
  421. if (bytesEqual(dataStart, '@', 'c', 'h', 'a', 'r', 's', 'e', 't')) {
  422. dataStart += 8;
  423. const char* pos = dataStart;
  424. if (!skipWhitespace(pos, dataEnd))
  425. return false;
  426. if (*pos == '"' || *pos == '\'') {
  427. char quotationMark = *pos;
  428. ++pos;
  429. dataStart = pos;
  430. while (pos < dataEnd && *pos != quotationMark)
  431. ++pos;
  432. if (pos == dataEnd)
  433. return false;
  434. int encodingNameLength = pos - dataStart;
  435. ++pos;
  436. if (!skipWhitespace(pos, dataEnd))
  437. return false;
  438. if (*pos == ';')
  439. setEncoding(findTextEncoding(dataStart, encodingNameLength), EncodingFromCSSCharset);
  440. }
  441. }
  442. m_checkedForCSSCharset = true;
  443. return true;
  444. }
  445. bool TextResourceDecoder::checkForHeadCharset(const char* data, size_t len, bool& movedDataToBuffer)
  446. {
  447. if (m_source != DefaultEncoding && m_source != EncodingFromParentFrame) {
  448. m_checkedForHeadCharset = true;
  449. return true;
  450. }
  451. // This is not completely efficient, since the function might go
  452. // through the HTML head several times.
  453. size_t oldSize = m_buffer.size();
  454. m_buffer.grow(oldSize + len);
  455. memcpy(m_buffer.data() + oldSize, data, len);
  456. movedDataToBuffer = true;
  457. // Continue with checking for an HTML meta tag if we were already doing so.
  458. if (m_charsetParser)
  459. return checkForMetaCharset(data, len);
  460. const char* ptr = m_buffer.data();
  461. const char* pEnd = ptr + m_buffer.size();
  462. // Is there enough data available to check for XML declaration?
  463. if (m_buffer.size() < 8)
  464. return false;
  465. // Handle XML declaration, which can have encoding in it. This encoding is honored even for HTML documents.
  466. // It is an error for an XML declaration not to be at the start of an XML document, and it is ignored in HTML documents in such case.
  467. if (bytesEqual(ptr, '<', '?', 'x', 'm', 'l')) {
  468. const char* xmlDeclarationEnd = ptr;
  469. while (xmlDeclarationEnd != pEnd && *xmlDeclarationEnd != '>')
  470. ++xmlDeclarationEnd;
  471. if (xmlDeclarationEnd == pEnd)
  472. return false;
  473. // No need for +1, because we have an extra "?" to lose at the end of XML declaration.
  474. int len = 0;
  475. int pos = findXMLEncoding(ptr, xmlDeclarationEnd - ptr, len);
  476. if (pos != -1)
  477. setEncoding(findTextEncoding(ptr + pos, len), EncodingFromXMLHeader);
  478. // continue looking for a charset - it may be specified in an HTTP-Equiv meta
  479. } else if (bytesEqual(ptr, '<', 0, '?', 0, 'x', 0)) {
  480. setEncoding(UTF16LittleEndianEncoding(), AutoDetectedEncoding);
  481. return true;
  482. } else if (bytesEqual(ptr, 0, '<', 0, '?', 0, 'x')) {
  483. setEncoding(UTF16BigEndianEncoding(), AutoDetectedEncoding);
  484. return true;
  485. } else if (bytesEqual(ptr, '<', 0, 0, 0, '?', 0, 0, 0)) {
  486. setEncoding(UTF32LittleEndianEncoding(), AutoDetectedEncoding);
  487. return true;
  488. } else if (bytesEqual(ptr, 0, 0, 0, '<', 0, 0, 0, '?')) {
  489. setEncoding(UTF32BigEndianEncoding(), AutoDetectedEncoding);
  490. return true;
  491. }
  492. // The HTTP-EQUIV meta has no effect on XHTML.
  493. if (m_contentType == XML)
  494. return true;
  495. m_charsetParser = HTMLMetaCharsetParser::create();
  496. return checkForMetaCharset(data, len);
  497. }
  498. bool TextResourceDecoder::checkForMetaCharset(const char* data, size_t length)
  499. {
  500. if (!m_charsetParser->checkForMetaCharset(data, length))
  501. return false;
  502. setEncoding(m_charsetParser->encoding(), EncodingFromMetaTag);
  503. m_charsetParser.clear();
  504. m_checkedForHeadCharset = true;
  505. return true;
  506. }
  507. void TextResourceDecoder::detectJapaneseEncoding(const char* data, size_t len)
  508. {
  509. switch (KanjiCode::judge(data, len)) {
  510. case KanjiCode::JIS:
  511. setEncoding("ISO-2022-JP", AutoDetectedEncoding);
  512. break;
  513. case KanjiCode::EUC:
  514. setEncoding("EUC-JP", AutoDetectedEncoding);
  515. break;
  516. case KanjiCode::SJIS:
  517. setEncoding("Shift_JIS", AutoDetectedEncoding);
  518. break;
  519. case KanjiCode::ASCII:
  520. case KanjiCode::UTF16:
  521. case KanjiCode::UTF8:
  522. break;
  523. }
  524. }
  525. // We use the encoding detector in two cases:
  526. // 1. Encoding detector is turned ON and no other encoding source is
  527. // available (that is, it's DefaultEncoding).
  528. // 2. Encoding detector is turned ON and the encoding is set to
  529. // the encoding of the parent frame, which is also auto-detected.
  530. // Note that condition #2 is NOT satisfied unless parent-child frame
  531. // relationship is compliant to the same-origin policy. If they're from
  532. // different domains, |m_source| would not be set to EncodingFromParentFrame
  533. // in the first place.
  534. bool TextResourceDecoder::shouldAutoDetect() const
  535. {
  536. // Just checking m_hintEncoding suffices here because it's only set
  537. // in setHintEncoding when the source is AutoDetectedEncoding.
  538. return m_usesEncodingDetector
  539. && (m_source == DefaultEncoding || (m_source == EncodingFromParentFrame && m_hintEncoding));
  540. }
  541. String TextResourceDecoder::decode(const char* data, size_t len)
  542. {
  543. size_t lengthOfBOM = 0;
  544. if (!m_checkedForBOM)
  545. lengthOfBOM = checkForBOM(data, len);
  546. bool movedDataToBuffer = false;
  547. if (m_contentType == CSS && !m_checkedForCSSCharset)
  548. if (!checkForCSSCharset(data, len, movedDataToBuffer))
  549. return emptyString();
  550. if ((m_contentType == HTML || m_contentType == XML) && !m_checkedForHeadCharset) // HTML and XML
  551. if (!checkForHeadCharset(data, len, movedDataToBuffer))
  552. return emptyString();
  553. // FIXME: It is wrong to change the encoding downstream after we have already done some decoding.
  554. if (shouldAutoDetect()) {
  555. if (m_encoding.isJapanese())
  556. detectJapaneseEncoding(data, len); // FIXME: We should use detectTextEncoding() for all languages.
  557. else {
  558. TextEncoding detectedEncoding;
  559. if (detectTextEncoding(data, len, m_hintEncoding, &detectedEncoding))
  560. setEncoding(detectedEncoding, AutoDetectedEncoding);
  561. }
  562. }
  563. ASSERT(m_encoding.isValid());
  564. if (!m_codec)
  565. m_codec = newTextCodec(m_encoding);
  566. if (m_buffer.isEmpty())
  567. return m_codec->decode(data + lengthOfBOM, len - lengthOfBOM, false, m_contentType == XML, m_sawError);
  568. if (!movedDataToBuffer) {
  569. size_t oldSize = m_buffer.size();
  570. m_buffer.grow(oldSize + len);
  571. memcpy(m_buffer.data() + oldSize, data, len);
  572. }
  573. String result = m_codec->decode(m_buffer.data() + lengthOfBOM, m_buffer.size() - lengthOfBOM, false, m_contentType == XML && !m_useLenientXMLDecoding, m_sawError);
  574. m_buffer.clear();
  575. return result;
  576. }
  577. String TextResourceDecoder::flush()
  578. {
  579. // If we can not identify the encoding even after a document is completely
  580. // loaded, we need to detect the encoding if other conditions for
  581. // autodetection is satisfied.
  582. if (m_buffer.size() && shouldAutoDetect()
  583. && ((!m_checkedForHeadCharset && (m_contentType == HTML || m_contentType == XML)) || (!m_checkedForCSSCharset && (m_contentType == CSS)))) {
  584. TextEncoding detectedEncoding;
  585. if (detectTextEncoding(m_buffer.data(), m_buffer.size(),
  586. m_hintEncoding, &detectedEncoding))
  587. setEncoding(detectedEncoding, AutoDetectedEncoding);
  588. }
  589. if (!m_codec)
  590. m_codec = newTextCodec(m_encoding);
  591. String result = m_codec->decode(m_buffer.data(), m_buffer.size(), true, m_contentType == XML && !m_useLenientXMLDecoding, m_sawError);
  592. m_buffer.clear();
  593. m_codec.clear();
  594. m_checkedForBOM = false; // Skip BOM again when re-decoding.
  595. return result;
  596. }
  597. }