<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* libwps
 * 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) 2002 <NAME> (<EMAIL>)
 * Copyright (C) 2002-2004 <NAME> (<EMAIL>)
 *
 * 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://libwps.sourceforge.net
 */

#include <string.h>

#include "libwps_internal.h"

#include "WPSHeader.h"

using namespace libwps;

WPSHeader::WPSHeader(RVNGInputStreamPtr &input, RVNGInputStreamPtr &fileInput, uint8_t majorVersion, WPSKind kind, WPSCreator creator) :
	m_input(input), m_fileInput(fileInput), m_majorVersion(majorVersion), m_kind(kind), m_creator(creator),
	m_needEncodingFlag(false)
{
}

WPSHeader::~WPSHeader()
{
}


/**
 * So far, we have identified three categories of Works documents.
 *
 * Works documents versions 3 and later use a MS OLE container, so we detect
 * their type by checking for OLE stream names.  Works version 2 is like
 * Works 3 without OLE, so those two types use the same parser.
 *
 */
WPSHeader *WPSHeader::constructHeader(RVNGInputStreamPtr &input)
{
	if (!input->isStructured())
	{
		input->seek(0, librevenge::RVNG_SEEK_SET);
		uint8_t val[6];
		for (int i=0; i<6; ++i) val[i] = libwps::readU8(input);

		if (val[0] < 6 && val[1] == 0xFE)
		{
			WPS_DEBUG_MSG(("WPSHeader::constructHeader: Microsoft Works v2 format detected\n"));
			return new WPSHeader(input, input, 2);
		}
		// works1 dos file begin by 2054
		if ((val[0] == 0xFF || val[0] == 0x20) && val[1]==0x54)
		{
			WPS_DEBUG_MSG(("WPSHeader::constructHeader: Microsoft Works wks database\n"));
			return new WPSHeader(input, input, 1, WPS_DATABASE);
		}
		if (val[0] == 0xFF && val[1] == 0 && val[2]==2)
		{
			WPS_DEBUG_MSG(("WPSHeader::constructHeader: Microsoft Works wks detected\n"));
			return new WPSHeader(input, input, 3, WPS_SPREADSHEET);
		}
		if (val[0] == 00 && val[1] == 0 && val[2]==2)
		{
			if (val[3]==0 && (val[4]==0x20 || val[4]==0x21) && val[5]==0x51)
			{
				WPS_DEBUG_MSG(("WPSHeader::constructHeader: Quattro Pro wq1 or wq2 detected\n"));
				return new WPSHeader(input, input, 2, WPS_SPREADSHEET, WPS_QUATTRO_PRO);
			}
			WPS_DEBUG_MSG(("WPSHeader::constructHeader: potential Lotus|Microsft Works|Quattro Pro spreadsheet detected\n"));
			return new WPSHeader(input, input, 2, WPS_SPREADSHEET);
		}
		if (val[0] == 00 && val[1] == 0x0 && val[2]==0x1a)
		{
			WPS_DEBUG_MSG(("WPSHeader::constructHeader: Lotus spreadsheet detected\n"));
			return new WPSHeader(input, input, 101, WPS_SPREADSHEET, WPS_LOTUS);
		}
		if ((val[0] == 0x31 || val[0] == 0x32) && val[1] == 0xbe && val[2] == 0 && val[3] == 0 && val[4] == 0 && val[5] == 0xab)
		{
			WPS_DEBUG_MSG(("WPSHeader::constructHeader: Microsoft Write detected\n"));
			return new WPSHeader(input, input, 3, WPS_TEXT, WPS_MSWRITE);
		}
		return 0;
	}

	RVNGInputStreamPtr document_mn0(input->getSubStreamByName("MN0"));
	if (document_mn0)
	{
		// can be a mac or a pc document
		// each must contains a MM Ole which begins by 0x444e: Mac or 0x4e44: PC
		RVNGInputStreamPtr document_mm(input->getSubStreamByName("MM"));
		if (document_mm && libwps::readU16(document_mm) == 0x4e44)
		{
			WPS_DEBUG_MSG(("WPSHeader::constructHeader: Microsoft Works Mac v4 format detected\n"));
			return 0;
		}
		// now, look if this is a database document
		uint16_t fileMagic=libwps::readU16(document_mn0);
		if (fileMagic == 0x54FF)
		{
			WPS_DEBUG_MSG(("WPSHeader::constructHeader: Microsoft Works Database format detected\n"));
			return new WPSHeader(document_mn0, input, 4, WPS_DATABASE);
		}
		WPS_DEBUG_MSG(("WPSHeader::constructHeader: Microsoft Works v4 format detected\n"));
		return new WPSHeader(document_mn0, input, 4);
	}<commit_msg>MsWrite: do not detect Microsoft Word for DOS documents as MsWrite<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* libwps
 * 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) 2002 <NAME> (<EMAIL>)
 * Copyright (C) 2002-2004 <NAME> (<EMAIL>)
 *
 * 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://libwps.sourceforge.net
 */

#include <string.h>

