/*
 *   Copyright 1992, 1993, 1994 John Melton (G0ORX/N6LYT)
 *              All Rights Reserved
 *
 *   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#define RCS_ID $Id: header.c,v 1.3 1999/02/26 12:19:24 bent Exp $

/*
	header.c

	Extract an FTL0 header from a file.

	John Melton

	G0ORX, N6LYT

	4 Charlwoods Close
	Copthorne
	West Sussex
	RH10 3QZ
	England

	Note: there may be a better way to do this, rather than having
	fixed field sizes in a structure.
*/

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

#include "ftl0.h"
#include "header.h"

void HeaderCopy(unsigned char *, int, char *, int);
void ConvertTime(unsigned long *);

HEADER *ExtractHeader(unsigned char *buffer, int nBytes, int *size)
{
	int i = 0;
	int bMore = 0;
	unsigned id;
	unsigned char length;
	HEADER  *hdr;

	if ((hdr = (HEADER *)malloc(sizeof(HEADER))) != NULL)
	{
		hdr->fileId             = 0;
		hdr->fileName[0]        = '\0';  
		hdr->fileExt[0]         = '\0';   
		hdr->fileSize           = 0;     
		hdr->createTime         = 0;   
		hdr->modifiedTime       = 0; 
		hdr->SEUflag            = 0;      
		hdr->fileType           = 0;     
		hdr->bodyCRC            = 0;      
		hdr->headerCRC          = 0;    
		hdr->bodyOffset         = 0;   

		hdr->source[0]          = '\0';         
		hdr->uploader[0]        = '\0';        
		hdr->uploadTime         = 0;         
		hdr->downloadCount      = 0;      
		hdr->destination[0]     = '\0';    
		hdr->downloader[0]      = '\0';      
		hdr->downloadTime       = 0;       
		hdr->expireTime         = 0;         
		hdr->priority           = 0;           
		hdr->compression        = 0;        
		hdr->BBSMessageType     = ' ';     
		hdr->BID[0]             = '\0';            
		hdr->title[0]           = '\0';          
		hdr->keyWords[0]        = '\0';       
		hdr->description[0]     = '\0';    
		hdr->compressionDesc[0] = '\0';
		hdr->userFileName[0]    = '\0';   

		if (buffer[0] != 0xAA || buffer[1] != 0x55)
		{
			free((char *)hdr);
			return (HEADER *)0;
		}

		bMore = 1;

		i = 2; /* skip over 0xAA 0x55 */

		while (bMore && i < nBytes)
		{
			id = buffer[i++];
			id += buffer[i++] << 8;
			length = buffer[i++];

#ifdef DEBUG
printf("ExtractHeader: id:%X length:%d\n", id, length);
#endif
			switch (id)
			{
			case 0x00:
				bMore = 0;
				break;
			case 0x01:
				hdr->fileId = *(unsigned long *)&buffer[i];
				break;
			case 0x02:
				HeaderCopy(&buffer[i], length, hdr->fileName, 9);
				break;
			case 0x03:
				HeaderCopy(&buffer[i], length, hdr->fileExt, 3);
				break;
			case 0x04:
				hdr->fileSize = *(unsigned long *)&buffer[i];
				break;
			case 0x05:
				hdr->createTime = *(unsigned long *)&buffer[i];
       				ConvertTime(&hdr->createTime);
				break;
			case 0x06:
				hdr->modifiedTime = *(unsigned long *)&buffer[i];
       				ConvertTime(&hdr->modifiedTime);
				break;
			case 0x07:
				hdr->SEUflag = buffer[i];
				break;
			case 0x08:
				hdr->fileType = buffer[i];
				break;
			case 0x09:
				hdr->bodyCRC = *(unsigned short *)&buffer[i];
				break;
			case 0x0A:
				hdr->headerCRC = *(unsigned short *)&buffer[i];
				break;
			case 0x0B:
				hdr->bodyOffset = *(unsigned short *)&buffer[i];
				break;
			case 0x10:
				HeaderCopy(&buffer[i], length, hdr->source, 32);
				break;
			case 0x11:
				HeaderCopy(&buffer[i], length, hdr->uploader, 6);
				break;
			case 0x12:
				hdr->uploadTime = *(unsigned long *)&buffer[i];
				ConvertTime(&hdr->uploadTime);
				break;
			case 0x13:
				hdr->downloadCount = buffer[i];
				break;
			case 0x14:
				HeaderCopy(&buffer[i], length, hdr->destination, 32);
				break;
			case 0x15:
				HeaderCopy(&buffer[i], length, hdr->downloader, 6);
				break;
			case 0x16:
				hdr->downloadTime = *(unsigned long *)&buffer[i];
				ConvertTime(&hdr->downloadTime);
				break;
			case 0x17:
				hdr->expireTime = *(unsigned long *)&buffer[i];
				ConvertTime(&hdr->expireTime);
				break;
			case 0x18:
				hdr->priority = buffer[i];
				break;
			case 0x19:
				hdr->compression = buffer[i];
				break;
			case 0x20:
				hdr->BBSMessageType = buffer[i];
				break;
			case 0x21:
				HeaderCopy(&buffer[i], length, hdr->BID, 32);
				break;
			case 0x22:
				HeaderCopy(&buffer[i], length, hdr->title, 64);
				break;
			case 0x23:
				HeaderCopy(&buffer[i], length, hdr->keyWords, 32);
				break;
			case 0x24:
				HeaderCopy(&buffer[i], length, hdr->description, 32);
				break;
			case 0x25:
				HeaderCopy(&buffer[i], length, hdr->compressionDesc, 32);
				break;
			case 0x26:
				HeaderCopy(&buffer[i], length, hdr->userFileName, 32);
				break;
			default:
				/*printf("Unknown header item, id:%d length:%d data:%02X %02X %02X %02X\n",
					id, length, buffer[i], buffer[i+1], buffer[i+2], buffer[i+3]);*/
			        break;
			}

			i+=length;
		}
	 }

	/* let the user know the size */
	*size = i;

	/* see if we ran out of space */
	if (bMore)
	{
		free((char *)hdr);
		return NULL;
	}

	return hdr;
}

void HeaderCopy(unsigned char *source, int length, 
		char *destination, int maxbytes)
{
	if (length > maxbytes) length = maxbytes;

	while (length > 0)
	{
		*destination++ = *source++;
		length--;
	}
	
	*destination = '\0';
}

/*
  ConvertTime

  Time is number of seconds since Jan 1 1970
  MicroSoft wants it to be since 1900
*/
void ConvertTime(unsigned long * pTime)
{
	struct tm time70;
  
	/* time is number of seconds since 1970 (MSC wants since 1900) */
	time70.tm_sec   = 0;
	time70.tm_min   = 0;
	time70.tm_hour  = 0;
	time70.tm_mday  = 1;
	time70.tm_mon   = 0;
	time70.tm_year  = 70;
  	time70.tm_wday  = 0;
	time70.tm_yday  = 0;
	time70.tm_isdst = 0;

	*pTime += (unsigned long)mktime(&time70);
}
