/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"


#include <string.h> 	// memset(), ...
#ifndef UNX
#include <io.h> 		// access()
#endif
#include <msvbasic.hxx>

/* class VBA_Impl:
 * The VBA class provides a set of methods to handle Visual Basic For
 * Applications streams, the constructor is given the root ole2 stream
 * of the document, Open reads the VBA project file and figures out
 * the number of VBA streams, and the offset of the data within them.
 * Decompress decompresses a particular numbered stream, NoStreams returns
 * this number, and StreamName can give you the streams name. Decompress
 * will call Output when it has a 4096 byte collection of data to output,
 * and also with the final remainder of data if there is still some left
 * at the end of compression. Output is virtual to allow custom handling
 * of each chunk of decompressed data. So inherit from this to do something
 * useful with the data.
 *
 * cmc
 * */

sal_uInt8 VBA_Impl::ReadPString(SvStorageStreamRef &xVBAProject)
{
	sal_uInt16 idlen;
	sal_uInt8 type=0;
	*xVBAProject >> idlen;
	sal_uInt8 out;
	int i=0;
	if (idlen < 6)
	{
		type=0;
		xVBAProject->SeekRel(-2);
		return(type);
	}

	for(i=0;i<idlen/2;i++)
	{
		*xVBAProject >> out;
		xVBAProject->SeekRel(1);
		if (i==2)
		{
			type=out;
			if ((type != 'G') && (type != 'C'))
				type=0;
			if (type == 0)
			{
				xVBAProject->SeekRel(-8);
				break;
			}
		}
	}


	return(type);
}

void VBA_Impl::ConfirmFixedOctect(SvStorageStreamRef &xVBAProject)
{
	static const sal_uInt8 stest[8] =
		{
		0x06, 0x02, 0x01, 0x00, 0x08, 0x02, 0x00, 0x00
		};

	sal_uInt8 test[8];
	xVBAProject->Read(test,8);
	if (memcmp(stest,test,8) != 0)
		DBG_WARNING("Found a different octect, please report");
}

void VBA_Impl::Confirm12Zeros(SvStorageStreamRef &xVBAProject)
{
	static const sal_uInt8 stest[12]={0};
	sal_uInt8 test[12];
	xVBAProject->Read(test,12);
	if (memcmp(stest,test,12) != 0)
		DBG_WARNING("Found a Non Zero block, please report");
}

void VBA_Impl::ConfirmHalfWayMarker(SvStorageStreamRef &xVBAProject)
{
	static const sal_uInt8 stest[12]={0,0,0,0,0,0,0,0,0,0,1,0};
	sal_uInt8 test[12];
	xVBAProject->Read(test,12);
	if (memcmp(stest,test,12) != 0)
		DBG_WARNING("Found a different halfway marker, please report");
}

void VBA_Impl::ConfirmFixedMiddle(SvStorageStreamRef &xVBAProject)
{
	static const sal_uInt8 stest[20] =
	{
		0x00, 0x00, 0xe1, 0x2e, 0x45, 0x0d, 0x8f, 0xe0,
		0x1a, 0x10, 0x85, 0x2e, 0x02, 0x60, 0x8c, 0x4d,
		0x0b, 0xb4, 0x00, 0x00
	};

	sal_uInt8 test[20];
	xVBAProject->Read(test,20);
	if (memcmp(stest,test,20) != 0)
	{
		DBG_WARNING("Found a different middle marker, please report");
		xVBAProject->SeekRel(-20);
	}
}

void VBA_Impl::ConfirmFixedMiddle2(SvStorageStreamRef &xVBAProject)
{
	static const sal_uInt8 stest[20] =
	{
		0x00, 0x00, 0x2e, 0xc9, 0x27, 0x8e, 0x64, 0x12,
		0x1c, 0x10, 0x8a, 0x2f, 0x04, 0x02, 0x24, 0x00,
		0x9c, 0x02, 0x00, 0x00
	};

	sal_uInt8 test[20];
	xVBAProject->Read(test,20);
	if (memcmp(stest,test,20) != 0)
		{
		DBG_WARNING("Found a different middle2 marker, please report");
		xVBAProject->SeekRel(-20);
		}
}


