/** -*-c++-*-
 * $Id$
 *
 * This file is part of plptools.
 *
 *  Copyright (C) 2002 Daniel Brahneborg <basic.chello@se>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "sisfileheader.h"
#include "plpintl.h"

#include <stdio.h>
#include <stdlib.h>

const int OFF_NUMBER_OF_FILES = 26;
const int OFF_INSTALLATION_DRIVE = 28;

SisRC
SISFileHeader::compareApp(SISFileHeader* other)
{
	if (m_uid1 != other->m_uid1)
		return SIS_DIFFERENT_APP;
	if ((m_major < other->m_major) ||
		((m_major == other->m_major) &&
		 (m_minor < other->m_minor)))
		return SIS_VER_EARLIER;
	if ((m_major == other->m_major) &&
		(m_minor == other->m_minor) &&
		(m_variant != other->m_variant))
		return SIS_OTHER_VARIANT;
	return SIS_SAME_OR_LATER;
}

SisRC
SISFileHeader::fillFrom(uint8_t* buf, int* base, off_t len)
{
	if (*base + 68 > len)
		return SIS_TRUNCATED;
	uint8_t* start = buf + *base;
	m_buf = buf;
	m_uid1 = read32(start);
	if (logLevel >= 1)
		printf(_("Got uid1 = %08x\n"), m_uid1);
	m_uid2 = read32(start + 4);
	if (m_uid2 != 0x1000006d)
		{
		printf(_("Got bad uid2.\n"));
		return SIS_CORRUPTED;
		}
	if (logLevel >= 2)
		printf(_("Got uid2 = %08x\n"), m_uid2);
	m_uid3 = read32(start + 8);
	if (m_uid3 != 0x10000419)
		{
		printf(_("Got bad uid3.\n"));
		return SIS_CORRUPTED;
		}
	if (logLevel >= 2)
		printf(_("Got uid3 = %08x\n"), m_uid3);
	m_uid4 = read32(start + 12);
//	printf(_("Got uid4 = %08x\n"), m_uid4);
	uint16_t crc1 = 0;
	for (int i = 0; i < 12; i += 2)
		crc1 = updateCrc(crc1, buf[*base + i]);
	uint16_t crc2 = 0;
	for (int i = 0; i < 12; i += 2)
		crc2 = updateCrc(crc2, buf[*base + i + 1]);
	if (logLevel >= 2)
		printf(_("Got first crc = %08x, wanted %08x\n"),
			   crc2 << 16 | crc1, m_uid4);
	if ((crc2 << 16 | crc1) != m_uid4)
		{
		printf(_("Got bad crc.\n"));
		return SIS_CORRUPTED;
		}
	m_crc = read16(start + 16);
	m_nlangs = read16(start + 18);
	if (logLevel >= 2)
		printf(_("Got %d languages\n"), m_nlangs);
	m_nfiles = read16(start + 20);
	if (logLevel >= 2)
		printf(_("Got %d files\n"), m_nfiles);
	m_nreqs = read16(start + 22);
	if (logLevel >= 2)
		printf(_("Got %d reqs\n"), m_nreqs);
	m_installationLanguage = read16(start + 24);
	if (logLevel >= 2)
		printf(_("Selected language is %d\n"), m_installationLanguage);
	m_installationFiles = read16(start + OFF_NUMBER_OF_FILES);
	if (logLevel >= 2)
		printf(_("Installed files: %d / %d\n"), m_installationFiles, m_nfiles);
	m_installationDrive = read32(start + OFF_INSTALLATION_DRIVE);
	if (logLevel >= 2)
		printf(_("Installed on drive %c\n"), m_installationDrive);
	m_installerVersion = read32(start + 32);
	if (logLevel >= 2)
		printf(_("Got installer version: %08x\n"), m_installerVersion);
	m_options = read16(start + 36);
	if (logLevel >= 2)
		printf(_("Got options: %04x\n"), m_options);
	m_type = read16(start + 38);
	if (logLevel >= 2)
		printf(_("Got type: %04x\n"), m_type);
	m_major = read16(start + 40);
	if (logLevel >= 2)
		printf(_("Got major: %d\n"), m_major);
	m_minor = read16(start + 42);
	if (logLevel >= 2)
		printf(_("Got minor: %d\n"), m_minor);
	m_variant = read32(start + 44);
	if (logLevel >= 2)
		printf(_("Got variant: %d\n"), m_variant);
	m_languagePtr = read32(start + 48);
	if (logLevel >= 2)
		printf(_("Languages begin at %d\n"), m_languagePtr);
//	if (m_languagePtr >= len)
//		return SIS_TRUNCATED;
	m_filesPtr = read32(start + 52);
	if (logLevel >= 2)
		printf(_("Files begin at %d\n"), m_filesPtr);
//	if (m_filesPtr >= len)
//		return SIS_TRUNCATED;
	m_reqPtr = read32(start + 56);
	if (logLevel >= 2)
		printf(_("Requisites begin at %d\n"), m_reqPtr);
//	if (m_reqPtr >= len)
//		return SIS_TRUNCATED;
	m_unknown = read32(start + 60);
	m_componentPtr = read32(start + 64);
	if (logLevel >= 2)
		printf(_("Components begin at %d\n"), m_componentPtr);
//	if (m_componentPtr >= len)
//		return SIS_TRUNCATED;
	*base += 68;
	return SIS_OK;
}

void
SISFileHeader::setDrive(char drive)
{
	m_installationDrive = drive;
	m_buf[OFF_INSTALLATION_DRIVE] = drive;
	m_buf[OFF_INSTALLATION_DRIVE + 1] =
		m_buf[OFF_INSTALLATION_DRIVE + 2] =
		m_buf[OFF_INSTALLATION_DRIVE + 3] = 0;
}

void
SISFileHeader::setFiles(int nFiles)
{
	m_installationFiles = nFiles;
	write16(m_buf + OFF_NUMBER_OF_FILES, nFiles);
}