#include "libwps_internal.h"

#include "WPSHeader.h"

using namespace libwps;

WPSHeader::WPSHeader(RVNGInputStreamPtr &input, RVNGInputStreamPtr &fileInput, uint8_t majorVersion, WPSKind kind, WPSCreator creator) :
	m_input(input), m_fileInput(fileInput), m_majorVersion(majorVersion), m_kind(kind), m_creator(creator),
	m_needEncodingFlag(false)
{
}

WPSHeader::~WPSHeader()
{
}


/**
 * So far, we have identified three categories of Works documents.
 *
 * Works documents versions 3 and later use a MS OLE container, so we detect
 * their type by checking for OLE stream names.  Works version 2 is like
 * Works 3 without OLE, so those two types use the same parser.
 *
 */
WPSHeader *WPSHeader::constructHeader(RVNGInputStreamPtr &input)
{
	if (!input->isStructured())
	{
		input->seek(0, librevenge::RVNG_SEEK_SET);
		uint8_t val[6];
		for (int i=0; i<6; ++i) val[i] = libwps::readU8(input);

		if (val[0] < 6 && val[1] == 0xFE)
		{
			WPS_DEBUG_MSG(("WPSHeader::constructHeader: Microsoft Works v2 format detected\n"));
			return new WPSHeader(input, input, 2);
		}
		// works1 dos file begin by 2054
		if ((val[0] == 0xFF || val[0] == 0x20) && val[1]==0x54)
		{
			WPS_DEBUG_MSG(("WPSHeader::constructHeader: Microsoft Works wks database\n"));
			return new WPSHeader(input, input, 1, WPS_DATABASE);
		}
		if (val[0] == 0xFF && val[1] == 0 && val[2]==2)
		{
			WPS_DEBUG_MSG(("WPSHeader::constructHeader: Microsoft Works wks detected\n"));
			return new WPSHeader(input, input, 3, WPS_SPREADSHEET);
		}
		if (val[0] == 00 && val[1] == 0 && val[2]==2)
		{
			if (val[3]==0 && (val[4]==0x20 || val[4]==0x21) && val[5]==0x51)
			{
				WPS_DEBUG_MSG(("WPSHeader::constructHeader: Quattro Pro wq1 or wq2 detected\n"));
				return new WPSHeader(input, input, 2, WPS_SPREADSHEET, WPS_QUATTRO_PRO);
			}
			WPS_DEBUG_MSG(("WPSHeader::constructHeader: potential Lotus|Microsft Works|Quattro Pro spreadsheet detected\n"));
			return new WPSHeader(input, input, 2, WPS_SPREADSHEET);
		}
		if (val[0] == 00 && val[1] == 0x0 && val[2]==0x1a)
		{
			WPS_DEBUG_MSG(("WPSHeader::constructHeader: Lotus spreadsheet detected\n"));
			return new WPSHeader(input, input, 101, WPS_SPREADSHEET, WPS_LOTUS);
		}
		if ((val[0] == 0x31 || val[0] == 0x32) && val[1] == 0xbe && val[2] == 0 && val[3] == 0 && val[4] == 0 && val[5] == 0xab)
		{
			// This value is always 0 for Word for DOS
			input->seek(96, librevenge::RVNG_SEEK_SET);
			if (libwps::readU16(input))
			{
				WPS_DEBUG_MSG(("WPSHeader::constructHeader: Microsoft Write detected\n"));
				return new WPSHeader(input, input, 3, WPS_TEXT, WPS_MSWRITE);
			}
			else
			{
				WPS_DEBUG_MSG(("WPSHeader::constructHeader: Microsoft Word for DOS detected, not supported yet\n"));
			}
		}
		return 0;
	}

	RVNGInputStreamPtr document_mn0(input->getSubStreamByName("MN0"));
	if (document_mn0)
	{
		// can be a mac or a pc document
		// each must contains a MM Ole which begins by 0x444e: Mac or 0x4e44: PC
		RVNGInputStreamPtr document_mm(input->getSubStreamByName("MM"));
		if (document_mm && libwps::readU16(document_mm) == 0x4e44)
		{
			WPS_DEBUG_MSG(("WPSHeader::constructHeader: Microsoft Works Mac v4 format detected\n"));
			return 0;
		}
		// now, look if this is a database document
		uint16_t fileMagic=libwps::readU16(document_mn0);
		if (fileMagic == 0x54FF)
		{
			WPS_DEBUG_MSG(("WPSHeader::constructHeader: Microsoft Works Database format detected\n"));
			return new WPSHeader(document_mn0, input, 4, WPS_DATABASE);
		}
		WPS_DEBUG_MSG(("WPSHeader::constructHeader: Microsoft Works v4 format detected\n"));
		return new WPSHeader(document_mn0, input, 4);
	}
{'fraction_non_alphanumeric': 0.14333180568285978, 'fraction_numerical': 0.036319890009165905, 'mean_word_length': 4.418373680943513, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4401650', 'n_tokens_mistral': 3531, 'n_tokens_neox': 3177, 'n_words': 867}