void VBA_Impl::Output( int nLen, const sal_uInt8 *pData)
{
	sVBAString += String( (const sal_Char *)pData, nLen );
/*
//For debugging purposes
	for(int i=0;i<len;i++)
		*pOut << data[i];
*/
}


int VBA_Impl::ReadVBAProject(const SvStorageRef &rxVBAStorage)
	{
	SvStorageStreamRef xVBAProject;
	xVBAProject = rxVBAStorage->OpenStream(
					String::CreateFromAscii( "_VBA_PROJECT" ),
					STREAM_STD_READ | STREAM_NOCREATE );

	if( !xVBAProject.Is() || SVSTREAM_OK != xVBAProject->GetError() )
	{
		DBG_WARNING("Not able to find vba project, cannot find macros");
		return(0);
	}
	xVBAProject->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );

	//*pOut << hex;
	sal_uInt8 header[30] =
	{
		0xcc, 0x61, 0x5e, 0x00, 0x00, 0x01, 0x00, 0xff,
		0x07, 0x04, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
		0xe4, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x01, 0x00
	};
	sal_uInt8 headerin[30];

	xVBAProject->Read(headerin,30);
	if (memcmp(header,headerin,30) != 0)
		DBG_WARNING("Warning VBA header is different, please report");
	sal_uInt16 value;
	*xVBAProject >> value;
	//*pOut << "Trigger value 1 is " << value << endl;
	sal_uInt16 svalue;
	*xVBAProject >> svalue;
	if (svalue != 0x02)
		DBG_WARNING("Warning VBA number is different, please report");

	int count=0;
	sal_uInt8 testc=0;

	//*pOut << "Other strings after the middle are..." << endl;
	//There appears to be almost any number of strings acceptable
	//most begin with */G , and sometimes with
	//*/C. Those with G always have a trailer of 12 bytes, those
	//with C come in pairs, the first with no trailer, and the
	//second with one of 12 bytes. The following code attempts
	//to read these strings and ends when it reaches a sequence of
	//bytes which fails a test to be a valid string. So this
	//while loop here is the particular piece of code which is
	//very suspect and likely to be the cause of any crashes and
	//problems.
	while ((testc = ReadPString(xVBAProject)) != 0)
	{
		//*pOut << endl;
		//*pOut << "testcharacter is " << testc << endl;
		switch (testc)
		{
			case 'C':
				count++;
				if (count == 2)
				{
					Confirm12Zeros(xVBAProject);
					count=0;
				}
				break;
			default:
			case 'G':
				Confirm12Zeros(xVBAProject);
				break;
		}
	}

	//appears to be a fixed 20 byte sequence here, and then the strings
	//continue
	ConfirmFixedMiddle(xVBAProject);

	count=0;
	testc=0;

	while ((testc = ReadPString(xVBAProject)) != 0)
	{
		//*pOut << endl;
		//*pOut << "testcharacter is " << testc << endl;
		switch (testc)
		{
			case 'C':
				count++;
				if (count == 2)
				{
					Confirm12Zeros(xVBAProject);
					count=0;
				}
				break;
			default:
			case 'G':
				Confirm12Zeros(xVBAProject);
				break;
		}
	}

	//there *may* be another different 20byte fixed string
	ConfirmFixedMiddle2(xVBAProject);

	//*pOut << "testc is " << testc << endl;
	//*pOut << "position is " << xVBAProject->Tell() << endl;

	sal_uInt16 nModules;
	*xVBAProject >> nModules;

	//begin section, this section isn't really 100% correct
	//*pOut << nModules << hex << " vba modules" << endl;
	xVBAProject->SeekRel(2*nModules);
	xVBAProject->SeekRel(4);
	//*pOut << "position is " << xVBAProject->Tell() << endl;
	ConfirmFixedOctect(xVBAProject);

	sal_uInt16 junksize;
	while(junksize != 0xFFFF)
	{
		xVBAProject->Read(&junksize,2); // usually 18 02, sometimes 1e 02
		//but sometimes its a run of numbers until 0xffff, gagh!!!
		//*pOut << "position is " << xVBAProject->Tell() << "len is "
		//	<< junksize << endl;
	}

	sal_uInt16 ftest;
	*xVBAProject >> ftest;
	if (ftest != 0xFFFF)
		xVBAProject->SeekRel(ftest);
	*xVBAProject >> ftest;
	if (ftest != 0xFFFF)
		xVBAProject->SeekRel(ftest);

	xVBAProject->SeekRel(100);
	//*pOut << "position is " << xVBAProject->Tell() << endl;
	//end section


	*xVBAProject >> nOffsets;
	pOffsets = new VBAOffset_Impl[nOffsets];
	int i;
	for (i=0;i<nOffsets;i++)
		{
		sal_uInt8 discard;
		sal_uInt16 len;
		*xVBAProject >> len;
		int j;
		for (j=0;j<len/2;j++)
			{
			*xVBAProject >> discard;
			pOffsets[i].sName += discard;
			*xVBAProject >> discard;
			}
		*xVBAProject >> len;
		xVBAProject->SeekRel(len);

		//begin section, another problem area
		*xVBAProject >> len;
		if (len == 0xFFFF)
		{
			xVBAProject->SeekRel(2);
			*xVBAProject >> len;
			xVBAProject->SeekRel(len);
		}
		else
			xVBAProject->SeekRel(len+2);
		//
		/* I have a theory that maybe you read a 16bit len, and
		 * if it has 0x02 for the second byte then it is a special
		 * token of its own that affects nothing else, otherwise
		 * it is a len of the following data. C. I must test this
		 * theory later.
		 */
		//end section

		xVBAProject->SeekRel(8);
		sal_uInt8 no_of_octects;
		*xVBAProject >> no_of_octects;
		for(j=0;j<no_of_octects;j++)
			xVBAProject->SeekRel(8);
		xVBAProject->SeekRel(6);

		*xVBAProject >> pOffsets[i].nOffset;
		//*pOut << pOffsets[i].pName.GetStr() << " at 0x" << hex << pOffsets[i].nOffset << endl;
		xVBAProject->SeekRel(2);
		}

	//*pOut << endl;
	return(nOffsets);
	}

