1 // Copyright 2017 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/fx_stream.h"
8
9 #include <algorithm>
10 #include <memory>
11 #include <utility>
12 #include <vector>
13
14 #include "core/fxcrt/fx_safe_types.h"
15 #include "core/fxcrt/ifx_fileaccess.h"
16 #include "third_party/base/ptr_util.h"
17
18 namespace {
19
20 class CFX_CRTFileStream final : public IFX_SeekableStream {
21 public:
22 template <typename T, typename... Args>
23 friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
24
25 // IFX_SeekableStream:
GetSize()26 FX_FILESIZE GetSize() override { return m_pFile->GetSize(); }
IsEOF()27 bool IsEOF() override { return GetPosition() >= GetSize(); }
GetPosition()28 FX_FILESIZE GetPosition() override { return m_pFile->GetPosition(); }
ReadBlock(void * buffer,FX_FILESIZE offset,size_t size)29 bool ReadBlock(void* buffer, FX_FILESIZE offset, size_t size) override {
30 return m_pFile->ReadPos(buffer, size, offset) > 0;
31 }
ReadBlock(void * buffer,size_t size)32 size_t ReadBlock(void* buffer, size_t size) override {
33 return m_pFile->Read(buffer, size);
34 }
WriteBlock(const void * buffer,FX_FILESIZE offset,size_t size)35 bool WriteBlock(const void* buffer,
36 FX_FILESIZE offset,
37 size_t size) override {
38 return !!m_pFile->WritePos(buffer, size, offset);
39 }
Flush()40 bool Flush() override { return m_pFile->Flush(); }
41
42 private:
CFX_CRTFileStream(std::unique_ptr<IFX_FileAccess> pFA)43 explicit CFX_CRTFileStream(std::unique_ptr<IFX_FileAccess> pFA)
44 : m_pFile(std::move(pFA)) {}
~CFX_CRTFileStream()45 ~CFX_CRTFileStream() override {}
46
47 std::unique_ptr<IFX_FileAccess> m_pFile;
48 };
49
50 } // namespace
51
52 // static
CreateFromFilename(const char * filename,uint32_t dwModes)53 RetainPtr<IFX_SeekableStream> IFX_SeekableStream::CreateFromFilename(
54 const char* filename,
55 uint32_t dwModes) {
56 std::unique_ptr<IFX_FileAccess> pFA = IFX_FileAccess::Create();
57 if (!pFA->Open(filename, dwModes))
58 return nullptr;
59 return pdfium::MakeRetain<CFX_CRTFileStream>(std::move(pFA));
60 }
61
62 // static
CreateFromFilename(const wchar_t * filename,uint32_t dwModes)63 RetainPtr<IFX_SeekableStream> IFX_SeekableStream::CreateFromFilename(
64 const wchar_t* filename,
65 uint32_t dwModes) {
66 std::unique_ptr<IFX_FileAccess> pFA = IFX_FileAccess::Create();
67 if (!pFA->Open(filename, dwModes))
68 return nullptr;
69 return pdfium::MakeRetain<CFX_CRTFileStream>(std::move(pFA));
70 }
71
72 // static
CreateFromFilename(const char * filename)73 RetainPtr<IFX_SeekableReadStream> IFX_SeekableReadStream::CreateFromFilename(
74 const char* filename) {
75 return IFX_SeekableStream::CreateFromFilename(filename, FX_FILEMODE_ReadOnly);
76 }
77
WriteBlock(const void * pData,size_t size)78 bool IFX_SeekableWriteStream::WriteBlock(const void* pData, size_t size) {
79 return WriteBlock(pData, GetSize(), size);
80 }
81
IsEOF()82 bool IFX_SeekableReadStream::IsEOF() {
83 return false;
84 }
85
GetPosition()86 FX_FILESIZE IFX_SeekableReadStream::GetPosition() {
87 return 0;
88 }
89
ReadBlock(void * buffer,size_t size)90 size_t IFX_SeekableReadStream::ReadBlock(void* buffer, size_t size) {
91 return 0;
92 }
93
WriteBlock(const void * buffer,size_t size)94 bool IFX_SeekableStream::WriteBlock(const void* buffer, size_t size) {
95 return WriteBlock(buffer, GetSize(), size);
96 }
97
WriteString(const ByteStringView & str)98 bool IFX_SeekableStream::WriteString(const ByteStringView& str) {
99 return WriteBlock(str.unterminated_c_str(), str.GetLength());
100 }
101
FX_OpenFolder(const char * path)102 FX_FileHandle* FX_OpenFolder(const char* path) {
103 #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
104 auto pData = pdfium::MakeUnique<CFindFileDataA>();
105 pData->m_Handle =
106 FindFirstFileExA((ByteString(path) + "/*.*").c_str(), FindExInfoStandard,
107 &pData->m_FindData, FindExSearchNameMatch, nullptr, 0);
108 if (pData->m_Handle == INVALID_HANDLE_VALUE)
109 return nullptr;
110
111 pData->m_bEnd = false;
112 return pData.release();
113 #else
114 return opendir(path);
115 #endif
116 }
117
FX_GetNextFile(FX_FileHandle * handle,ByteString * filename,bool * bFolder)118 bool FX_GetNextFile(FX_FileHandle* handle,
119 ByteString* filename,
120 bool* bFolder) {
121 if (!handle)
122 return false;
123
124 #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
125 if (handle->m_bEnd)
126 return false;
127
128 *filename = handle->m_FindData.cFileName;
129 *bFolder =
130 (handle->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
131 if (!FindNextFileA(handle->m_Handle, &handle->m_FindData))
132 handle->m_bEnd = true;
133 return true;
134 #else
135 struct dirent* de = readdir(handle);
136 if (!de)
137 return false;
138 *filename = de->d_name;
139 *bFolder = de->d_type == DT_DIR;
140 return true;
141 #endif
142 }
143
FX_CloseFolder(FX_FileHandle * handle)144 void FX_CloseFolder(FX_FileHandle* handle) {
145 if (!handle)
146 return;
147
148 #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
149 FindClose(handle->m_Handle);
150 delete handle;
151 #else
152 closedir(handle);
153 #endif
154 }
155