// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "../../include/javascript/JavaScript.h"
#include "../../include/javascript/IJavaScript.h"
#include "../../include/javascript/JS_GlobalData.h"

#define JS_MAXGLOBALDATA			(1024 * 4 - 8)

/* --------------------- CJS_GlobalVariableArray --------------------- */

CJS_GlobalVariableArray::CJS_GlobalVariableArray()
{
}

CJS_GlobalVariableArray::~CJS_GlobalVariableArray()
{
	Empty();
}

void CJS_GlobalVariableArray::Copy(const CJS_GlobalVariableArray& array)
{
	Empty();
	for (int i=0,sz=array.Count(); i<sz; i++)
	{
		CJS_KeyValue* pOldObjData = array.GetAt(i);
		ASSERT(pOldObjData != NULL);

		switch (pOldObjData->nType)
		{
		case JS_GLOBALDATA_TYPE_NUMBER:
			{
				CJS_KeyValue* pNewObjData = new CJS_KeyValue;
				pNewObjData->sKey = pOldObjData->sKey;
				pNewObjData->nType = pOldObjData->nType;
				pNewObjData->dData = pOldObjData->dData;
				Add(pNewObjData);
			}
			break;
		case JS_GLOBALDATA_TYPE_BOOLEAN:
			{
				CJS_KeyValue* pNewObjData = new CJS_KeyValue;
				pNewObjData->sKey = pOldObjData->sKey;
				pNewObjData->nType = pOldObjData->nType;
				pNewObjData->bData = pOldObjData->bData;
				Add(pNewObjData);
			}
			break;
		case JS_GLOBALDATA_TYPE_STRING:
			{
				CJS_KeyValue* pNewObjData = new CJS_KeyValue;
				pNewObjData->sKey = pOldObjData->sKey;
				pNewObjData->nType = pOldObjData->nType;
				pNewObjData->sData = pOldObjData->sData;
				Add(pNewObjData);
			}
			break;
		case JS_GLOBALDATA_TYPE_OBJECT:
			{
				CJS_KeyValue* pNewObjData = new CJS_KeyValue;
				pNewObjData->sKey = pOldObjData->sKey;
				pNewObjData->nType = pOldObjData->nType;
				pNewObjData->objData.Copy(pOldObjData->objData);
				Add(pNewObjData);
			}
		case JS_GLOBALDATA_TYPE_NULL:
			{
				CJS_KeyValue* pNewObjData = new CJS_KeyValue;
				pNewObjData->sKey = pOldObjData->sKey;
				pNewObjData->nType = pOldObjData->nType;
				Add(pNewObjData);
			}
		}
	}
}

void CJS_GlobalVariableArray::Add(CJS_KeyValue* p)
{
	array.Add(p);
}

int CJS_GlobalVariableArray::Count() const
{
	return array.GetSize();
}

CJS_KeyValue* CJS_GlobalVariableArray::GetAt(int index) const
{
	return array.GetAt(index);
}

void CJS_GlobalVariableArray::Empty()
{
	for (int i=0,sz=array.GetSize(); i<sz; i++)
		delete array.GetAt(i);
	array.RemoveAll();
}

/* -------------------------- CJS_GlobalData -------------------------- */

#define READER_JS_GLOBALDATA_FILENAME				L"Reader_JsGlobal.Data"
#define PHANTOM_JS_GLOBALDATA_FILENAME				L"Phantom_JsGlobal.Data"
#define SDK_JS_GLOBALDATA_FILENAME					L"SDK_JsGlobal.Data"

static const uint8_t JS_RC4KEY[] = {0x19,0xa8,0xe8,0x01,0xf6,0xa8,0xb6,0x4d,0x82,0x04,
							0x45,0x6d,0xb4,0xcf,0xd7,0x77,0x67,0xf9,0x75,0x9f,
							0xf0,0xe0,0x1e,0x51,0xee,0x46,0xfd,0x0b,0xc9,0x93,
							0x25,0x55,0x4a,0xee,0xe0,0x16,0xd0,0xdf,0x8c,0xfa,
							0x2a,0xa9,0x49,0xfd,0x97,0x1c,0x0e,0x22,0x13,0x28,
							0x7c,0xaf,0xc4,0xfc,0x9c,0x12,0x65,0x8c,0x4e,0x5b,
							0x04,0x75,0x89,0xc9,0xb1,0xed,0x50,0xca,0x96,0x6f,
							0x1a,0x7a,0xfe,0x58,0x5d,0xec,0x19,0x4a,0xf6,0x35,
							0x6a,0x97,0x14,0x00,0x0e,0xd0,0x6b,0xbb,0xd5,0x75,
							0x55,0x8b,0x6e,0x6b,0x19,0xa0,0xf8,0x77,0xd5,0xa3
							};