sal_Bool VBA_Impl::Open( const String &rToplevel,const String &rSublevel )
{
	/* beginning test for vba stuff */
	sal_Bool bRet = sal_False;
	SvStorageRef xMacros= xStor->OpenStorage(rToplevel);
	if( !xMacros.Is() || SVSTREAM_OK != xMacros->GetError() )
	{
		DBG_WARNING("No Macros Storage");
	}
	else
	{
		xVBA = xMacros->OpenStorage(rSublevel);
		if( !xVBA.Is() || SVSTREAM_OK != xVBA->GetError() )
		{
			DBG_WARNING("No Visual Basic in Storage");
		}
		else
		{
			if (ReadVBAProject(xVBA))
				bRet = sal_True;
		}
	}
	/* end test for vba stuff */
	return bRet;
}

const String &VBA_Impl::Decompress( sal_uInt16 nIndex, int *pOverflow)
{
	SvStorageStreamRef xVBAStream;
	sVBAString.Erase();

	DBG_ASSERT( nIndex < nOffsets, "Index out of range" );
	xVBAStream = xVBA->OpenStream( pOffsets[nIndex].sName,
						STREAM_STD_READ | STREAM_NOCREATE );
	if (pOverflow)
		*pOverflow=0;
	if( !xVBAStream.Is() || SVSTREAM_OK !=
		xVBAStream->GetError() )
	{
		DBG_WARNING("Not able to open vb module ");
//		DBG_WARNING((pOffsets[nIndex].sName).GetStr());
	}
	else
	{
		xVBAStream->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
		DecompressVBA(nIndex,xVBAStream);
		/*
		 * if len was too big for a single string set that variable ?
		 *	if ((len > XX) && (pOverflow))
				*pOverflow=1;
		 */
		if (bCommented)
		{
			String sTempStringa(String::CreateFromAscii( "\x0D\x0A"));
			String sTempStringb(String::CreateFromAscii( "\x0D\x0ARem "));
			sVBAString.SearchAndReplaceAll(sTempStringa,sTempStringb);
			sVBAString.InsertAscii("Rem ",0);
		}
	}
	return sVBAString;
}


