Home | History | Annotate | Download | only in javascript
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "../../include/javascript/JavaScript.h"
      8 #include "../../include/javascript/IJavaScript.h"
      9 #include "../../include/javascript/JS_GlobalData.h"
     10 
     11 #define JS_MAXGLOBALDATA			(1024 * 4 - 8)
     12 
     13 /* --------------------- CJS_GlobalVariableArray --------------------- */
     14 
     15 CJS_GlobalVariableArray::CJS_GlobalVariableArray()
     16 {
     17 }
     18 
     19 CJS_GlobalVariableArray::~CJS_GlobalVariableArray()
     20 {
     21 	Empty();
     22 }
     23 
     24 void CJS_GlobalVariableArray::Copy(const CJS_GlobalVariableArray& array)
     25 {
     26 	Empty();
     27 	for (int i=0,sz=array.Count(); i<sz; i++)
     28 	{
     29 		CJS_KeyValue* pOldObjData = array.GetAt(i);
     30 		ASSERT(pOldObjData != NULL);
     31 
     32 		switch (pOldObjData->nType)
     33 		{
     34 		case JS_GLOBALDATA_TYPE_NUMBER:
     35 			{
     36 				CJS_KeyValue* pNewObjData = new CJS_KeyValue;
     37 				pNewObjData->sKey = pOldObjData->sKey;
     38 				pNewObjData->nType = pOldObjData->nType;
     39 				pNewObjData->dData = pOldObjData->dData;
     40 				Add(pNewObjData);
     41 			}
     42 			break;
     43 		case JS_GLOBALDATA_TYPE_BOOLEAN:
     44 			{
     45 				CJS_KeyValue* pNewObjData = new CJS_KeyValue;
     46 				pNewObjData->sKey = pOldObjData->sKey;
     47 				pNewObjData->nType = pOldObjData->nType;
     48 				pNewObjData->bData = pOldObjData->bData;
     49 				Add(pNewObjData);
     50 			}
     51 			break;
     52 		case JS_GLOBALDATA_TYPE_STRING:
     53 			{
     54 				CJS_KeyValue* pNewObjData = new CJS_KeyValue;
     55 				pNewObjData->sKey = pOldObjData->sKey;
     56 				pNewObjData->nType = pOldObjData->nType;
     57 				pNewObjData->sData = pOldObjData->sData;
     58 				Add(pNewObjData);
     59 			}
     60 			break;
     61 		case JS_GLOBALDATA_TYPE_OBJECT:
     62 			{
     63 				CJS_KeyValue* pNewObjData = new CJS_KeyValue;
     64 				pNewObjData->sKey = pOldObjData->sKey;
     65 				pNewObjData->nType = pOldObjData->nType;
     66 				pNewObjData->objData.Copy(pOldObjData->objData);
     67 				Add(pNewObjData);
     68 			}
     69 		case JS_GLOBALDATA_TYPE_NULL:
     70 			{
     71 				CJS_KeyValue* pNewObjData = new CJS_KeyValue;
     72 				pNewObjData->sKey = pOldObjData->sKey;
     73 				pNewObjData->nType = pOldObjData->nType;
     74 				Add(pNewObjData);
     75 			}
     76 		}
     77 	}
     78 }
     79 
     80 void CJS_GlobalVariableArray::Add(CJS_KeyValue* p)
     81 {
     82 	array.Add(p);
     83 }
     84 
     85 int CJS_GlobalVariableArray::Count() const
     86 {
     87 	return array.GetSize();
     88 }
     89 
     90 CJS_KeyValue* CJS_GlobalVariableArray::GetAt(int index) const
     91 {
     92 	return array.GetAt(index);
     93 }
     94 
     95 void CJS_GlobalVariableArray::Empty()
     96 {
     97 	for (int i=0,sz=array.GetSize(); i<sz; i++)
     98 		delete array.GetAt(i);
     99 	array.RemoveAll();
    100 }
    101 
    102 /* -------------------------- CJS_GlobalData -------------------------- */
    103 
    104 #define READER_JS_GLOBALDATA_FILENAME				L"Reader_JsGlobal.Data"
    105 #define PHANTOM_JS_GLOBALDATA_FILENAME				L"Phantom_JsGlobal.Data"
    106 #define SDK_JS_GLOBALDATA_FILENAME					L"SDK_JsGlobal.Data"
    107 
    108 static const FX_BYTE JS_RC4KEY[] = {0x19,0xa8,0xe8,0x01,0xf6,0xa8,0xb6,0x4d,0x82,0x04,
    109 							0x45,0x6d,0xb4,0xcf,0xd7,0x77,0x67,0xf9,0x75,0x9f,
    110 							0xf0,0xe0,0x1e,0x51,0xee,0x46,0xfd,0x0b,0xc9,0x93,
    111 							0x25,0x55,0x4a,0xee,0xe0,0x16,0xd0,0xdf,0x8c,0xfa,
    112 							0x2a,0xa9,0x49,0xfd,0x97,0x1c,0x0e,0x22,0x13,0x28,
    113 							0x7c,0xaf,0xc4,0xfc,0x9c,0x12,0x65,0x8c,0x4e,0x5b,
    114 							0x04,0x75,0x89,0xc9,0xb1,0xed,0x50,0xca,0x96,0x6f,
    115 							0x1a,0x7a,0xfe,0x58,0x5d,0xec,0x19,0x4a,0xf6,0x35,
    116 							0x6a,0x97,0x14,0x00,0x0e,0xd0,0x6b,0xbb,0xd5,0x75,
    117 							0x55,0x8b,0x6e,0x6b,0x19,0xa0,0xf8,0x77,0xd5,0xa3
    118 							};
    119 
    120 CJS_GlobalData::CJS_GlobalData(CPDFDoc_Environment* pApp) : m_pApp(pApp)
    121 {
    122 // 	IBaseAnnot* pBaseAnnot = IBaseAnnot::GetBaseAnnot(m_pApp);
    123 // 	ASSERT(pBaseAnnot != NULL);
    124 //
    125 // 	m_sFilePath = pBaseAnnot->GetUserPath();
    126 	m_sFilePath += SDK_JS_GLOBALDATA_FILENAME;
    127 
    128 	LoadGlobalPersistentVariables();
    129 }
    130 
    131 CJS_GlobalData::~CJS_GlobalData()
    132 {
    133 	SaveGlobalPersisitentVariables();
    134 
    135 	for (int i=0,sz=m_arrayGlobalData.GetSize(); i<sz; i++)
    136 		delete m_arrayGlobalData.GetAt(i);
    137 
    138 	m_arrayGlobalData.RemoveAll();
    139 }
    140 
    141 int	CJS_GlobalData::FindGlobalVariable(FX_LPCSTR propname)
    142 {
    143 	ASSERT(propname != NULL);
    144 
    145 	int nRet = -1;
    146 
    147 	for (int i=0,sz=m_arrayGlobalData.GetSize(); i<sz; i++)
    148 	{
    149 		CJS_GlobalData_Element* pTemp = m_arrayGlobalData.GetAt(i);
    150 		if (pTemp->data.sKey[0] == *propname && pTemp->data.sKey == propname)
    151 		{
    152 			nRet = i;
    153 			break;
    154 		}
    155 	}
    156 
    157 	return nRet;
    158 }
    159 
    160 CJS_GlobalData_Element* CJS_GlobalData::GetGlobalVariable(FX_LPCSTR propname)
    161 {
    162 	ASSERT(propname != NULL);
    163 
    164 	int	nFind = FindGlobalVariable(propname);
    165 
    166 	if (nFind >= 0)
    167 		return m_arrayGlobalData.GetAt(nFind);
    168 	else
    169 		return NULL;
    170 }
    171 
    172 void CJS_GlobalData::SetGlobalVariableNumber(FX_LPCSTR propname, double dData)
    173 {
    174 	ASSERT(propname != NULL);
    175 	CFX_ByteString sPropName = propname;
    176 
    177 	sPropName.TrimLeft();
    178 	sPropName.TrimRight();
    179 
    180 	if (sPropName.GetLength() == 0) return;
    181 
    182 	if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName))
    183 	{
    184 		pData->data.nType = JS_GLOBALDATA_TYPE_NUMBER;
    185 		pData->data.dData = dData;
    186 	}
    187 	else
    188 	{
    189 		CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element;
    190 		pNewData->data.sKey = sPropName;
    191 		pNewData->data.nType = JS_GLOBALDATA_TYPE_NUMBER;
    192 		pNewData->data.dData = dData;
    193 
    194 		m_arrayGlobalData.Add(pNewData);
    195 	}
    196 }
    197 
    198 void CJS_GlobalData::SetGlobalVariableBoolean(FX_LPCSTR propname, bool bData)
    199 {
    200 	ASSERT(propname != NULL);
    201 	CFX_ByteString sPropName = propname;
    202 
    203 	sPropName.TrimLeft();
    204 	sPropName.TrimRight();
    205 
    206 	if (sPropName.GetLength() == 0) return;
    207 
    208 	if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName))
    209 	{
    210 		pData->data.nType = JS_GLOBALDATA_TYPE_BOOLEAN;
    211 		pData->data.bData = bData;
    212 	}
    213 	else
    214 	{
    215 		CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element;
    216 		pNewData->data.sKey = sPropName;
    217 		pNewData->data.nType = JS_GLOBALDATA_TYPE_BOOLEAN;
    218 		pNewData->data.bData = bData;
    219 
    220 		m_arrayGlobalData.Add(pNewData);
    221 	}
    222 }
    223 
    224 void CJS_GlobalData::SetGlobalVariableString(FX_LPCSTR propname, const CFX_ByteString& sData)
    225 {
    226 	ASSERT(propname != NULL);
    227 	CFX_ByteString sPropName = propname;
    228 
    229 	sPropName.TrimLeft();
    230 	sPropName.TrimRight();
    231 
    232 	if (sPropName.GetLength() == 0) return;
    233 
    234 	if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName))
    235 	{
    236 		pData->data.nType = JS_GLOBALDATA_TYPE_STRING;
    237 		pData->data.sData = sData;
    238 	}
    239 	else
    240 	{
    241 		CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element;
    242 		pNewData->data.sKey = sPropName;
    243 		pNewData->data.nType = JS_GLOBALDATA_TYPE_STRING;
    244 		pNewData->data.sData = sData;
    245 
    246 		m_arrayGlobalData.Add(pNewData);
    247 	}
    248 }
    249 
    250 void CJS_GlobalData::SetGlobalVariableObject(FX_LPCSTR propname, const CJS_GlobalVariableArray& array)
    251 {
    252 	ASSERT(propname != NULL);
    253 	CFX_ByteString sPropName = propname;
    254 
    255 	sPropName.TrimLeft();
    256 	sPropName.TrimRight();
    257 
    258 	if (sPropName.GetLength() == 0) return;
    259 
    260 	if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName))
    261 	{
    262 		pData->data.nType = JS_GLOBALDATA_TYPE_OBJECT;
    263 		pData->data.objData.Copy(array);
    264 	}
    265 	else
    266 	{
    267 		CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element;
    268 		pNewData->data.sKey = sPropName;
    269 		pNewData->data.nType = JS_GLOBALDATA_TYPE_OBJECT;
    270 		pNewData->data.objData.Copy(array);
    271 
    272 		m_arrayGlobalData.Add(pNewData);
    273 	}
    274 }
    275 
    276 void CJS_GlobalData::SetGlobalVariableNull(FX_LPCSTR propname)
    277 {
    278 	ASSERT(propname != NULL);
    279 	CFX_ByteString sPropName = propname;
    280 
    281 	sPropName.TrimLeft();
    282 	sPropName.TrimRight();
    283 
    284 	if (sPropName.GetLength() == 0) return;
    285 
    286 	if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName))
    287 	{
    288 		pData->data.nType = JS_GLOBALDATA_TYPE_NULL;
    289 	}
    290 	else
    291 	{
    292 		CJS_GlobalData_Element* pNewData = new CJS_GlobalData_Element;
    293 		pNewData->data.sKey = sPropName;
    294 		pNewData->data.nType = JS_GLOBALDATA_TYPE_NULL;
    295 
    296 		m_arrayGlobalData.Add(pNewData);
    297 	}
    298 }
    299 
    300 FX_BOOL CJS_GlobalData::SetGlobalVariablePersistent(FX_LPCSTR propname, FX_BOOL bPersistent)
    301 {
    302 	ASSERT(propname != NULL);
    303 	CFX_ByteString sPropName = propname;
    304 
    305 	sPropName.TrimLeft();
    306 	sPropName.TrimRight();
    307 
    308 	if (sPropName.GetLength() == 0) return FALSE;
    309 
    310 	if (CJS_GlobalData_Element* pData = GetGlobalVariable(sPropName))
    311 	{
    312 		pData->bPersistent = bPersistent;
    313 		return TRUE;
    314 	}
    315 
    316 	return FALSE;
    317 }
    318 
    319 FX_BOOL CJS_GlobalData::DeleteGlobalVariable(FX_LPCSTR propname)
    320 {
    321 	ASSERT(propname != NULL);
    322 	CFX_ByteString sPropName = propname;
    323 
    324 	sPropName.TrimLeft();
    325 	sPropName.TrimRight();
    326 
    327 	if (sPropName.GetLength() == 0) return FALSE;
    328 
    329 	int	nFind = FindGlobalVariable(sPropName);
    330 
    331 	if (nFind >= 0)
    332 	{
    333 		delete m_arrayGlobalData.GetAt(nFind);
    334 		m_arrayGlobalData.RemoveAt(nFind);
    335 		return TRUE;
    336 	}
    337 
    338 	return FALSE;
    339 }
    340 
    341 FX_INT32 CJS_GlobalData::GetSize() const
    342 {
    343 	return m_arrayGlobalData.GetSize();
    344 }
    345 
    346 CJS_GlobalData_Element* CJS_GlobalData::GetAt(int index) const
    347 {
    348 	return m_arrayGlobalData.GetAt(index);
    349 }
    350 
    351 void CJS_GlobalData::LoadGlobalPersistentVariables()
    352 {
    353 	FX_LPBYTE pBuffer = NULL;
    354 	FX_INT32 nLength = 0;
    355 
    356 	LoadFileBuffer(m_sFilePath, pBuffer, nLength);
    357 
    358 	CRYPT_ArcFourCryptBlock(pBuffer, nLength, JS_RC4KEY, sizeof(JS_RC4KEY));
    359 
    360 	if (pBuffer)
    361 	{
    362 		FX_LPBYTE p = pBuffer;
    363 		FX_WORD wType = *((FX_WORD*)p);
    364 		p += sizeof(FX_WORD);
    365 
    366 		//FX_WORD wTemp = (FX_WORD)(('X' << 8) | 'F');
    367 
    368 		if (wType == (FX_WORD)(('X' << 8) | 'F'))
    369 		{
    370 			FX_WORD wVersion = *((FX_WORD*)p);
    371 			p += sizeof(FX_WORD);
    372 
    373 			ASSERT(wVersion <= 2);
    374 
    375 			FX_DWORD dwCount = *((FX_DWORD*)p);
    376 			p += sizeof(FX_DWORD);
    377 
    378 			FX_DWORD dwSize = *((FX_DWORD*)p);
    379 			p += sizeof(FX_DWORD);
    380 
    381 			if (dwSize == nLength - sizeof(FX_WORD) * 2 - sizeof(FX_DWORD)* 2)
    382 			{
    383 				for (FX_INT32 i=0,sz=dwCount; i<sz; i++)
    384 				{
    385 					if (p > pBuffer + nLength)
    386 						break;
    387 
    388 					FX_DWORD dwNameLen = *((FX_DWORD*)p);
    389 					p += sizeof(FX_DWORD);
    390 
    391 					if (p + dwNameLen > pBuffer + nLength)
    392 						break;
    393 
    394 					CFX_ByteString sEntry = CFX_ByteString(p, dwNameLen);
    395 					p += sizeof(char) * dwNameLen;
    396 
    397 					FX_WORD wDataType = *((FX_WORD*)p);
    398 					p += sizeof(FX_WORD);
    399 
    400 					switch (wDataType)
    401 					{
    402 					case JS_GLOBALDATA_TYPE_NUMBER:
    403 						{
    404 							double dData = 0;
    405 							switch (wVersion)
    406 							{
    407 							case 1:
    408 								{
    409 									FX_DWORD dwData = *((FX_DWORD*)p);
    410 									p += sizeof(FX_DWORD);
    411 									dData = dwData;
    412 								}
    413 								break;
    414 							case 2:
    415 								{
    416 									dData = *((double*)p);
    417 									p += sizeof(double);
    418 								}
    419 								break;
    420 							}
    421 							SetGlobalVariableNumber(sEntry, dData);
    422 							SetGlobalVariablePersistent(sEntry, TRUE);
    423 						}
    424 						break;
    425 					case JS_GLOBALDATA_TYPE_BOOLEAN:
    426 						{
    427 							FX_WORD wData = *((FX_WORD*)p);
    428 							p += sizeof(FX_WORD);
    429 							SetGlobalVariableBoolean(sEntry, (bool)(wData == 1));
    430 							SetGlobalVariablePersistent(sEntry, TRUE);
    431 						}
    432 						break;
    433 					case JS_GLOBALDATA_TYPE_STRING:
    434 						{
    435 							FX_DWORD dwLength = *((FX_DWORD*)p);
    436 							p += sizeof(FX_DWORD);
    437 
    438 							if (p + dwLength > pBuffer + nLength)
    439 								break;
    440 
    441 							SetGlobalVariableString(sEntry, CFX_ByteString(p, dwLength));
    442 							SetGlobalVariablePersistent(sEntry, TRUE);
    443 							p += sizeof(char) * dwLength;
    444 						}
    445 						break;
    446 					case JS_GLOBALDATA_TYPE_NULL:
    447 						{
    448 							SetGlobalVariableNull(sEntry);
    449 							SetGlobalVariablePersistent(sEntry, TRUE);
    450 						}
    451 					}
    452 				}
    453 			}
    454 		}
    455 		FX_Free(pBuffer);
    456 	}
    457 }
    458 
    459 /*
    460 struct js_global_datafile_header
    461 {
    462 	FX_WORD type; //FX ('X' << 8) | 'F'
    463 	FX_WORD version; //1.0
    464 	FX_DWORD datacount;
    465 };
    466 struct js_global_datafile_data
    467 {
    468 	FX_WORD type;
    469 	FX_DWORD nData;
    470 	FX_WORD bData;
    471 	FX_DWORD nStrLen;
    472 	char* pStr;
    473 };
    474 */
    475 
    476 void CJS_GlobalData::SaveGlobalPersisitentVariables()
    477 {
    478 	FX_DWORD nCount = 0;
    479 	CFX_BinaryBuf sData;
    480 
    481 	for (int i=0,sz=m_arrayGlobalData.GetSize(); i<sz; i++)
    482 	{
    483 		CJS_GlobalData_Element* pElement = m_arrayGlobalData.GetAt(i);
    484 		ASSERT(pElement != NULL);
    485 
    486 		if (pElement->bPersistent)
    487 		{
    488 			CFX_BinaryBuf sElement;
    489 			MakeByteString(pElement->data.sKey, &pElement->data, sElement);
    490 
    491 			if (sData.GetSize() + sElement.GetSize() > JS_MAXGLOBALDATA)
    492 				break;
    493 
    494 			sData.AppendBlock(sElement.GetBuffer(), sElement.GetSize());
    495 			nCount++;
    496 		}
    497 	}
    498 
    499 	CFX_BinaryBuf sFile;
    500 
    501 	FX_WORD wType = (FX_WORD)(('X' << 8) | 'F');
    502 	sFile.AppendBlock(&wType, sizeof(FX_WORD));
    503 	FX_WORD wVersion = 2;
    504 	sFile.AppendBlock(&wVersion, sizeof(FX_WORD));
    505 	sFile.AppendBlock(&nCount, sizeof(FX_DWORD));
    506 	FX_DWORD dwSize = sData.GetSize();
    507 	sFile.AppendBlock(&dwSize, sizeof(FX_DWORD));
    508 
    509 	sFile.AppendBlock(sData.GetBuffer(), sData.GetSize());
    510 
    511 	CRYPT_ArcFourCryptBlock(sFile.GetBuffer(), sFile.GetSize(), JS_RC4KEY, sizeof(JS_RC4KEY));
    512 	WriteFileBuffer(m_sFilePath, (FX_LPCSTR)sFile.GetBuffer(), sFile.GetSize());
    513 }
    514 
    515 void CJS_GlobalData::LoadFileBuffer(FX_LPCWSTR sFilePath, FX_LPBYTE& pBuffer, FX_INT32& nLength)
    516 {
    517 //UnSupport.
    518 }
    519 
    520 void CJS_GlobalData::WriteFileBuffer(FX_LPCWSTR sFilePath, FX_LPCSTR pBuffer, FX_INT32 nLength)
    521 {
    522 //UnSupport.
    523 }
    524 
    525 void CJS_GlobalData::MakeByteString(const CFX_ByteString& name, CJS_KeyValue* pData, CFX_BinaryBuf& sData)
    526 {
    527 	ASSERT(pData != NULL);
    528 
    529 	FX_WORD wType = (FX_WORD)pData->nType;
    530 
    531 	switch (wType)
    532 	{
    533 	case JS_GLOBALDATA_TYPE_NUMBER:
    534 		{
    535 			FX_DWORD dwNameLen = (FX_DWORD)name.GetLength();
    536 			sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD));
    537 			sData.AppendString(name);
    538 
    539 			sData.AppendBlock(&wType, sizeof(FX_WORD));
    540 			double dData = pData->dData;
    541 			sData.AppendBlock(&dData, sizeof(double));
    542 		}
    543 		break;
    544 	case JS_GLOBALDATA_TYPE_BOOLEAN:
    545 		{
    546 			FX_DWORD dwNameLen = (FX_DWORD)name.GetLength();
    547 			sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD));
    548 			sData.AppendString(name);
    549 
    550 			sData.AppendBlock(&wType, sizeof(FX_WORD));
    551 			FX_WORD wData = (FX_WORD)pData->bData;
    552 			sData.AppendBlock(&wData, sizeof(FX_WORD));
    553 		}
    554 		break;
    555 	case JS_GLOBALDATA_TYPE_STRING:
    556 		{
    557 			FX_DWORD dwNameLen = (FX_DWORD)name.GetLength();
    558 			sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD));
    559 			sData.AppendString(name);
    560 
    561 			sData.AppendBlock(&wType, sizeof(FX_WORD));
    562 
    563 			FX_DWORD dwDataLen = (FX_DWORD)pData->sData.GetLength();
    564 			sData.AppendBlock(&dwDataLen, sizeof(FX_DWORD));
    565 			sData.AppendString(pData->sData);
    566 		}
    567 		break;
    568 	case JS_GLOBALDATA_TYPE_NULL:
    569 		{
    570 			FX_DWORD dwNameLen = (FX_DWORD)name.GetLength();
    571 			sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD));
    572 			sData.AppendString(name);
    573 
    574 			sData.AppendBlock(&wType, sizeof(FX_DWORD));
    575 		}
    576 		break;
    577 	default:
    578 		break;
    579 	}
    580 }
    581 
    582