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/fxcrt/extension.h"
8
9 #include <algorithm>
10 #include <memory>
11 #include <utility>
12
13 #include "core/fxcrt/fx_basic.h"
14 #include "core/fxcrt/fx_ext.h"
15
16 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
17 #include <wincrypt.h>
18 #else
19 #include <ctime>
20 #endif
21
22 namespace {
23
24 #ifdef PDF_ENABLE_XFA
25
26 class CFX_CRTFileAccess : public IFX_FileAccess {
27 public:
28 template <typename T, typename... Args>
29 friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args);
30
31 // IFX_FileAccess
32 void GetPath(CFX_WideString& wsPath) override;
33 CFX_RetainPtr<IFX_SeekableStream> CreateFileStream(uint32_t dwModes) override;
34
35 bool Init(const CFX_WideStringC& wsPath);
36
37 private:
38 CFX_CRTFileAccess();
39 ~CFX_CRTFileAccess() override;
40
41 CFX_WideString m_path;
42 };
43
CFX_CRTFileAccess()44 CFX_CRTFileAccess::CFX_CRTFileAccess() {}
45
~CFX_CRTFileAccess()46 CFX_CRTFileAccess::~CFX_CRTFileAccess() {}
47
GetPath(CFX_WideString & wsPath)48 void CFX_CRTFileAccess::GetPath(CFX_WideString& wsPath) {
49 wsPath = m_path;
50 }
51
CreateFileStream(uint32_t dwModes)52 CFX_RetainPtr<IFX_SeekableStream> CFX_CRTFileAccess::CreateFileStream(
53 uint32_t dwModes) {
54 return IFX_SeekableStream::CreateFromFilename(m_path.c_str(), dwModes);
55 }
56
Init(const CFX_WideStringC & wsPath)57 bool CFX_CRTFileAccess::Init(const CFX_WideStringC& wsPath) {
58 m_path = wsPath;
59 return true;
60 }
61
62 #endif // PDF_ENABLE_XFA
63
64 class CFX_CRTFileStream final : public IFX_SeekableStream {
65 public:
66 template <typename T, typename... Args>
67 friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args);
68
69 // IFX_SeekableStream:
70 FX_FILESIZE GetSize() override;
71 bool IsEOF() override;
72 FX_FILESIZE GetPosition() override;
73 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
74 size_t ReadBlock(void* buffer, size_t size) override;
75 bool WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) override;
76 bool Flush() override;
77
78 private:
79 explicit CFX_CRTFileStream(std::unique_ptr<IFXCRT_FileAccess> pFA);
80 ~CFX_CRTFileStream() override;
81
82 std::unique_ptr<IFXCRT_FileAccess> m_pFile;
83 };
84
CFX_CRTFileStream(std::unique_ptr<IFXCRT_FileAccess> pFA)85 CFX_CRTFileStream::CFX_CRTFileStream(std::unique_ptr<IFXCRT_FileAccess> pFA)
86 : m_pFile(std::move(pFA)) {}
87
~CFX_CRTFileStream()88 CFX_CRTFileStream::~CFX_CRTFileStream() {}
89
GetSize()90 FX_FILESIZE CFX_CRTFileStream::GetSize() {
91 return m_pFile->GetSize();
92 }
93
IsEOF()94 bool CFX_CRTFileStream::IsEOF() {
95 return GetPosition() >= GetSize();
96 }
97
GetPosition()98 FX_FILESIZE CFX_CRTFileStream::GetPosition() {
99 return m_pFile->GetPosition();
100 }
101
ReadBlock(void * buffer,FX_FILESIZE offset,size_t size)102 bool CFX_CRTFileStream::ReadBlock(void* buffer,
103 FX_FILESIZE offset,
104 size_t size) {
105 return m_pFile->ReadPos(buffer, size, offset) > 0;
106 }
107
ReadBlock(void * buffer,size_t size)108 size_t CFX_CRTFileStream::ReadBlock(void* buffer, size_t size) {
109 return m_pFile->Read(buffer, size);
110 }
111
WriteBlock(const void * buffer,FX_FILESIZE offset,size_t size)112 bool CFX_CRTFileStream::WriteBlock(const void* buffer,
113 FX_FILESIZE offset,
114 size_t size) {
115 return !!m_pFile->WritePos(buffer, size, offset);
116 }
117
Flush()118 bool CFX_CRTFileStream::Flush() {
119 return m_pFile->Flush();
120 }
121
122 #define FX_MEMSTREAM_BlockSize (64 * 1024)
123 #define FX_MEMSTREAM_Consecutive 0x01
124 #define FX_MEMSTREAM_TakeOver 0x02
125
126 class CFX_MemoryStream final : public IFX_MemoryStream {
127 public:
128 template <typename T, typename... Args>
129 friend CFX_RetainPtr<T> pdfium::MakeRetain(Args&&... args);
130
131 // IFX_MemoryStream
132 FX_FILESIZE GetSize() override;
133 bool IsEOF() override;
134 FX_FILESIZE GetPosition() override;
135 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
136 size_t ReadBlock(void* buffer, size_t size) override;
137 bool WriteBlock(const void* buffer, FX_FILESIZE offset, size_t size) override;
138 bool Flush() override;
139 bool IsConsecutive() const override;
140 void EstimateSize(size_t nInitSize, size_t nGrowSize) override;
141 uint8_t* GetBuffer() const override;
142 void AttachBuffer(uint8_t* pBuffer,
143 size_t nSize,
144 bool bTakeOver = false) override;
145 void DetachBuffer() override;
146
147 private:
148 explicit CFX_MemoryStream(bool bConsecutive);
149 CFX_MemoryStream(uint8_t* pBuffer, size_t nSize, bool bTakeOver);
150 ~CFX_MemoryStream() override;
151
152 bool ExpandBlocks(size_t size);
153
154 CFX_ArrayTemplate<uint8_t*> m_Blocks;
155 size_t m_nTotalSize;
156 size_t m_nCurSize;
157 size_t m_nCurPos;
158 size_t m_nGrowSize;
159 uint32_t m_dwFlags;
160 };
161
CFX_MemoryStream(bool bConsecutive)162 CFX_MemoryStream::CFX_MemoryStream(bool bConsecutive)
163 : m_nTotalSize(0),
164 m_nCurSize(0),
165 m_nCurPos(0),
166 m_nGrowSize(FX_MEMSTREAM_BlockSize) {
167 m_dwFlags =
168 FX_MEMSTREAM_TakeOver | (bConsecutive ? FX_MEMSTREAM_Consecutive : 0);
169 }
170
CFX_MemoryStream(uint8_t * pBuffer,size_t nSize,bool bTakeOver)171 CFX_MemoryStream::CFX_MemoryStream(uint8_t* pBuffer,
172 size_t nSize,
173 bool bTakeOver)
174 : m_nTotalSize(nSize),
175 m_nCurSize(nSize),
176 m_nCurPos(0),
177 m_nGrowSize(FX_MEMSTREAM_BlockSize) {
178 m_Blocks.Add(pBuffer);
179 m_dwFlags =
180 FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
181 }
182
~CFX_MemoryStream()183 CFX_MemoryStream::~CFX_MemoryStream() {
184 if (m_dwFlags & FX_MEMSTREAM_TakeOver) {
185 for (int32_t i = 0; i < m_Blocks.GetSize(); i++) {
186 FX_Free(m_Blocks[i]);
187 }
188 }
189 m_Blocks.RemoveAll();
190 }
191
GetSize()192 FX_FILESIZE CFX_MemoryStream::GetSize() {
193 return (FX_FILESIZE)m_nCurSize;
194 }
195
IsEOF()196 bool CFX_MemoryStream::IsEOF() {
197 return m_nCurPos >= (size_t)GetSize();
198 }
199
GetPosition()200 FX_FILESIZE CFX_MemoryStream::GetPosition() {
201 return (FX_FILESIZE)m_nCurPos;
202 }
203
ReadBlock(void * buffer,FX_FILESIZE offset,size_t size)204 bool CFX_MemoryStream::ReadBlock(void* buffer,
205 FX_FILESIZE offset,
206 size_t size) {
207 if (!buffer || !size || offset < 0)
208 return false;
209
210 FX_SAFE_SIZE_T newPos = size;
211 newPos += offset;
212 if (!newPos.IsValid() || newPos.ValueOrDefault(0) == 0 ||
213 newPos.ValueOrDie() > m_nCurSize) {
214 return false;
215 }
216
217 m_nCurPos = newPos.ValueOrDie();
218 if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
219 FXSYS_memcpy(buffer, m_Blocks[0] + (size_t)offset, size);
220 return true;
221 }
222 size_t nStartBlock = (size_t)offset / m_nGrowSize;
223 offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
224 while (size) {
225 size_t nRead = m_nGrowSize - (size_t)offset;
226 if (nRead > size) {
227 nRead = size;
228 }
229 FXSYS_memcpy(buffer, m_Blocks[(int)nStartBlock] + (size_t)offset, nRead);
230 buffer = ((uint8_t*)buffer) + nRead;
231 size -= nRead;
232 nStartBlock++;
233 offset = 0;
234 }
235 return true;
236 }
237
ReadBlock(void * buffer,size_t size)238 size_t CFX_MemoryStream::ReadBlock(void* buffer, size_t size) {
239 if (m_nCurPos >= m_nCurSize) {
240 return 0;
241 }
242 size_t nRead = std::min(size, m_nCurSize - m_nCurPos);
243 if (!ReadBlock(buffer, (int32_t)m_nCurPos, nRead)) {
244 return 0;
245 }
246 return nRead;
247 }
248
WriteBlock(const void * buffer,FX_FILESIZE offset,size_t size)249 bool CFX_MemoryStream::WriteBlock(const void* buffer,
250 FX_FILESIZE offset,
251 size_t size) {
252 if (!buffer || !size)
253 return false;
254
255 if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
256 FX_SAFE_SIZE_T newPos = size;
257 newPos += offset;
258 if (!newPos.IsValid())
259 return false;
260
261 m_nCurPos = newPos.ValueOrDie();
262 if (m_nCurPos > m_nTotalSize) {
263 m_nTotalSize = (m_nCurPos + m_nGrowSize - 1) / m_nGrowSize * m_nGrowSize;
264 if (m_Blocks.GetSize() < 1) {
265 uint8_t* block = FX_Alloc(uint8_t, m_nTotalSize);
266 m_Blocks.Add(block);
267 } else {
268 m_Blocks[0] = FX_Realloc(uint8_t, m_Blocks[0], m_nTotalSize);
269 }
270 if (!m_Blocks[0]) {
271 m_Blocks.RemoveAll();
272 return false;
273 }
274 }
275 FXSYS_memcpy(m_Blocks[0] + (size_t)offset, buffer, size);
276 if (m_nCurSize < m_nCurPos) {
277 m_nCurSize = m_nCurPos;
278 }
279 return true;
280 }
281
282 FX_SAFE_SIZE_T newPos = size;
283 newPos += offset;
284 if (!newPos.IsValid()) {
285 return false;
286 }
287
288 if (!ExpandBlocks(newPos.ValueOrDie())) {
289 return false;
290 }
291 m_nCurPos = newPos.ValueOrDie();
292 size_t nStartBlock = (size_t)offset / m_nGrowSize;
293 offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
294 while (size) {
295 size_t nWrite = m_nGrowSize - (size_t)offset;
296 if (nWrite > size) {
297 nWrite = size;
298 }
299 FXSYS_memcpy(m_Blocks[(int)nStartBlock] + (size_t)offset, buffer, nWrite);
300 buffer = ((uint8_t*)buffer) + nWrite;
301 size -= nWrite;
302 nStartBlock++;
303 offset = 0;
304 }
305 return true;
306 }
307
Flush()308 bool CFX_MemoryStream::Flush() {
309 return true;
310 }
311
IsConsecutive() const312 bool CFX_MemoryStream::IsConsecutive() const {
313 return !!(m_dwFlags & FX_MEMSTREAM_Consecutive);
314 }
315
EstimateSize(size_t nInitSize,size_t nGrowSize)316 void CFX_MemoryStream::EstimateSize(size_t nInitSize, size_t nGrowSize) {
317 if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
318 if (m_Blocks.GetSize() < 1) {
319 uint8_t* pBlock =
320 FX_Alloc(uint8_t, std::max(nInitSize, static_cast<size_t>(4096)));
321 m_Blocks.Add(pBlock);
322 }
323 m_nGrowSize = std::max(nGrowSize, static_cast<size_t>(4096));
324 } else if (m_Blocks.GetSize() < 1) {
325 m_nGrowSize = std::max(nGrowSize, static_cast<size_t>(4096));
326 }
327 }
328
GetBuffer() const329 uint8_t* CFX_MemoryStream::GetBuffer() const {
330 return m_Blocks.GetSize() ? m_Blocks[0] : nullptr;
331 }
332
AttachBuffer(uint8_t * pBuffer,size_t nSize,bool bTakeOver)333 void CFX_MemoryStream::AttachBuffer(uint8_t* pBuffer,
334 size_t nSize,
335 bool bTakeOver) {
336 if (!(m_dwFlags & FX_MEMSTREAM_Consecutive))
337 return;
338
339 m_Blocks.RemoveAll();
340 m_Blocks.Add(pBuffer);
341 m_nTotalSize = m_nCurSize = nSize;
342 m_nCurPos = 0;
343 m_dwFlags =
344 FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
345 }
346
DetachBuffer()347 void CFX_MemoryStream::DetachBuffer() {
348 if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) {
349 return;
350 }
351 m_Blocks.RemoveAll();
352 m_nTotalSize = m_nCurSize = m_nCurPos = 0;
353 m_dwFlags = FX_MEMSTREAM_TakeOver;
354 }
355
ExpandBlocks(size_t size)356 bool CFX_MemoryStream::ExpandBlocks(size_t size) {
357 if (m_nCurSize < size) {
358 m_nCurSize = size;
359 }
360 if (size <= m_nTotalSize) {
361 return true;
362 }
363 int32_t iCount = m_Blocks.GetSize();
364 size = (size - m_nTotalSize + m_nGrowSize - 1) / m_nGrowSize;
365 m_Blocks.SetSize(m_Blocks.GetSize() + (int32_t)size);
366 while (size--) {
367 uint8_t* pBlock = FX_Alloc(uint8_t, m_nGrowSize);
368 m_Blocks.SetAt(iCount++, pBlock);
369 m_nTotalSize += m_nGrowSize;
370 }
371 return true;
372 }
373
374 } // namespace
375
376 #ifdef PDF_ENABLE_XFA
CreateDefault(const CFX_WideStringC & wsPath)377 CFX_RetainPtr<IFX_FileAccess> IFX_FileAccess::CreateDefault(
378 const CFX_WideStringC& wsPath) {
379 if (wsPath.GetLength() == 0)
380 return nullptr;
381
382 auto pFA = pdfium::MakeRetain<CFX_CRTFileAccess>();
383 pFA->Init(wsPath);
384 return pFA;
385 }
386 #endif // PDF_ENABLE_XFA
387
388 // static
CreateFromFilename(const FX_CHAR * filename,uint32_t dwModes)389 CFX_RetainPtr<IFX_SeekableStream> IFX_SeekableStream::CreateFromFilename(
390 const FX_CHAR* filename,
391 uint32_t dwModes) {
392 std::unique_ptr<IFXCRT_FileAccess> pFA(IFXCRT_FileAccess::Create());
393 if (!pFA->Open(filename, dwModes))
394 return nullptr;
395 return pdfium::MakeRetain<CFX_CRTFileStream>(std::move(pFA));
396 }
397
398 // static
CreateFromFilename(const FX_WCHAR * filename,uint32_t dwModes)399 CFX_RetainPtr<IFX_SeekableStream> IFX_SeekableStream::CreateFromFilename(
400 const FX_WCHAR* filename,
401 uint32_t dwModes) {
402 std::unique_ptr<IFXCRT_FileAccess> pFA(IFXCRT_FileAccess::Create());
403 if (!pFA->Open(filename, dwModes))
404 return nullptr;
405 return pdfium::MakeRetain<CFX_CRTFileStream>(std::move(pFA));
406 }
407
408 // static
409 CFX_RetainPtr<IFX_SeekableReadStream>
CreateFromFilename(const FX_CHAR * filename)410 IFX_SeekableReadStream::CreateFromFilename(const FX_CHAR* filename) {
411 return IFX_SeekableStream::CreateFromFilename(filename, FX_FILEMODE_ReadOnly);
412 }
413
414 // static
Create(uint8_t * pBuffer,size_t dwSize,bool bTakeOver)415 CFX_RetainPtr<IFX_MemoryStream> IFX_MemoryStream::Create(uint8_t* pBuffer,
416 size_t dwSize,
417 bool bTakeOver) {
418 return pdfium::MakeRetain<CFX_MemoryStream>(pBuffer, dwSize, bTakeOver);
419 }
420
421 // static
Create(bool bConsecutive)422 CFX_RetainPtr<IFX_MemoryStream> IFX_MemoryStream::Create(bool bConsecutive) {
423 return pdfium::MakeRetain<CFX_MemoryStream>(bConsecutive);
424 }
425
FXSYS_tan(FX_FLOAT a)426 FX_FLOAT FXSYS_tan(FX_FLOAT a) {
427 return (FX_FLOAT)tan(a);
428 }
FXSYS_logb(FX_FLOAT b,FX_FLOAT x)429 FX_FLOAT FXSYS_logb(FX_FLOAT b, FX_FLOAT x) {
430 return FXSYS_log(x) / FXSYS_log(b);
431 }
FXSYS_strtof(const FX_CHAR * pcsStr,int32_t iLength,int32_t * pUsedLen)432 FX_FLOAT FXSYS_strtof(const FX_CHAR* pcsStr,
433 int32_t iLength,
434 int32_t* pUsedLen) {
435 ASSERT(pcsStr);
436 if (iLength < 0) {
437 iLength = (int32_t)FXSYS_strlen(pcsStr);
438 }
439 CFX_WideString ws =
440 CFX_WideString::FromLocal(CFX_ByteStringC(pcsStr, iLength));
441 return FXSYS_wcstof(ws.c_str(), iLength, pUsedLen);
442 }
FXSYS_wcstof(const FX_WCHAR * pwsStr,int32_t iLength,int32_t * pUsedLen)443 FX_FLOAT FXSYS_wcstof(const FX_WCHAR* pwsStr,
444 int32_t iLength,
445 int32_t* pUsedLen) {
446 ASSERT(pwsStr);
447 if (iLength < 0) {
448 iLength = (int32_t)FXSYS_wcslen(pwsStr);
449 }
450 if (iLength == 0) {
451 return 0.0f;
452 }
453 int32_t iUsedLen = 0;
454 bool bNegtive = false;
455 switch (pwsStr[iUsedLen]) {
456 case '-':
457 bNegtive = true;
458 case '+':
459 iUsedLen++;
460 break;
461 }
462 FX_FLOAT fValue = 0.0f;
463 while (iUsedLen < iLength) {
464 FX_WCHAR wch = pwsStr[iUsedLen];
465 if (wch >= L'0' && wch <= L'9') {
466 fValue = fValue * 10.0f + (wch - L'0');
467 } else {
468 break;
469 }
470 iUsedLen++;
471 }
472 if (iUsedLen < iLength && pwsStr[iUsedLen] == L'.') {
473 FX_FLOAT fPrecise = 0.1f;
474 while (++iUsedLen < iLength) {
475 FX_WCHAR wch = pwsStr[iUsedLen];
476 if (wch >= L'0' && wch <= L'9') {
477 fValue += (wch - L'0') * fPrecise;
478 fPrecise *= 0.1f;
479 } else {
480 break;
481 }
482 }
483 }
484 if (pUsedLen) {
485 *pUsedLen = iUsedLen;
486 }
487 return bNegtive ? -fValue : fValue;
488 }
FXSYS_wcsncpy(FX_WCHAR * dstStr,const FX_WCHAR * srcStr,size_t count)489 FX_WCHAR* FXSYS_wcsncpy(FX_WCHAR* dstStr,
490 const FX_WCHAR* srcStr,
491 size_t count) {
492 ASSERT(dstStr && srcStr && count > 0);
493 for (size_t i = 0; i < count; ++i)
494 if ((dstStr[i] = srcStr[i]) == L'\0') {
495 break;
496 }
497 return dstStr;
498 }
FXSYS_wcsnicmp(const FX_WCHAR * s1,const FX_WCHAR * s2,size_t count)499 int32_t FXSYS_wcsnicmp(const FX_WCHAR* s1, const FX_WCHAR* s2, size_t count) {
500 ASSERT(s1 && s2 && count > 0);
501 FX_WCHAR wch1 = 0, wch2 = 0;
502 while (count-- > 0) {
503 wch1 = (FX_WCHAR)FXSYS_tolower(*s1++);
504 wch2 = (FX_WCHAR)FXSYS_tolower(*s2++);
505 if (wch1 != wch2) {
506 break;
507 }
508 }
509 return wch1 - wch2;
510 }
FXSYS_strnicmp(const FX_CHAR * s1,const FX_CHAR * s2,size_t count)511 int32_t FXSYS_strnicmp(const FX_CHAR* s1, const FX_CHAR* s2, size_t count) {
512 ASSERT(s1 && s2 && count > 0);
513 FX_CHAR ch1 = 0, ch2 = 0;
514 while (count-- > 0) {
515 ch1 = (FX_CHAR)FXSYS_tolower(*s1++);
516 ch2 = (FX_CHAR)FXSYS_tolower(*s2++);
517 if (ch1 != ch2) {
518 break;
519 }
520 }
521 return ch1 - ch2;
522 }
523
FX_HashCode_GetA(const CFX_ByteStringC & str,bool bIgnoreCase)524 uint32_t FX_HashCode_GetA(const CFX_ByteStringC& str, bool bIgnoreCase) {
525 uint32_t dwHashCode = 0;
526 if (bIgnoreCase) {
527 for (FX_STRSIZE i = 0; i < str.GetLength(); ++i)
528 dwHashCode = 31 * dwHashCode + FXSYS_tolower(str.CharAt(i));
529 } else {
530 for (FX_STRSIZE i = 0; i < str.GetLength(); ++i)
531 dwHashCode = 31 * dwHashCode + str.CharAt(i);
532 }
533 return dwHashCode;
534 }
535
FX_HashCode_GetW(const CFX_WideStringC & str,bool bIgnoreCase)536 uint32_t FX_HashCode_GetW(const CFX_WideStringC& str, bool bIgnoreCase) {
537 uint32_t dwHashCode = 0;
538 if (bIgnoreCase) {
539 for (FX_STRSIZE i = 0; i < str.GetLength(); ++i)
540 dwHashCode = 1313 * dwHashCode + FXSYS_tolower(str.CharAt(i));
541 } else {
542 for (FX_STRSIZE i = 0; i < str.GetLength(); ++i)
543 dwHashCode = 1313 * dwHashCode + str.CharAt(i);
544 }
545 return dwHashCode;
546 }
547
FX_Random_MT_Start(uint32_t dwSeed)548 void* FX_Random_MT_Start(uint32_t dwSeed) {
549 FX_MTRANDOMCONTEXT* pContext = FX_Alloc(FX_MTRANDOMCONTEXT, 1);
550 pContext->mt[0] = dwSeed;
551 uint32_t& i = pContext->mti;
552 uint32_t* pBuf = pContext->mt;
553 for (i = 1; i < MT_N; i++) {
554 pBuf[i] = (1812433253UL * (pBuf[i - 1] ^ (pBuf[i - 1] >> 30)) + i);
555 }
556 pContext->bHaveSeed = true;
557 return pContext;
558 }
FX_Random_MT_Generate(void * pContext)559 uint32_t FX_Random_MT_Generate(void* pContext) {
560 ASSERT(pContext);
561 FX_MTRANDOMCONTEXT* pMTC = static_cast<FX_MTRANDOMCONTEXT*>(pContext);
562 uint32_t v;
563 static uint32_t mag[2] = {0, MT_Matrix_A};
564 uint32_t& mti = pMTC->mti;
565 uint32_t* pBuf = pMTC->mt;
566 if ((int)mti < 0 || mti >= MT_N) {
567 if (mti > MT_N && !pMTC->bHaveSeed) {
568 return 0;
569 }
570 uint32_t kk;
571 for (kk = 0; kk < MT_N - MT_M; kk++) {
572 v = (pBuf[kk] & MT_Upper_Mask) | (pBuf[kk + 1] & MT_Lower_Mask);
573 pBuf[kk] = pBuf[kk + MT_M] ^ (v >> 1) ^ mag[v & 1];
574 }
575 for (; kk < MT_N - 1; kk++) {
576 v = (pBuf[kk] & MT_Upper_Mask) | (pBuf[kk + 1] & MT_Lower_Mask);
577 pBuf[kk] = pBuf[kk + (MT_M - MT_N)] ^ (v >> 1) ^ mag[v & 1];
578 }
579 v = (pBuf[MT_N - 1] & MT_Upper_Mask) | (pBuf[0] & MT_Lower_Mask);
580 pBuf[MT_N - 1] = pBuf[MT_M - 1] ^ (v >> 1) ^ mag[v & 1];
581 mti = 0;
582 }
583 v = pBuf[mti++];
584 v ^= (v >> 11);
585 v ^= (v << 7) & 0x9d2c5680UL;
586 v ^= (v << 15) & 0xefc60000UL;
587 v ^= (v >> 18);
588 return v;
589 }
FX_Random_MT_Close(void * pContext)590 void FX_Random_MT_Close(void* pContext) {
591 ASSERT(pContext);
592 FX_Free(pContext);
593 }
FX_Random_GenerateMT(uint32_t * pBuffer,int32_t iCount)594 void FX_Random_GenerateMT(uint32_t* pBuffer, int32_t iCount) {
595 uint32_t dwSeed;
596 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
597 if (!FX_GenerateCryptoRandom(&dwSeed, 1)) {
598 FX_Random_GenerateBase(&dwSeed, 1);
599 }
600 #else
601 FX_Random_GenerateBase(&dwSeed, 1);
602 #endif
603 void* pContext = FX_Random_MT_Start(dwSeed);
604 while (iCount-- > 0) {
605 *pBuffer++ = FX_Random_MT_Generate(pContext);
606 }
607 FX_Random_MT_Close(pContext);
608 }
FX_Random_GenerateBase(uint32_t * pBuffer,int32_t iCount)609 void FX_Random_GenerateBase(uint32_t* pBuffer, int32_t iCount) {
610 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
611 SYSTEMTIME st1, st2;
612 ::GetSystemTime(&st1);
613 do {
614 ::GetSystemTime(&st2);
615 } while (FXSYS_memcmp(&st1, &st2, sizeof(SYSTEMTIME)) == 0);
616 uint32_t dwHash1 =
617 FX_HashCode_GetA(CFX_ByteStringC((uint8_t*)&st1, sizeof(st1)), true);
618 uint32_t dwHash2 =
619 FX_HashCode_GetA(CFX_ByteStringC((uint8_t*)&st2, sizeof(st2)), true);
620 ::srand((dwHash1 << 16) | (uint32_t)dwHash2);
621 #else
622 time_t tmLast = time(nullptr);
623 time_t tmCur;
624 while ((tmCur = time(nullptr)) == tmLast) {
625 continue;
626 }
627
628 ::srand((tmCur << 16) | (tmLast & 0xFFFF));
629 #endif
630 while (iCount-- > 0) {
631 *pBuffer++ = (uint32_t)((::rand() << 16) | (::rand() & 0xFFFF));
632 }
633 }
634 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
FX_GenerateCryptoRandom(uint32_t * pBuffer,int32_t iCount)635 bool FX_GenerateCryptoRandom(uint32_t* pBuffer, int32_t iCount) {
636 HCRYPTPROV hCP = 0;
637 if (!::CryptAcquireContext(&hCP, nullptr, nullptr, PROV_RSA_FULL, 0) ||
638 !hCP) {
639 return false;
640 }
641 ::CryptGenRandom(hCP, iCount * sizeof(uint32_t), (uint8_t*)pBuffer);
642 ::CryptReleaseContext(hCP, 0);
643 return true;
644 }
645 #endif
FX_Random_GenerateCrypto(uint32_t * pBuffer,int32_t iCount)646 void FX_Random_GenerateCrypto(uint32_t* pBuffer, int32_t iCount) {
647 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
648 FX_GenerateCryptoRandom(pBuffer, iCount);
649 #else
650 FX_Random_GenerateBase(pBuffer, iCount);
651 #endif
652 }
653
654 #ifdef PDF_ENABLE_XFA
655 static const FX_CHAR gs_FX_pHexChars[] = "0123456789ABCDEF";
FX_GUID_CreateV4(FX_GUID * pGUID)656 void FX_GUID_CreateV4(FX_GUID* pGUID) {
657 FX_Random_GenerateMT((uint32_t*)pGUID, 4);
658 uint8_t& b = ((uint8_t*)pGUID)[6];
659 b = (b & 0x0F) | 0x40;
660 }
FX_GUID_ToString(const FX_GUID * pGUID,CFX_ByteString & bsStr,bool bSeparator)661 void FX_GUID_ToString(const FX_GUID* pGUID,
662 CFX_ByteString& bsStr,
663 bool bSeparator) {
664 FX_CHAR* pBuf = bsStr.GetBuffer(40);
665 uint8_t b;
666 for (int32_t i = 0; i < 16; i++) {
667 b = ((const uint8_t*)pGUID)[i];
668 *pBuf++ = gs_FX_pHexChars[b >> 4];
669 *pBuf++ = gs_FX_pHexChars[b & 0x0F];
670 if (bSeparator && (i == 3 || i == 5 || i == 7 || i == 9)) {
671 *pBuf++ = L'-';
672 }
673 }
674 bsStr.ReleaseBuffer(bSeparator ? 36 : 32);
675 }
676 #endif // PDF_ENABLE_XFA
677