CJS_GlobalData::CJS_GlobalData(CPDFDoc_Environment* pApp) : m_pApp(pApp)
{
// 	IBaseAnnot* pBaseAnnot = IBaseAnnot::GetBaseAnnot(m_pApp);
// 	ASSERT(pBaseAnnot != NULL);
//
// 	m_sFilePath = pBaseAnnot->GetUserPath();
	m_sFilePath += SDK_JS_GLOBALDATA_FILENAME;

	LoadGlobalPersistentVariables();
}

CJS_GlobalData::~CJS_GlobalData()
{
	SaveGlobalPersisitentVariables();

	for (int i=0,sz=m_arrayGlobalData.GetSize(); i<sz; i++)
		delete m_arrayGlobalData.GetAt(i);

	m_arrayGlobalData.RemoveAll();
}

int	CJS_GlobalData::FindGlobalVariable(const FX_CHAR* propname)
{
	ASSERT(propname != NULL);

	int nRet = -1;

	for (int i=0,sz=m_arrayGlobalData.GetSize(); i<sz; i++)
	{
		CJS_GlobalData_Element* pTemp = m_arrayGlobalData.GetAt(i);
		if (pTemp->data.sKey[0] == *propname && pTemp->data.sKey == propname)
		{
			nRet = i;
			break;
		}
	}

	return nRet;
}

CJS_GlobalData_Element* CJS_GlobalData::GetGlobalVariable(const FX_CHAR* propname)
{
	ASSERT(propname != NULL);

	int	nFind = FindGlobalVariable(propname);

	if (nFind >= 0)
		return m_arrayGlobalData.GetAt(nFind);
	else
		return NULL;
}

void CJS_GlobalData::SetGlobalVariableNumber(const FX_CHAR* propname, double dData)
{
	ASSERT(propname != NULL);
	CFX_ByteString sPropName = propname;

	sPropName.TrimLeft();
	sPropName.TrimRight();

	if (sPropName.GetLength() == 0) return;

	if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName))
	{
		pData->data.nType = JS_GLOBALDATA_TYPE_NUMBER;
		pData->data.dData = dData;
	}
	else
	{
		CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element;
		pNewData->data.sKey = sPropName;
		pNewData->data.nType = JS_GLOBALDATA_TYPE_NUMBER;
		pNewData->data.dData = dData;

		m_arrayGlobalData.Add(pNewData);
	}
}

void CJS_GlobalData::SetGlobalVariableBoolean(const FX_CHAR* propname, bool bData)
{
	ASSERT(propname != NULL);
	CFX_ByteString sPropName = propname;

	sPropName.TrimLeft();
	sPropName.TrimRight();

	if (sPropName.GetLength() == 0) return;

	if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName))
	{
		pData->data.nType = JS_GLOBALDATA_TYPE_BOOLEAN;
		pData->data.bData = bData;
	}
	else
	{
		CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element;
		pNewData->data.sKey = sPropName;
		pNewData->data.nType = JS_GLOBALDATA_TYPE_BOOLEAN;
		pNewData->data.bData = bData;

		m_arrayGlobalData.Add(pNewData);
	}
}

void CJS_GlobalData::SetGlobalVariableString(const FX_CHAR* propname, const CFX_ByteString& sData)
{
	ASSERT(propname != NULL);
	CFX_ByteString sPropName = propname;

	sPropName.TrimLeft();
	sPropName.TrimRight();

	if (sPropName.GetLength() == 0) return;

	if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName))
	{
		pData->data.nType = JS_GLOBALDATA_TYPE_STRING;
		pData->data.sData = sData;
	}
	else
	{
		CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element;
		pNewData->data.sKey = sPropName;
		pNewData->data.nType = JS_GLOBALDATA_TYPE_STRING;
		pNewData->data.sData = sData;

		m_arrayGlobalData.Add(pNewData);
	}
}

void CJS_GlobalData::SetGlobalVariableObject(const FX_CHAR* propname, const CJS_GlobalVariableArray& array)
{
	ASSERT(propname != NULL);
	CFX_ByteString sPropName = propname;

	sPropName.TrimLeft();
	sPropName.TrimRight();

	if (sPropName.GetLength() == 0) return;

	if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName))
	{
		pData->data.nType = JS_GLOBALDATA_TYPE_OBJECT;
		pData->data.objData.Copy(array);
	}
	else
	{
		CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element;
		pNewData->data.sKey = sPropName;
		pNewData->data.nType = JS_GLOBALDATA_TYPE_OBJECT;
		pNewData->data.objData.Copy(array);

		m_arrayGlobalData.Add(pNewData);
	}
}

