• 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) : 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 
~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, 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 
SaveGlobalPersisitentVariables()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 
LoadFileBuffer(FX_LPCWSTR sFilePath,FX_LPBYTE & pBuffer,FX_INT32 & nLength)515 void CJS_GlobalData::LoadFileBuffer(FX_LPCWSTR sFilePath, FX_LPBYTE& pBuffer, FX_INT32& nLength)
516 {
517 //UnSupport.
518 }
519 
WriteFileBuffer(FX_LPCWSTR sFilePath,FX_LPCSTR pBuffer,FX_INT32 nLength)520 void CJS_GlobalData::WriteFileBuffer(FX_LPCWSTR sFilePath, FX_LPCSTR pBuffer, FX_INT32 nLength)
521 {
522 //UnSupport.
523 }
524 
MakeByteString(const CFX_ByteString & name,CJS_KeyValue * pData,CFX_BinaryBuf & sData)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