int VBA_Impl::DecompressVBA( int nIndex, SvStorageStreamRef &xVBAStream )
{
	sal_uInt8 leadbyte;
	unsigned int pos = 0;

	//*pOut << "jumping to " << hex << offsets[nIndex].offset << endl;
	xVBAStream->Seek(pOffsets[nIndex].nOffset+3);

	int len;
	sal_uInt16 token;
	int distance, shift, clean=1;

	while(xVBAStream->Read(&leadbyte,1))
		{
		//*pOut << "reading 8 data unit block beginning with " << leadbyte << int(leadbyte) << " at pos " << xVBAStream->Tell() << " real pos " << pos << endl;
		for(int position=0x01;position < 0x100;position=position<<1)
			{
			//we see if the leadbyte has flagged this location as a dataunit
			//which is actually a token which must be looked up in the history
			if (leadbyte & position)
				{
				*xVBAStream >> token;

				if (clean == 0)
					clean=1;

				//For some reason the division of the token into the length
				//field of the data to be inserted, and the distance back into
				//the history differs depending on how full the history is
				int pos2 = pos%WINDOWLEN;
				if (pos2 <= 0x10)
					shift = 12;
				else if (pos2 <= 0x20)
					shift = 11;
				else if (pos2 <= 0x40)
					shift = 10;
				else if (pos2 <= 0x80)
					shift = 9;
				else if (pos2 <= 0x100)
					shift = 8;
				else if (pos2 <= 0x200)
					shift = 7;
				else if (pos2 <= 0x400)
					shift = 6;
				else if (pos2 <= 0x800)
					shift = 5;
				else
					shift = 4;

				int i;
				len=0;
				for(i=0;i<shift;i++)
					len |= token & (1<<i);

				//*pOut << endl << "match lookup token " << int(token) << "len " << int(len) << endl;

				len += 3;
				//*pOut << endl << "len is " << len << "shift is " << shift << endl;

				distance = token >> shift;
				//*pOut << "distance token shift is " << distance << " " << int(token) << " " << shift << "pos is " << pos << " " << xVBAStream->Tell() << endl;

				//read the len of data from the history, wrapping around the
				//WINDOWLEN boundary if necessary
				//data read from the history is also copied into the recent
				//part of the history as well.
				for (i = 0; i < len; i++)
					{
					unsigned char c;
					//*pOut << endl << (pos%WINDOWLEN)-distance-1 << " " << pos << " " << distance << endl;
					c = aHistory[(pos-distance-1)%WINDOWLEN];
					aHistory[pos%WINDOWLEN] = c;
					pos++;
					//*pOut << "real pos is " << pos << endl;
					//
					//temp removed
					//*pOut << c ;
					}
				}
			else
				{
				// special boundary case code, not guarantueed to be correct
				// seems to work though, there is something wrong with the
				// compression scheme (or maybe a feature) where when
				// the data ends on a WINDOWLEN boundary and the excess
				// bytes in the 8 dataunit list are discarded, and not
				// interpreted as tokens or normal data.
				if ((pos != 0) && ((pos%WINDOWLEN) == 0) && (clean))
					{
					//*pOut << "at boundary position is " << position << " " << xVBAStream->Tell() << " pos is " << pos << endl;
					//if (position != 0x01)
					//*pOut << "must restart by eating remainder single byte data units" << endl;
					xVBAStream->SeekRel(2);
					clean=0;
					Output(WINDOWLEN,aHistory);
					break;
					}
				//This is the normal case for when the data unit is not a
				//token to be looked up, but instead some normal data which
				//can be output, and placed in the history.
				if (xVBAStream->Read(&aHistory[pos%WINDOWLEN],1))
				{
					pos++;
					//temp removed
					//*pOut << aHistory[pos++%WINDOWLEN];
				}
				if (clean == 0)
					clean=1;
				//*pOut << "pos is " << pos << " " << xVBAStream->Tell() << endl;
				}
			}
		}
	if (pos%WINDOWLEN)
		Output(pos%WINDOWLEN,aHistory);
	return(pos);
}