void CJS_GlobalData::SetGlobalVariableNull(const FX_CHAR* propname)
{
	ASSERT(propname != NULL);
	CFX_ByteString sPropName = propname;

	sPropName.TrimLeft();
	sPropName.TrimRight();

	if (sPropName.GetLength() == 0) return;

	if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName))
	{
		pData->data.nType = JS_GLOBALDATA_TYPE_NULL;
	}
	else
	{
		CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element;
		pNewData->data.sKey = sPropName;
		pNewData->data.nType = JS_GLOBALDATA_TYPE_NULL;

		m_arrayGlobalData.Add(pNewData);
	}
}

FX_BOOL CJS_GlobalData::SetGlobalVariablePersistent(const FX_CHAR* propname, FX_BOOL bPersistent)
{
	ASSERT(propname != NULL);
	CFX_ByteString sPropName = propname;

	sPropName.TrimLeft();
	sPropName.TrimRight();

	if (sPropName.GetLength() == 0) return FALSE;

	if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName))
	{
		pData->bPersistent = bPersistent;
		return TRUE;
	}

	return FALSE;
}

FX_BOOL CJS_GlobalData::DeleteGlobalVariable(const FX_CHAR* propname)
{
	ASSERT(propname != NULL);
	CFX_ByteString sPropName = propname;

	sPropName.TrimLeft();
	sPropName.TrimRight();

	if (sPropName.GetLength() == 0) return FALSE;

	int	nFind = FindGlobalVariable(sPropName);

	if (nFind >= 0)
	{
		delete m_arrayGlobalData.GetAt(nFind);
		m_arrayGlobalData.RemoveAt(nFind);
		return TRUE;
	}

	return FALSE;
}

int32_t CJS_GlobalData::GetSize() const
{
	return m_arrayGlobalData.GetSize();
}

CJS_GlobalData_Element* CJS_GlobalData::GetAt(int index) const
{
	return m_arrayGlobalData.GetAt(index);
}

void CJS_GlobalData::LoadGlobalPersistentVariables()
{
	uint8_t* pBuffer = NULL;
	int32_t nLength = 0;

	LoadFileBuffer(m_sFilePath.c_str(), pBuffer, nLength);
	CRYPT_ArcFourCryptBlock(pBuffer, nLength, JS_RC4KEY, sizeof(JS_RC4KEY));

	if (pBuffer)
	{
		uint8_t* p = pBuffer;
		FX_WORD wType = *((FX_WORD*)p);
		p += sizeof(FX_WORD);

		//FX_WORD wTemp = (FX_WORD)(('X' << 8) | 'F');

		if (wType == (FX_WORD)(('X' << 8) | 'F'))
		{
			FX_WORD wVersion = *((FX_WORD*)p);
			p += sizeof(FX_WORD);

			ASSERT(wVersion <= 2);

			FX_DWORD dwCount = *((FX_DWORD*)p);
			p += sizeof(FX_DWORD);

			FX_DWORD dwSize = *((FX_DWORD*)p);
			p += sizeof(FX_DWORD);

			if (dwSize == nLength - sizeof(FX_WORD) * 2 - sizeof(FX_DWORD)* 2)
			{
				for (int32_t i=0,sz=dwCount; i<sz; i++)
				{
					if (p > pBuffer + nLength)
						break;

					FX_DWORD dwNameLen = *((FX_DWORD*)p);
					p += sizeof(FX_DWORD);

					if (p + dwNameLen > pBuffer + nLength)
						break;

					CFX_ByteString sEntry = CFX_ByteString(p, dwNameLen);
					p += sizeof(char) * dwNameLen;

					FX_WORD wDataType = *((FX_WORD*)p);
					p += sizeof(FX_WORD);

					switch (wDataType)
					{
					case JS_GLOBALDATA_TYPE_NUMBER:
						{
							double dData = 0;
							switch (wVersion)
							{
							case 1:
								{
									FX_DWORD dwData = *((FX_DWORD*)p);
									p += sizeof(FX_DWORD);
									dData = dwData;
								}
								break;
							case 2:
								{
									dData = *((double*)p);
									p += sizeof(double);
								}
								break;
							}
							SetGlobalVariableNumber(sEntry, dData);
							SetGlobalVariablePersistent(sEntry, TRUE);
						}
						break;
					case JS_GLOBALDATA_TYPE_BOOLEAN:
						{
							FX_WORD wData = *((FX_WORD*)p);
							p += sizeof(FX_WORD);
							SetGlobalVariableBoolean(sEntry, (bool)(wData == 1));
							SetGlobalVariablePersistent(sEntry, TRUE);
						}
						break;
					case JS_GLOBALDATA_TYPE_STRING:
						{
							FX_DWORD dwLength = *((FX_DWORD*)p);
							p += sizeof(FX_DWORD);

							if (p + dwLength > pBuffer + nLength)
								break;

							SetGlobalVariableString(sEntry, CFX_ByteString(p, dwLength));
							SetGlobalVariablePersistent(sEntry, TRUE);
							p += sizeof(char) * dwLength;
						}
						break;
					case JS_GLOBALDATA_TYPE_NULL:
						{
							SetGlobalVariableNull(sEntry);
							SetGlobalVariablePersistent(sEntry, TRUE);
						}
					}
				}
			}
		}
		FX_Free(pBuffer);
	}
}

