/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* libwpd * Version: MPL 2.0 / LGPLv2.1+ * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Major Contributor(s): * Copyright (C) 2003 William Lachance (wrlach@gmail.com) * Copyright (C) 2003 Marc Maurer (uwog@uwog.net) * Copyright (C) 2006 Fridrich Strba (fridrich.strba@bluewin.ch) * * For minor contributions see the git repository. * * Alternatively, the contents of this file may be used under the terms * of the GNU Lesser General Public License Version 2.1 or later * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are * applicable instead of those above. * * For further information visit http://libwpd.sourceforge.net */ /* "This product is not manufactured, approved, or supported by * Corel Corporation or Corel Corporation Limited." */ #include "WP42Heuristics.h" #include #include "WP42FileStructure.h" #include "libwpd_internal.h" using namespace libwpd; WPDPasswordMatch WP42Heuristics::verifyPassword(librevenge::RVNGInputStream *input, const char *password) try { if (!password) return WPD_PASSWORD_MATCH_DONTKNOW; input->seek(0, librevenge::RVNG_SEEK_SET); if (readU8(input, nullptr) == 0xFE && readU8(input, nullptr) == 0xFF && readU8(input, nullptr) == 0x61 && readU8(input, nullptr) == 0x61) { WPXEncryption encryption(password, 6); if (readU16(input, nullptr) == encryption.getCheckSum()) return WPD_PASSWORD_MATCH_OK; else return WPD_PASSWORD_MATCH_NONE; } else return WPD_PASSWORD_MATCH_DONTKNOW; } catch (...) { return WPD_PASSWORD_MATCH_DONTKNOW; } WPDConfidence WP42Heuristics::isWP42FileFormat(librevenge::RVNGInputStream *input, const char *password) try { input->seek(0, librevenge::RVNG_SEEK_SET); std::unique_ptr encryption; if (readU8(input, nullptr) == 0xFE && readU8(input, nullptr) == 0xFF && readU8(input, nullptr) == 0x61 && readU8(input, nullptr) == 0x61) { if (password) { encryption.reset(new WPXEncryption(password, 6)); if (readU16(input, nullptr) != encryption->getCheckSum()) return WPD_CONFIDENCE_SUPPORTED_ENCRYPTION; } else { if (readU16(input,nullptr) != 0x0000) return WPD_CONFIDENCE_SUPPORTED_ENCRYPTION; } } input->seek(0, librevenge::RVNG_SEEK_SET); if (password && encryption) input->seek(6, librevenge::RVNG_SEEK_SET); int functionGroupCount = 0; WPD_DEBUG_MSG(("WP42Heuristics::isWP42FileFormat()\n")); while (!input->isEnd()) { unsigned char readVal = readU8(input, encryption.get()); WPD_DEBUG_MSG(("WP42Heuristics, Offset 0x%.8x, value 0x%.2x\n", (unsigned int)(input->tell() - 1), readVal)); if (readVal < (unsigned char)0x20) { // line breaks et al, skip } else if (readVal >= (unsigned char)0x20 && readVal <= (unsigned char)0x7F) { // normal ASCII characters, skip } else if (readVal >= (unsigned char)0x80 && readVal <= (unsigned char)0xBF) { // single character function codes, skip functionGroupCount++; } else if (readVal >= (unsigned char)0xFF) { // special codes that should not be found as separate functions return WPD_CONFIDENCE_NONE; } else { // multi character function group // check that the size constrains are valid, and that every group_member // is properly closed at the right place if (WP42_FUNCTION_GROUP_SIZE[readVal-0xC0] == -1) { // variable length function group // skip over all the bytes in the group, and scan for the closing gate unsigned char readNextVal = 0; while (!input->isEnd()) { readNextVal = readU8(input, encryption.get()); if (readNextVal == readVal) break; } // when passed the complete file, we don't allow for open groups when we've reached EOF if ((readNextVal == 0) || (input->isEnd() && (readNextVal != readVal))) return WPD_CONFIDENCE_NONE; functionGroupCount++; } else { // fixed length function group // seek to the position where the closing gate should be int res = input->seek(WP42_FUNCTION_GROUP_SIZE[readVal-0xC0]-2, librevenge::RVNG_SEEK_CUR); // when passed the complete file, we should be able to do that if (res) return WPD_CONFIDENCE_NONE; // read the closing gate unsigned char readNextVal = readU8(input, encryption.get()); if (readNextVal != readVal) return WPD_CONFIDENCE_NONE; functionGroupCount++; } } } /* When we get here, the document is in a format that we *could* import properly. However, if we didn't entcounter a single WP4.2 function group) we need to be more carefull: this would be the case when passed a plaintext file for example, which libwpd is not supposed to handle. */ if (!functionGroupCount && !encryption) return WPD_CONFIDENCE_NONE; return WPD_CONFIDENCE_EXCELLENT; } catch (...) { return WPD_CONFIDENCE_NONE; } /* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */