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/fxcrt/fx_basic.h"
8 #include "core/include/fxcrt/fx_ext.h"
9 #include "extension.h"
10
11 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
12 #include <wincrypt.h>
13 #else
14 #include <ctime>
15 #endif
16
CFX_CRTFileStream(IFXCRT_FileAccess * pFA)17 CFX_CRTFileStream::CFX_CRTFileStream(IFXCRT_FileAccess* pFA)
18 : m_pFile(pFA), m_dwCount(1) {}
19
~CFX_CRTFileStream()20 CFX_CRTFileStream::~CFX_CRTFileStream() {
21 if (m_pFile) {
22 m_pFile->Release();
23 }
24 }
25
Retain()26 IFX_FileStream* CFX_CRTFileStream::Retain() {
27 m_dwCount++;
28 return this;
29 }
30
Release()31 void CFX_CRTFileStream::Release() {
32 FX_DWORD nCount = --m_dwCount;
33 if (!nCount) {
34 delete this;
35 }
36 }
37
GetSize()38 FX_FILESIZE CFX_CRTFileStream::GetSize() {
39 return m_pFile->GetSize();
40 }
41
IsEOF()42 FX_BOOL CFX_CRTFileStream::IsEOF() {
43 return GetPosition() >= GetSize();
44 }
45
GetPosition()46 FX_FILESIZE CFX_CRTFileStream::GetPosition() {
47 return m_pFile->GetPosition();
48 }
49
ReadBlock(void * buffer,FX_FILESIZE offset,size_t size)50 FX_BOOL CFX_CRTFileStream::ReadBlock(void* buffer,
51 FX_FILESIZE offset,
52 size_t size) {
53 return (FX_BOOL)m_pFile->ReadPos(buffer, size, offset);
54 }
55
ReadBlock(void * buffer,size_t size)56 size_t CFX_CRTFileStream::ReadBlock(void* buffer, size_t size) {
57 return m_pFile->Read(buffer, size);
58 }
59
WriteBlock(const void * buffer,FX_FILESIZE offset,size_t size)60 FX_BOOL CFX_CRTFileStream::WriteBlock(const void* buffer,
61 FX_FILESIZE offset,
62 size_t size) {
63 return (FX_BOOL)m_pFile->WritePos(buffer, size, offset);
64 }
65
Flush()66 FX_BOOL CFX_CRTFileStream::Flush() {
67 return m_pFile->Flush();
68 }
69
70 #ifdef PDF_ENABLE_XFA
FX_CreateDefaultFileAccess(const CFX_WideStringC & wsPath)71 IFX_FileAccess* FX_CreateDefaultFileAccess(const CFX_WideStringC& wsPath) {
72 if (wsPath.GetLength() == 0)
73 return NULL;
74
75 CFX_CRTFileAccess* pFA = NULL;
76 pFA = new CFX_CRTFileAccess;
77 if (NULL == pFA)
78 return NULL;
79
80 pFA->Init(wsPath);
81 return pFA;
82 }
83 #endif // PDF_ENABLE_XFA
84
FX_CreateFileStream(const FX_CHAR * filename,FX_DWORD dwModes)85 IFX_FileStream* FX_CreateFileStream(const FX_CHAR* filename, FX_DWORD dwModes) {
86 IFXCRT_FileAccess* pFA = FXCRT_FileAccess_Create();
87 if (!pFA) {
88 return NULL;
89 }
90 if (!pFA->Open(filename, dwModes)) {
91 pFA->Release();
92 return NULL;
93 }
94 return new CFX_CRTFileStream(pFA);
95 }
FX_CreateFileStream(const FX_WCHAR * filename,FX_DWORD dwModes)96 IFX_FileStream* FX_CreateFileStream(const FX_WCHAR* filename,
97 FX_DWORD dwModes) {
98 IFXCRT_FileAccess* pFA = FXCRT_FileAccess_Create();
99 if (!pFA) {
100 return NULL;
101 }
102 if (!pFA->Open(filename, dwModes)) {
103 pFA->Release();
104 return NULL;
105 }
106 return new CFX_CRTFileStream(pFA);
107 }
FX_CreateFileRead(const FX_CHAR * filename)108 IFX_FileRead* FX_CreateFileRead(const FX_CHAR* filename) {
109 return FX_CreateFileStream(filename, FX_FILEMODE_ReadOnly);
110 }
FX_CreateFileRead(const FX_WCHAR * filename)111 IFX_FileRead* FX_CreateFileRead(const FX_WCHAR* filename) {
112 return FX_CreateFileStream(filename, FX_FILEMODE_ReadOnly);
113 }
FX_CreateMemoryStream(uint8_t * pBuffer,size_t dwSize,FX_BOOL bTakeOver)114 IFX_MemoryStream* FX_CreateMemoryStream(uint8_t* pBuffer,
115 size_t dwSize,
116 FX_BOOL bTakeOver) {
117 return new CFX_MemoryStream(pBuffer, dwSize, bTakeOver);
118 }
FX_CreateMemoryStream(FX_BOOL bConsecutive)119 IFX_MemoryStream* FX_CreateMemoryStream(FX_BOOL bConsecutive) {
120 return new CFX_MemoryStream(bConsecutive);
121 }
122
FXSYS_tan(FX_FLOAT a)123 FX_FLOAT FXSYS_tan(FX_FLOAT a) {
124 return (FX_FLOAT)tan(a);
125 }
FXSYS_logb(FX_FLOAT b,FX_FLOAT x)126 FX_FLOAT FXSYS_logb(FX_FLOAT b, FX_FLOAT x) {
127 return FXSYS_log(x) / FXSYS_log(b);
128 }
FXSYS_strtof(const FX_CHAR * pcsStr,int32_t iLength,int32_t * pUsedLen)129 FX_FLOAT FXSYS_strtof(const FX_CHAR* pcsStr,
130 int32_t iLength,
131 int32_t* pUsedLen) {
132 FXSYS_assert(pcsStr);
133 if (iLength < 0) {
134 iLength = (int32_t)FXSYS_strlen(pcsStr);
135 }
136 CFX_WideString ws = CFX_WideString::FromLocal(pcsStr, iLength);
137 return FXSYS_wcstof(ws.c_str(), iLength, pUsedLen);
138 }
FXSYS_wcstof(const FX_WCHAR * pwsStr,int32_t iLength,int32_t * pUsedLen)139 FX_FLOAT FXSYS_wcstof(const FX_WCHAR* pwsStr,
140 int32_t iLength,
141 int32_t* pUsedLen) {
142 FXSYS_assert(pwsStr);
143 if (iLength < 0) {
144 iLength = (int32_t)FXSYS_wcslen(pwsStr);
145 }
146 if (iLength == 0) {
147 return 0.0f;
148 }
149 int32_t iUsedLen = 0;
150 FX_BOOL bNegtive = FALSE;
151 switch (pwsStr[iUsedLen]) {
152 case '-':
153 bNegtive = TRUE;
154 case '+':
155 iUsedLen++;
156 break;
157 }
158 FX_FLOAT fValue = 0.0f;
159 while (iUsedLen < iLength) {
160 FX_WCHAR wch = pwsStr[iUsedLen];
161 if (wch >= L'0' && wch <= L'9') {
162 fValue = fValue * 10.0f + (wch - L'0');
163 } else {
164 break;
165 }
166 iUsedLen++;
167 }
168 if (iUsedLen < iLength && pwsStr[iUsedLen] == L'.') {
169 FX_FLOAT fPrecise = 0.1f;
170 while (++iUsedLen < iLength) {
171 FX_WCHAR wch = pwsStr[iUsedLen];
172 if (wch >= L'0' && wch <= L'9') {
173 fValue += (wch - L'0') * fPrecise;
174 fPrecise *= 0.1f;
175 } else {
176 break;
177 }
178 }
179 }
180 if (pUsedLen) {
181 *pUsedLen = iUsedLen;
182 }
183 return bNegtive ? -fValue : fValue;
184 }
FXSYS_wcsncpy(FX_WCHAR * dstStr,const FX_WCHAR * srcStr,size_t count)185 FX_WCHAR* FXSYS_wcsncpy(FX_WCHAR* dstStr,
186 const FX_WCHAR* srcStr,
187 size_t count) {
188 FXSYS_assert(dstStr && srcStr && count > 0);
189 for (size_t i = 0; i < count; ++i)
190 if ((dstStr[i] = srcStr[i]) == L'\0') {
191 break;
192 }
193 return dstStr;
194 }
FXSYS_wcsnicmp(const FX_WCHAR * s1,const FX_WCHAR * s2,size_t count)195 int32_t FXSYS_wcsnicmp(const FX_WCHAR* s1, const FX_WCHAR* s2, size_t count) {
196 FXSYS_assert(s1 && s2 && count > 0);
197 FX_WCHAR wch1 = 0, wch2 = 0;
198 while (count-- > 0) {
199 wch1 = (FX_WCHAR)FXSYS_tolower(*s1++);
200 wch2 = (FX_WCHAR)FXSYS_tolower(*s2++);
201 if (wch1 != wch2) {
202 break;
203 }
204 }
205 return wch1 - wch2;
206 }
FXSYS_strnicmp(const FX_CHAR * s1,const FX_CHAR * s2,size_t count)207 int32_t FXSYS_strnicmp(const FX_CHAR* s1, const FX_CHAR* s2, size_t count) {
208 FXSYS_assert(s1 && s2 && count > 0);
209 FX_CHAR ch1 = 0, ch2 = 0;
210 while (count-- > 0) {
211 ch1 = (FX_CHAR)FXSYS_tolower(*s1++);
212 ch2 = (FX_CHAR)FXSYS_tolower(*s2++);
213 if (ch1 != ch2) {
214 break;
215 }
216 }
217 return ch1 - ch2;
218 }
FX_HashCode_String_GetA(const FX_CHAR * pStr,int32_t iLength,FX_BOOL bIgnoreCase)219 FX_DWORD FX_HashCode_String_GetA(const FX_CHAR* pStr,
220 int32_t iLength,
221 FX_BOOL bIgnoreCase) {
222 FXSYS_assert(pStr);
223 if (iLength < 0) {
224 iLength = (int32_t)FXSYS_strlen(pStr);
225 }
226 const FX_CHAR* pStrEnd = pStr + iLength;
227 FX_DWORD dwHashCode = 0;
228 if (bIgnoreCase) {
229 while (pStr < pStrEnd) {
230 dwHashCode = 31 * dwHashCode + FXSYS_tolower(*pStr++);
231 }
232 } else {
233 while (pStr < pStrEnd) {
234 dwHashCode = 31 * dwHashCode + *pStr++;
235 }
236 }
237 return dwHashCode;
238 }
FX_HashCode_String_GetW(const FX_WCHAR * pStr,int32_t iLength,FX_BOOL bIgnoreCase)239 FX_DWORD FX_HashCode_String_GetW(const FX_WCHAR* pStr,
240 int32_t iLength,
241 FX_BOOL bIgnoreCase) {
242 FXSYS_assert(pStr);
243 if (iLength < 0) {
244 iLength = (int32_t)FXSYS_wcslen(pStr);
245 }
246 const FX_WCHAR* pStrEnd = pStr + iLength;
247 FX_DWORD dwHashCode = 0;
248 if (bIgnoreCase) {
249 while (pStr < pStrEnd) {
250 dwHashCode = 1313 * dwHashCode + FXSYS_tolower(*pStr++);
251 }
252 } else {
253 while (pStr < pStrEnd) {
254 dwHashCode = 1313 * dwHashCode + *pStr++;
255 }
256 }
257 return dwHashCode;
258 }
259
FX_Random_MT_Start(FX_DWORD dwSeed)260 void* FX_Random_MT_Start(FX_DWORD dwSeed) {
261 FX_LPMTRANDOMCONTEXT pContext = FX_Alloc(FX_MTRANDOMCONTEXT, 1);
262 pContext->mt[0] = dwSeed;
263 FX_DWORD& i = pContext->mti;
264 FX_DWORD* pBuf = pContext->mt;
265 for (i = 1; i < MT_N; i++) {
266 pBuf[i] = (1812433253UL * (pBuf[i - 1] ^ (pBuf[i - 1] >> 30)) + i);
267 }
268 pContext->bHaveSeed = TRUE;
269 return pContext;
270 }
FX_Random_MT_Generate(void * pContext)271 FX_DWORD FX_Random_MT_Generate(void* pContext) {
272 FXSYS_assert(pContext);
273 FX_LPMTRANDOMCONTEXT pMTC = (FX_LPMTRANDOMCONTEXT)pContext;
274 FX_DWORD v;
275 static FX_DWORD mag[2] = {0, MT_Matrix_A};
276 FX_DWORD& mti = pMTC->mti;
277 FX_DWORD* pBuf = pMTC->mt;
278 if ((int)mti < 0 || mti >= MT_N) {
279 if (mti > MT_N && !pMTC->bHaveSeed) {
280 return 0;
281 }
282 FX_DWORD kk;
283 for (kk = 0; kk < MT_N - MT_M; kk++) {
284 v = (pBuf[kk] & MT_Upper_Mask) | (pBuf[kk + 1] & MT_Lower_Mask);
285 pBuf[kk] = pBuf[kk + MT_M] ^ (v >> 1) ^ mag[v & 1];
286 }
287 for (; kk < MT_N - 1; kk++) {
288 v = (pBuf[kk] & MT_Upper_Mask) | (pBuf[kk + 1] & MT_Lower_Mask);
289 pBuf[kk] = pBuf[kk + (MT_M - MT_N)] ^ (v >> 1) ^ mag[v & 1];
290 }
291 v = (pBuf[MT_N - 1] & MT_Upper_Mask) | (pBuf[0] & MT_Lower_Mask);
292 pBuf[MT_N - 1] = pBuf[MT_M - 1] ^ (v >> 1) ^ mag[v & 1];
293 mti = 0;
294 }
295 v = pBuf[mti++];
296 v ^= (v >> 11);
297 v ^= (v << 7) & 0x9d2c5680UL;
298 v ^= (v << 15) & 0xefc60000UL;
299 v ^= (v >> 18);
300 return v;
301 }
FX_Random_MT_Close(void * pContext)302 void FX_Random_MT_Close(void* pContext) {
303 FXSYS_assert(pContext);
304 FX_Free(pContext);
305 }
FX_Random_GenerateMT(FX_DWORD * pBuffer,int32_t iCount)306 void FX_Random_GenerateMT(FX_DWORD* pBuffer, int32_t iCount) {
307 FX_DWORD dwSeed;
308 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
309 if (!FX_GenerateCryptoRandom(&dwSeed, 1)) {
310 FX_Random_GenerateBase(&dwSeed, 1);
311 }
312 #else
313 FX_Random_GenerateBase(&dwSeed, 1);
314 #endif
315 void* pContext = FX_Random_MT_Start(dwSeed);
316 while (iCount-- > 0) {
317 *pBuffer++ = FX_Random_MT_Generate(pContext);
318 }
319 FX_Random_MT_Close(pContext);
320 }
FX_Random_GenerateBase(FX_DWORD * pBuffer,int32_t iCount)321 void FX_Random_GenerateBase(FX_DWORD* pBuffer, int32_t iCount) {
322 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
323 SYSTEMTIME st1, st2;
324 ::GetSystemTime(&st1);
325 do {
326 ::GetSystemTime(&st2);
327 } while (FXSYS_memcmp(&st1, &st2, sizeof(SYSTEMTIME)) == 0);
328 FX_DWORD dwHash1 =
329 FX_HashCode_String_GetA((const FX_CHAR*)&st1, sizeof(st1), TRUE);
330 FX_DWORD dwHash2 =
331 FX_HashCode_String_GetA((const FX_CHAR*)&st2, sizeof(st2), TRUE);
332 ::srand((dwHash1 << 16) | (FX_DWORD)dwHash2);
333 #else
334 time_t tmLast = time(NULL), tmCur;
335 while ((tmCur = time(NULL)) == tmLast)
336 ;
337 ::srand((tmCur << 16) | (tmLast & 0xFFFF));
338 #endif
339 while (iCount-- > 0) {
340 *pBuffer++ = (FX_DWORD)((::rand() << 16) | (::rand() & 0xFFFF));
341 }
342 }
343 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
FX_GenerateCryptoRandom(FX_DWORD * pBuffer,int32_t iCount)344 FX_BOOL FX_GenerateCryptoRandom(FX_DWORD* pBuffer, int32_t iCount) {
345 HCRYPTPROV hCP = NULL;
346 if (!::CryptAcquireContext(&hCP, NULL, NULL, PROV_RSA_FULL, 0) || !hCP) {
347 return FALSE;
348 }
349 ::CryptGenRandom(hCP, iCount * sizeof(FX_DWORD), (uint8_t*)pBuffer);
350 ::CryptReleaseContext(hCP, 0);
351 return TRUE;
352 }
353 #endif
FX_Random_GenerateCrypto(FX_DWORD * pBuffer,int32_t iCount)354 void FX_Random_GenerateCrypto(FX_DWORD* pBuffer, int32_t iCount) {
355 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
356 FX_GenerateCryptoRandom(pBuffer, iCount);
357 #else
358 FX_Random_GenerateBase(pBuffer, iCount);
359 #endif
360 }
361
362 #ifdef PDF_ENABLE_XFA
FX_GUID_CreateV4(FX_LPGUID pGUID)363 void FX_GUID_CreateV4(FX_LPGUID pGUID) {
364 #if (_FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || \
365 _FX_OS_ == _FX_WIN64_)
366 #ifdef _FX_WINAPI_PARTITION_DESKTOP_
367 if (!FX_GenerateCryptoRandom((FX_DWORD*)pGUID, 4)) {
368 FX_Random_GenerateMT((FX_DWORD*)pGUID, 4);
369 }
370 #else
371 FX_Random_GenerateMT((FX_DWORD*)pGUID, 4);
372 #endif
373 #else
374 FX_Random_GenerateMT((FX_DWORD*)pGUID, 4);
375 #endif
376 uint8_t& b = ((uint8_t*)pGUID)[6];
377 b = (b & 0x0F) | 0x40;
378 }
379 const FX_CHAR* gs_FX_pHexChars = "0123456789ABCDEF";
FX_GUID_ToString(FX_LPCGUID pGUID,CFX_ByteString & bsStr,FX_BOOL bSeparator)380 void FX_GUID_ToString(FX_LPCGUID pGUID,
381 CFX_ByteString& bsStr,
382 FX_BOOL bSeparator) {
383 FX_CHAR* pBuf = bsStr.GetBuffer(40);
384 uint8_t b;
385 for (int32_t i = 0; i < 16; i++) {
386 b = ((const uint8_t*)pGUID)[i];
387 *pBuf++ = gs_FX_pHexChars[b >> 4];
388 *pBuf++ = gs_FX_pHexChars[b & 0x0F];
389 if (bSeparator && (i == 3 || i == 5 || i == 7 || i == 9)) {
390 *pBuf++ = L'-';
391 }
392 }
393 bsStr.ReleaseBuffer(bSeparator ? 36 : 32);
394 }
395 #endif // PDF_ENABLE_XFA
396