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)
    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.c_str(), pBuffer, nLength);
    357 	CRYPT_ArcFourCryptBlock(pBuffer, nLength, JS_RC4KEY, sizeof(JS_RC4KEY));
    358 
    359 	if (pBuffer)
    360 	{
    361 		FX_LPBYTE p = pBuffer;
    362 		FX_WORD wType = *((FX_WORD*)p);
    363 		p += sizeof(FX_WORD);
    364 
    365 		//FX_WORD wTemp = (FX_WORD)(('X' << 8) | 'F');
    366 
    367 		if (wType == (FX_WORD)(('X' << 8) | 'F'))
    368 		{
    369 			FX_WORD wVersion = *((FX_WORD*)p);
    370 			p += sizeof(FX_WORD);
    371 
    372 			ASSERT(wVersion <= 2);
    373 
    374 			FX_DWORD dwCount = *((FX_DWORD*)p);
    375 			p += sizeof(FX_DWORD);
    376 
    377 			FX_DWORD dwSize = *((FX_DWORD*)p);
    378 			p += sizeof(FX_DWORD);
    379 
    380 			if (dwSize == nLength - sizeof(FX_WORD) * 2 - sizeof(FX_DWORD)* 2)
    381 			{
    382 				for (FX_INT32 i=0,sz=dwCount; i<sz; i++)
    383 				{
    384 					if (p > pBuffer + nLength)
    385 						break;
    386 
    387 					FX_DWORD dwNameLen = *((FX_DWORD*)p);
    388 					p += sizeof(FX_DWORD);
    389 
    390 					if (p + dwNameLen > pBuffer + nLength)
    391 						break;
    392 
    393 					CFX_ByteString sEntry = CFX_ByteString(p, dwNameLen);
    394 					p += sizeof(char) * dwNameLen;
    395 
    396 					FX_WORD wDataType = *((FX_WORD*)p);
    397 					p += sizeof(FX_WORD);
    398 
    399 					switch (wDataType)
    400 					{
    401 					case JS_GLOBALDATA_TYPE_NUMBER:
    402 						{
    403 							double dData = 0;
    404 							switch (wVersion)
    405 							{
    406 							case 1:
    407 								{
    408 									FX_DWORD dwData = *((FX_DWORD*)p);
    409 									p += sizeof(FX_DWORD);
    410 									dData = dwData;
    411 								}
    412 								break;
    413 							case 2:
    414 								{
    415 									dData = *((double*)p);
    416 									p += sizeof(double);
    417 								}
    418 								break;
    419 							}
    420 							SetGlobalVariableNumber(sEntry, dData);
    421 							SetGlobalVariablePersistent(sEntry, TRUE);
    422 						}
    423 						break;
    424 					case JS_GLOBALDATA_TYPE_BOOLEAN:
    425 						{
    426 							FX_WORD wData = *((FX_WORD*)p);
    427 							p += sizeof(FX_WORD);
    428 							SetGlobalVariableBoolean(sEntry, (bool)(wData == 1));
    429 							SetGlobalVariablePersistent(sEntry, TRUE);
    430 						}
    431 						break;
    432 					case JS_GLOBALDATA_TYPE_STRING:
    433 						{
    434 							FX_DWORD dwLength = *((FX_DWORD*)p);
    435 							p += sizeof(FX_DWORD);
    436 
    437 							if (p + dwLength > pBuffer + nLength)
    438 								break;
    439 
    440 							SetGlobalVariableString(sEntry, CFX_ByteString(p, dwLength));
    441 							SetGlobalVariablePersistent(sEntry, TRUE);
    442 							p += sizeof(char) * dwLength;
    443 						}
    444 						break;
    445 					case JS_GLOBALDATA_TYPE_NULL:
    446 						{
    447 							SetGlobalVariableNull(sEntry);
    448 							SetGlobalVariablePersistent(sEntry, TRUE);
    449 						}
    450 					}
    451 				}
    452 			}
    453 		}
    454 		FX_Free(pBuffer);
    455 	}
    456 }
    457 
    458 /*
    459 struct js_global_datafile_header
    460 {
    461 	FX_WORD type; //FX ('X' << 8) | 'F'
    462 	FX_WORD version; //1.0
    463 	FX_DWORD datacount;
    464 };
    465 struct js_global_datafile_data
    466 {
    467 	FX_WORD type;
    468 	FX_DWORD nData;
    469 	FX_WORD bData;
    470 	FX_DWORD nStrLen;
    471 	char* pStr;
    472 };
    473 */
    474 
    475 void CJS_GlobalData::SaveGlobalPersisitentVariables()
    476 {
    477 	FX_DWORD nCount = 0;
    478 	CFX_BinaryBuf sData;
    479 
    480 	for (int i=0,sz=m_arrayGlobalData.GetSize(); i<sz; i++)
    481 	{
    482 		CJS_GlobalData_Element* pElement = m_arrayGlobalData.GetAt(i);
    483 		ASSERT(pElement != NULL);
    484 
    485 		if (pElement->bPersistent)
    486 		{
    487 			CFX_BinaryBuf sElement;
    488 			MakeByteString(pElement->data.sKey, &pElement->data, sElement);
    489 
    490 			if (sData.GetSize() + sElement.GetSize() > JS_MAXGLOBALDATA)
    491 				break;
    492 
    493 			sData.AppendBlock(sElement.GetBuffer(), sElement.GetSize());
    494 			nCount++;
    495 		}
    496 	}
    497 
    498 	CFX_BinaryBuf sFile;
    499 
    500 	FX_WORD wType = (FX_WORD)(('X' << 8) | 'F');
    501 	sFile.AppendBlock(&wType, sizeof(FX_WORD));
    502 	FX_WORD wVersion = 2;
    503 	sFile.AppendBlock(&wVersion, sizeof(FX_WORD));
    504 	sFile.AppendBlock(&nCount, sizeof(FX_DWORD));
    505 	FX_DWORD dwSize = sData.GetSize();
    506 	sFile.AppendBlock(&dwSize, sizeof(FX_DWORD));
    507 
    508 	sFile.AppendBlock(sData.GetBuffer(), sData.GetSize());
    509 
    510 	CRYPT_ArcFourCryptBlock(sFile.GetBuffer(), sFile.GetSize(), JS_RC4KEY, sizeof(JS_RC4KEY));
    511 	WriteFileBuffer(m_sFilePath.c_str(), (FX_LPCSTR)sFile.GetBuffer(), sFile.GetSize());
    512 }
    513 
    514 void CJS_GlobalData::LoadFileBuffer(FX_LPCWSTR sFilePath, FX_LPBYTE& pBuffer, FX_INT32& nLength)
    515 {
    516 //UnSupport.
    517 }
    518 
    519 void CJS_GlobalData::WriteFileBuffer(FX_LPCWSTR sFilePath, FX_LPCSTR pBuffer, FX_INT32 nLength)
    520 {
    521 //UnSupport.
    522 }
    523 
    524 void CJS_GlobalData::MakeByteString(const CFX_ByteString& name, CJS_KeyValue* pData, CFX_BinaryBuf& sData)
    525 {
    526 	ASSERT(pData != NULL);
    527 
    528 	FX_WORD wType = (FX_WORD)pData->nType;
    529 
    530 	switch (wType)
    531 	{
    532 	case JS_GLOBALDATA_TYPE_NUMBER:
    533 		{
    534 			FX_DWORD dwNameLen = (FX_DWORD)name.GetLength();
    535 			sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD));
    536 			sData.AppendString(name);
    537 
    538 			sData.AppendBlock(&wType, sizeof(FX_WORD));
    539 			double dData = pData->dData;
    540 			sData.AppendBlock(&dData, sizeof(double));
    541 		}
    542 		break;
    543 	case JS_GLOBALDATA_TYPE_BOOLEAN:
    544 		{
    545 			FX_DWORD dwNameLen = (FX_DWORD)name.GetLength();
    546 			sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD));
    547 			sData.AppendString(name);
    548 
    549 			sData.AppendBlock(&wType, sizeof(FX_WORD));
    550 			FX_WORD wData = (FX_WORD)pData->bData;
    551 			sData.AppendBlock(&wData, sizeof(FX_WORD));
    552 		}
    553 		break;
    554 	case JS_GLOBALDATA_TYPE_STRING:
    555 		{
    556 			FX_DWORD dwNameLen = (FX_DWORD)name.GetLength();
    557 			sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD));
    558 			sData.AppendString(name);
    559 
    560 			sData.AppendBlock(&wType, sizeof(FX_WORD));
    561 
    562 			FX_DWORD dwDataLen = (FX_DWORD)pData->sData.GetLength();
    563 			sData.AppendBlock(&dwDataLen, sizeof(FX_DWORD));
    564 			sData.AppendString(pData->sData);
    565 		}
    566 		break;
    567 	case JS_GLOBALDATA_TYPE_NULL:
    568 		{
    569 			FX_DWORD dwNameLen = (FX_DWORD)name.GetLength();
    570 			sData.AppendBlock(&dwNameLen, sizeof(FX_DWORD));
    571 			sData.AppendString(name);
    572 
    573 			sData.AppendBlock(&wType, sizeof(FX_DWORD));
    574 		}
    575 		break;
    576 	default:
    577 		break;
    578 	}
    579 }
    580 
    581