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
15class IFXCRT_FileAccess {
16 public:
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};
34IFXCRT_FileAccess* FXCRT_FileAccess_Create();
35
36#ifdef PDF_ENABLE_XFA
37class CFX_CRTFileAccess : public IFX_FileAccess {
38 public:
39  CFX_CRTFileAccess() : m_RefCount(0) {}
40
41  // IFX_FileAccess
42  void Release() override {
43    if (--m_RefCount == 0)
44      delete this;
45  }
46
47  IFX_FileAccess* Retain() override {
48    m_RefCount++;
49    return (IFX_FileAccess*)this;
50  }
51
52  void GetPath(CFX_WideString& wsPath) override { wsPath = m_path; }
53
54  IFX_FileStream* CreateFileStream(FX_DWORD dwModes) override {
55    return FX_CreateFileStream(m_path, dwModes);
56  }
57
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
70class 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
96class CFX_MemoryStream final : public IFX_MemoryStream {
97 public:
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  }
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  }
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:
127  IFX_FileStream* Retain() override {
128    m_dwCount++;
129    return this;
130  }
131  void Release() override {
132    FX_DWORD nCount = --m_dwCount;
133    if (nCount) {
134      return;
135    }
136    delete this;
137  }
138  FX_FILESIZE GetSize() override { return (FX_FILESIZE)m_nCurSize; }
139  FX_BOOL IsEOF() override { return m_nCurPos >= (size_t)GetSize(); }
140  FX_FILESIZE GetPosition() override { return (FX_FILESIZE)m_nCurPos; }
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  }
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  }
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  }
242  FX_BOOL Flush() override { return TRUE; }
243  FX_BOOL IsConsecutive() const override {
244    return m_dwFlags & FX_MEMSTREAM_Consecutive;
245  }
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  }
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  }
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;
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
311extern "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
318typedef struct _FX_MTRANDOMCONTEXT {
319  _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;
327typedef FX_MTRANDOMCONTEXT const* FX_LPCMTRANDOMCONTEXT;
328#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
329FX_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