• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CJS_GlobalVariableArray()15 CJS_GlobalVariableArray::CJS_GlobalVariableArray()
16 {
17 }
18 
~CJS_GlobalVariableArray()19 CJS_GlobalVariableArray::~CJS_GlobalVariableArray()
20 {
21 	Empty();
22 }
23 
Copy(const CJS_GlobalVariableArray & array)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 
Add(CJS_KeyValue * p)80 void CJS_GlobalVariableArray::Add(CJS_KeyValue* p)
81 {
82 	array.Add(p);
83 }
84 
Count() const85 int CJS_GlobalVariableArray::Count() const
86 {
87 	return array.GetSize();
88 }
89 
GetAt(int index) const90 CJS_KeyValue* CJS_GlobalVariableArray::GetAt(int index) const
91 {
92 	return array.GetAt(index);
93 }
94 
Empty()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 
CJS_GlobalData(CPDFDoc_Environment * pApp)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 
~CJS_GlobalData()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 
FindGlobalVariable(FX_LPCSTR propname)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 
GetGlobalVariable(FX_LPCSTR propname)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 
SetGlobalVariableNumber(FX_LPCSTR propname,double dData)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 
SetGlobalVariableBoolean(FX_LPCSTR propname,bool bData)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 
SetGlobalVariableString(FX_LPCSTR propname,const CFX_ByteString & sData)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 
SetGlobalVariableObject(FX_LPCSTR propname,const CJS_GlobalVariableArray & array)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 
SetGlobalVariableNull(FX_LPCSTR propname)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 
SetGlobalVariablePersistent(FX_LPCSTR propname,FX_BOOL bPersistent)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 
DeleteGlobalVariable(FX_LPCSTR propname)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 
GetSize() const341 FX_INT32 CJS_GlobalData::GetSize() const
342 {
343 	return m_arrayGlobalData.GetSize();
344 }
345 
GetAt(int index) const346 CJS_GlobalData_Element* CJS_GlobalData::GetAt(int index) const
347 {
348 	return m_arrayGlobalData.GetAt(index);
349 }
350 
LoadGlobalPersistentVariables()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 
SaveGlobalPersisitentVariables()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 
LoadFileBuffer(FX_LPCWSTR sFilePath,FX_LPBYTE & pBuffer,FX_INT32 & nLength)514 void CJS_GlobalData::LoadFileBuffer(FX_LPCWSTR sFilePath, FX_LPBYTE& pBuffer, FX_INT32& nLength)
515 {
516 //UnSupport.
517 }
518 
WriteFileBuffer(FX_LPCWSTR sFilePath,FX_LPCSTR pBuffer,FX_INT32 nLength)519 void CJS_GlobalData::WriteFileBuffer(FX_LPCWSTR sFilePath, FX_LPCSTR pBuffer, FX_INT32 nLength)
520 {
521 //UnSupport.
522 }
523 
MakeByteString(const CFX_ByteString & name,CJS_KeyValue * pData,CFX_BinaryBuf & sData)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