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 #ifndef CORE_SRC_FXCRT_EXTENSION_H_
8 #define CORE_SRC_FXCRT_EXTENSION_H_
9 
10 #include <algorithm>
11 
12 #include "core/include/fxcrt/fx_basic.h"
13 #include "core/include/fxcrt/fx_safe_types.h"
14 
15 class IFXCRT_FileAccess {
16  public:
~IFXCRT_FileAccess()17   virtual ~IFXCRT_FileAccess() {}
18   virtual FX_BOOL Open(const CFX_ByteStringC& fileName, FX_DWORD dwMode) = 0;
19   virtual FX_BOOL Open(const CFX_WideStringC& fileName, FX_DWORD dwMode) = 0;
20   virtual void Close() = 0;
21   virtual void Release() = 0;
22   virtual FX_FILESIZE GetSize() const = 0;
23   virtual FX_FILESIZE GetPosition() const = 0;
24   virtual FX_FILESIZE SetPosition(FX_FILESIZE pos) = 0;
25   virtual size_t Read(void* pBuffer, size_t szBuffer) = 0;
26   virtual size_t Write(const void* pBuffer, size_t szBuffer) = 0;
27   virtual size_t ReadPos(void* pBuffer, size_t szBuffer, FX_FILESIZE pos) = 0;
28   virtual size_t WritePos(const void* pBuffer,
29                           size_t szBuffer,
30                           FX_FILESIZE pos) = 0;
31   virtual FX_BOOL Flush() = 0;
32   virtual FX_BOOL Truncate(FX_FILESIZE szFile) = 0;
33 };
34 IFXCRT_FileAccess* FXCRT_FileAccess_Create();
35 
36 #ifdef PDF_ENABLE_XFA
37 class CFX_CRTFileAccess : public IFX_FileAccess {
38  public:
CFX_CRTFileAccess()39   CFX_CRTFileAccess() : m_RefCount(0) {}
40 
41   // IFX_FileAccess
Release()42   void Release() override {
43     if (--m_RefCount == 0)
44       delete this;
45   }
46 
Retain()47   IFX_FileAccess* Retain() override {
48     m_RefCount++;
49     return (IFX_FileAccess*)this;
50   }
51 
GetPath(CFX_WideString & wsPath)52   void GetPath(CFX_WideString& wsPath) override { wsPath = m_path; }
53 
CreateFileStream(FX_DWORD dwModes)54   IFX_FileStream* CreateFileStream(FX_DWORD dwModes) override {
55     return FX_CreateFileStream(m_path, dwModes);
56   }
57 
Init(const CFX_WideStringC & wsPath)58   FX_BOOL Init(const CFX_WideStringC& wsPath) {
59     m_path = wsPath;
60     m_RefCount = 1;
61     return TRUE;
62   }
63 
64  protected:
65   CFX_WideString m_path;
66   FX_DWORD m_RefCount;
67 };
68 #endif  // PDF_ENABLE_XFA
69 
70 class CFX_CRTFileStream final : public IFX_FileStream {
71  public:
72   explicit CFX_CRTFileStream(IFXCRT_FileAccess* pFA);
73   ~CFX_CRTFileStream() override;
74 
75   // IFX_FileStream:
76   IFX_FileStream* Retain() override;
77   void Release() override;
78   FX_FILESIZE GetSize() override;
79   FX_BOOL IsEOF() override;
80   FX_FILESIZE GetPosition() override;
81   FX_BOOL ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override;
82   size_t ReadBlock(void* buffer, size_t size) override;
83   FX_BOOL WriteBlock(const void* buffer,
84                      FX_FILESIZE offset,
85                      size_t size) override;
86   FX_BOOL Flush() override;
87 
88  protected:
89   IFXCRT_FileAccess* m_pFile;
90   FX_DWORD m_dwCount;
91 };
92 
93 #define FX_MEMSTREAM_BlockSize (64 * 1024)
94 #define FX_MEMSTREAM_Consecutive 0x01
95 #define FX_MEMSTREAM_TakeOver 0x02
96 class CFX_MemoryStream final : public IFX_MemoryStream {
97  public:
CFX_MemoryStream(FX_BOOL bConsecutive)98   explicit CFX_MemoryStream(FX_BOOL bConsecutive)
99       : m_dwCount(1),
100         m_nTotalSize(0),
101         m_nCurSize(0),
102         m_nCurPos(0),
103         m_nGrowSize(FX_MEMSTREAM_BlockSize) {
104     m_dwFlags =
105         FX_MEMSTREAM_TakeOver | (bConsecutive ? FX_MEMSTREAM_Consecutive : 0);
106   }
CFX_MemoryStream(uint8_t * pBuffer,size_t nSize,FX_BOOL bTakeOver)107   CFX_MemoryStream(uint8_t* pBuffer, size_t nSize, FX_BOOL bTakeOver)
108       : m_dwCount(1),
109         m_nTotalSize(nSize),
110         m_nCurSize(nSize),
111         m_nCurPos(0),
112         m_nGrowSize(FX_MEMSTREAM_BlockSize) {
113     m_Blocks.Add(pBuffer);
114     m_dwFlags =
115         FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
116   }
~CFX_MemoryStream()117   ~CFX_MemoryStream() override {
118     if (m_dwFlags & FX_MEMSTREAM_TakeOver) {
119       for (int32_t i = 0; i < m_Blocks.GetSize(); i++) {
120         FX_Free(m_Blocks[i]);
121       }
122     }
123     m_Blocks.RemoveAll();
124   }
125 
126   // IFX_MemoryStream:
Retain()127   IFX_FileStream* Retain() override {
128     m_dwCount++;
129     return this;
130   }
Release()131   void Release() override {
132     FX_DWORD nCount = --m_dwCount;
133     if (nCount) {
134       return;
135     }
136     delete this;
137   }
GetSize()138   FX_FILESIZE GetSize() override { return (FX_FILESIZE)m_nCurSize; }
IsEOF()139   FX_BOOL IsEOF() override { return m_nCurPos >= (size_t)GetSize(); }
GetPosition()140   FX_FILESIZE GetPosition() override { return (FX_FILESIZE)m_nCurPos; }
ReadBlock(void * buffer,FX_FILESIZE offset,size_t size)141   FX_BOOL ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override {
142     if (!buffer || !size) {
143       return FALSE;
144     }
145 
146     FX_SAFE_SIZE_T newPos = size;
147     newPos += offset;
148     if (!newPos.IsValid() || newPos.ValueOrDefault(0) == 0 ||
149         newPos.ValueOrDie() > m_nCurSize) {
150       return FALSE;
151     }
152 
153     m_nCurPos = newPos.ValueOrDie();
154     if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
155       FXSYS_memcpy(buffer, m_Blocks[0] + (size_t)offset, size);
156       return TRUE;
157     }
158     size_t nStartBlock = (size_t)offset / m_nGrowSize;
159     offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
160     while (size) {
161       size_t nRead = m_nGrowSize - (size_t)offset;
162       if (nRead > size) {
163         nRead = size;
164       }
165       FXSYS_memcpy(buffer, m_Blocks[(int)nStartBlock] + (size_t)offset, nRead);
166       buffer = ((uint8_t*)buffer) + nRead;
167       size -= nRead;
168       nStartBlock++;
169       offset = 0;
170     }
171     return TRUE;
172   }
ReadBlock(void * buffer,size_t size)173   size_t ReadBlock(void* buffer, size_t size) override {
174     if (m_nCurPos >= m_nCurSize) {
175       return 0;
176     }
177     size_t nRead = std::min(size, m_nCurSize - m_nCurPos);
178     if (!ReadBlock(buffer, (int32_t)m_nCurPos, nRead)) {
179       return 0;
180     }
181     return nRead;
182   }
WriteBlock(const void * buffer,FX_FILESIZE offset,size_t size)183   FX_BOOL WriteBlock(const void* buffer,
184                      FX_FILESIZE offset,
185                      size_t size) override {
186     if (!buffer || !size) {
187       return FALSE;
188     }
189     if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
190       FX_SAFE_SIZE_T newPos = size;
191       newPos += offset;
192       if (!newPos.IsValid())
193         return FALSE;
194 
195       m_nCurPos = newPos.ValueOrDie();
196       if (m_nCurPos > m_nTotalSize) {
197         m_nTotalSize =
198             (m_nCurPos + m_nGrowSize - 1) / m_nGrowSize * m_nGrowSize;
199         if (m_Blocks.GetSize() < 1) {
200           uint8_t* block = FX_Alloc(uint8_t, m_nTotalSize);
201           m_Blocks.Add(block);
202         } else {
203           m_Blocks[0] = FX_Realloc(uint8_t, m_Blocks[0], m_nTotalSize);
204         }
205         if (!m_Blocks[0]) {
206           m_Blocks.RemoveAll();
207           return FALSE;
208         }
209       }
210       FXSYS_memcpy(m_Blocks[0] + (size_t)offset, buffer, size);
211       if (m_nCurSize < m_nCurPos) {
212         m_nCurSize = m_nCurPos;
213       }
214       return TRUE;
215     }
216 
217     FX_SAFE_SIZE_T newPos = size;
218     newPos += offset;
219     if (!newPos.IsValid()) {
220       return FALSE;
221     }
222 
223     if (!ExpandBlocks(newPos.ValueOrDie())) {
224       return FALSE;
225     }
226     m_nCurPos = newPos.ValueOrDie();
227     size_t nStartBlock = (size_t)offset / m_nGrowSize;
228     offset -= (FX_FILESIZE)(nStartBlock * m_nGrowSize);
229     while (size) {
230       size_t nWrite = m_nGrowSize - (size_t)offset;
231       if (nWrite > size) {
232         nWrite = size;
233       }
234       FXSYS_memcpy(m_Blocks[(int)nStartBlock] + (size_t)offset, buffer, nWrite);
235       buffer = ((uint8_t*)buffer) + nWrite;
236       size -= nWrite;
237       nStartBlock++;
238       offset = 0;
239     }
240     return TRUE;
241   }
Flush()242   FX_BOOL Flush() override { return TRUE; }
IsConsecutive()243   FX_BOOL IsConsecutive() const override {
244     return m_dwFlags & FX_MEMSTREAM_Consecutive;
245   }
EstimateSize(size_t nInitSize,size_t nGrowSize)246   void EstimateSize(size_t nInitSize, size_t nGrowSize) override {
247     if (m_dwFlags & FX_MEMSTREAM_Consecutive) {
248       if (m_Blocks.GetSize() < 1) {
249         uint8_t* pBlock =
250             FX_Alloc(uint8_t, std::max(nInitSize, static_cast<size_t>(4096)));
251         m_Blocks.Add(pBlock);
252       }
253       m_nGrowSize = std::max(nGrowSize, static_cast<size_t>(4096));
254     } else if (m_Blocks.GetSize() < 1) {
255       m_nGrowSize = std::max(nGrowSize, static_cast<size_t>(4096));
256     }
257   }
GetBuffer()258   uint8_t* GetBuffer() const override {
259     return m_Blocks.GetSize() ? m_Blocks[0] : nullptr;
260   }
261   void AttachBuffer(uint8_t* pBuffer,
262                     size_t nSize,
263                     FX_BOOL bTakeOver = FALSE) override {
264     if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) {
265       return;
266     }
267     m_Blocks.RemoveAll();
268     m_Blocks.Add(pBuffer);
269     m_nTotalSize = m_nCurSize = nSize;
270     m_nCurPos = 0;
271     m_dwFlags =
272         FX_MEMSTREAM_Consecutive | (bTakeOver ? FX_MEMSTREAM_TakeOver : 0);
273   }
DetachBuffer()274   void DetachBuffer() override {
275     if (!(m_dwFlags & FX_MEMSTREAM_Consecutive)) {
276       return;
277     }
278     m_Blocks.RemoveAll();
279     m_nTotalSize = m_nCurSize = m_nCurPos = 0;
280     m_dwFlags = FX_MEMSTREAM_TakeOver;
281   }
282 
283  protected:
284   CFX_ArrayTemplate<uint8_t*> m_Blocks;
285   FX_DWORD m_dwCount;
286   size_t m_nTotalSize;
287   size_t m_nCurSize;
288   size_t m_nCurPos;
289   size_t m_nGrowSize;
290   FX_DWORD m_dwFlags;
ExpandBlocks(size_t size)291   FX_BOOL ExpandBlocks(size_t size) {
292     if (m_nCurSize < size) {
293       m_nCurSize = size;
294     }
295     if (size <= m_nTotalSize) {
296       return TRUE;
297     }
298     int32_t iCount = m_Blocks.GetSize();
299     size = (size - m_nTotalSize + m_nGrowSize - 1) / m_nGrowSize;
300     m_Blocks.SetSize(m_Blocks.GetSize() + (int32_t)size);
301     while (size--) {
302       uint8_t* pBlock = FX_Alloc(uint8_t, m_nGrowSize);
303       m_Blocks.SetAt(iCount++, pBlock);
304       m_nTotalSize += m_nGrowSize;
305     }
306     return TRUE;
307   }
308 };
309 
310 #ifdef __cplusplus
311 extern "C" {
312 #endif
313 #define MT_N 848
314 #define MT_M 456
315 #define MT_Matrix_A 0x9908b0df
316 #define MT_Upper_Mask 0x80000000
317 #define MT_Lower_Mask 0x7fffffff
318 typedef struct _FX_MTRANDOMCONTEXT {
_FX_MTRANDOMCONTEXT_FX_MTRANDOMCONTEXT319   _FX_MTRANDOMCONTEXT() {
320     mti = MT_N + 1;
321     bHaveSeed = FALSE;
322   }
323   FX_DWORD mti;
324   FX_BOOL bHaveSeed;
325   FX_DWORD mt[MT_N];
326 } FX_MTRANDOMCONTEXT, *FX_LPMTRANDOMCONTEXT;
327 typedef FX_MTRANDOMCONTEXT const* FX_LPCMTRANDOMCONTEXT;
328 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
329 FX_BOOL FX_GenerateCryptoRandom(FX_DWORD* pBuffer, int32_t iCount);
330 #endif
331 #ifdef __cplusplus
332 }
333 #endif
334 
335 #endif  // CORE_SRC_FXCRT_EXTENSION_H_
336