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