/*
struct js_global_datafile_header
{
	FX_WORD type; //FX ('X' << 8) | 'F'
	FX_WORD version; //1.0
	FX_DWORD datacount;
};
struct js_global_datafile_data
{
	FX_WORD type;
	FX_DWORD nData;
	FX_WORD bData;
	FX_DWORD nStrLen;
	char* pStr;
};
*/

void CJS_GlobalData::SaveGlobalPersisitentVariables()
{
	FX_DWORD nCount = 0;
	CFX_BinaryBuf sData;

	for (int i=0,sz=m_arrayGlobalData.GetSize(); i<sz; i++)
	{
		CJS_GlobalData_Element* pElement = m_arrayGlobalData.GetAt(i);
		ASSERT(pElement != NULL);

		if (pElement->bPersistent)
		{
			CFX_BinaryBuf sElement;
			MakeByteString(pElement->data.sKey, &pElement->data, sElement);

			if (sData.GetSize() + sElement.GetSize() > JS_MAXGLOBALDATA)
				break;

			sData.AppendBlock(sElement.GetBuffer(), sElement.GetSize());
			nCount++;
		}
	}

	CFX_BinaryBuf sFile;

	FX_WORD wType = (FX_WORD)(('X' << 8) | 'F');
	sFile.AppendBlock(&wType, sizeof(FX_WORD));
	FX_WORD wVersion = 2;
	sFile.AppendBlock(&wVersion, sizeof(FX_WORD));
	sFile.AppendBlock(&nCount, sizeof(FX_DWORD));
	FX_DWORD dwSize = sData.GetSize();
	sFile.AppendBlock(&dwSize, sizeof(FX_DWORD));

	sFile.AppendBlock(sData.GetBuffer(), sData.GetSize());

	CRYPT_ArcFourCryptBlock(sFile.GetBuffer(), sFile.GetSize(), JS_RC4KEY, sizeof(JS_RC4KEY));
	WriteFileBuffer(m_sFilePath.c_str(), (const FX_CHAR*)sFile.GetBuffer(), sFile.GetSize());
}

void CJS_GlobalData::LoadFileBuffer(const FX_WCHAR* sFilePath, uint8_t*& pBuffer, int32_t& nLength)
{
//UnSupport.
}

void CJS_GlobalData::WriteFileBuffer(const FX_WCHAR* sFilePath, const FX_CHAR* pBuffer, int32_t nLength)
{
//UnSupport.
}

void CJS_GlobalData::MakeByteString(const CFX_ByteString& name, CJS_KeyValue* pData, CFX_BinaryBuf& sData)
{
	ASSERT(pData != NULL);

	FX_WORD wType = (FX_WORD)pData->nType;

	switch (wType)
	{
	case JS_GLOBALDATA_TYPE_NUMBER:
		{
			FX_DWORD dwNameLen = (FX_DWORD)name.GetLength();
			sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD));
			sData.AppendString(name);

			sData.AppendBlock(&wType, sizeof(FX_WORD));
			double dData = pData->dData;
			sData.AppendBlock(&dData, sizeof(double));
		}
		break;
	case JS_GLOBALDATA_TYPE_BOOLEAN:
		{
			FX_DWORD dwNameLen = (FX_DWORD)name.GetLength();
			sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD));
			sData.AppendString(name);

			sData.AppendBlock(&wType, sizeof(FX_WORD));
			FX_WORD wData = (FX_WORD)pData->bData;
			sData.AppendBlock(&wData, sizeof(FX_WORD));
		}
		break;
	case JS_GLOBALDATA_TYPE_STRING:
		{
			FX_DWORD dwNameLen = (FX_DWORD)name.GetLength();
			sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD));
			sData.AppendString(name);

			sData.AppendBlock(&wType, sizeof(FX_WORD));

			FX_DWORD dwDataLen = (FX_DWORD)pData->sData.GetLength();
			sData.AppendBlock(&dwDataLen, sizeof(FX_DWORD));
			sData.AppendString(pData->sData);
		}
		break;
	case JS_GLOBALDATA_TYPE_NULL:
		{
			FX_DWORD dwNameLen = (FX_DWORD)name.GetLength();
			sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD));
			sData.AppendString(name);

			sData.AppendBlock(&wType, sizeof(FX_DWORD));
		}
		break;
	default:
		break;
	}
}

