/**
 * @file   oleparser.c
 * @author Alex Ott <ott@jet.msk.su>
 * @date   02 Июн 2003
 * Version: $Id: oleparser.c,v 1.1 2003/06/05 12:41:23 ott Exp $
 * 
 * @brief  parser of ole-streams. Used to find specific streams in ole
 * container. 
 * 
 * 
 */

#include <stdio.h>
#include <string.h>
#include "ole.h"
#include "catdoc.h"

/** 
 * Init oleObject structure
 * 
 * @param name 
 * @param type 
 * @param childNum 
 * @param length 
 * @param offset 
 * 
 * @return 
 */
oleObject* initOleObject(char *name, oleType type,
						 int childNum, long offset, long length) {
	oleObject* obs;
	obs = (oleObject*)malloc(sizeof(oleObject));
	if (obs == NULL){
		perror("Can't allocate memory");
		return NULL;
	}
	obs->name=strdup(name);
	obs->type=type;
	obs->childNum=childNum;
	obs->length=length;
	obs->offset=offset;
	obs->objects=NULL;
	return obs;
}

int getshort(char *rec,int offset) {
	return (signed short int) (*((unsigned char *)(rec+offset))|
			((*((unsigned char *)(rec+offset+1)))<<8));
}	      

int getint(char *rec,int offset) {
	return (signed int) (*((unsigned char *)(rec+offset)) |
			((*((unsigned char *)(rec+offset+1)))<<8) |
			((*((unsigned char *)(rec+offset+2)))<<16) |
			((*((unsigned char *)(rec+offset+3)))<<24));
}	      

/** 
 * 
 * 
 * @param f - file to search blocks
 * 
 * @return pointer to root oleObject type objects
 */
oleObject* oleParser(FILE *f) {
	oleObject* obs=NULL;
	unsigned char oleBuf[BBD_BLOCK_SIZE];
	int ret,i;
	int bbdNumBlocks, rootStart, sbdStart,  bbdList;
	static char ole_sign[]={0xD0,0xCF,0x11,0xE0,0xA1,0xB1,0x1A,0xE1,0};
	
	fseek(f,0,SEEK_SET);
	ret=fread(oleBuf,1,0x4c,f);
	if ( ret != 0x4c ) {
		return NULL;
	}
/*	signature = getint(oleBuf,0);
	oleVersion = getint(oleBuf,4);
	fprintf(stderr, "sign=%08x ver=%08x\n", signature, oleVersion);*/
	if (strncmp(oleBuf,ole_sign,8) != 0) {
		return NULL;
	}
	bbdNumBlocks = getint(oleBuf,0x2c);
	rootStart = getint(oleBuf,0x30);
	sbdStart = getint(oleBuf,0x3c);
/* 	fprintf(stderr, "bbdNumBlocks=%d rootStart=%d sbdStart=%d\n", */
/* 			bbdNumBlocks, rootStart, sbdStart); */

	for(i=0; i < bbdNumBlocks ; i++) {
		long old_pos;
		int block_pos,j,k;
		
		ret=fread(oleBuf,1,4,f);
		block_pos=getint(oleBuf,0);
		fprintf(stderr, "%d=%d\n",i,block_pos);
/* 		old_pos=ftell(f); */
/* 		fseek(f,BBD_BLOCK_SIZE*(block_pos+1),SEEK_SET); */
/* 		ret=fread(oleBuf,1,BBD_BLOCK_SIZE,f); */
/* 		for(j=0;j<BBD_BLOCK_SIZE/16; j++) { */
/* 			for(k=0; k<16; k++) */
/* 				fprintf(stderr, "%02x ",(unsigned char)oleBuf[j*16+k]); */
/* 			fprintf(stderr, "\n"); */
/* 		} */
/* 		fseek(f,old_pos,SEEK_SET); */
	}
	fseek(f,BBD_BLOCK_SIZE*(rootStart+1),SEEK_SET);
	while(1) {
		char name[33];
		ret=fread(oleBuf,1,128,f);
		if(ret != 128)
			break;
/* 		fprintf(stderr, "type=%d\n",(char)oleBuf[0x42]); */
/* 		fprintf(stderr, "size=%d startSect=%d\n",getint(oleBuf,0x78),getint(oleBuf,0x74)); */
/* 		fprintf(stderr, "name size=%d\n",getshort(oleBuf,0x40)); */
/* Преобразовать функциями catdoc */		
/* 		for(i=0; i< getshort(oleBuf,0x40)/2; i++) { */
/* 			char c=(char)oleBuf[2*i]; */
/* 			name[i]=c; */
/* 		} */
/* 		name[i]='\0'; */
/* 		fprintf(stderr, "Name=%s\n",name); */
	}
	
//	fprintf(stderr, "%ld\n", ftell(f));
	obs=initOleObject("/",oleUnknown,0,BBD_BLOCK_SIZE*(rootStart+1),0);
	return obs;
}

void freeOleObjects(oleObject *obs) {
	if (obs != NULL) {
		int i;
		for(i=0; i < obs->childNum ; i++)
			if ((obs->objects)[i] != NULL)
				freeOleObjects((obs->objects)[i]);
		if(obs->objects != NULL )
			free(obs->objects);
		if(obs->name != NULL )
			free(obs->name);
		free(obs);
	}
}
