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 "../../include/fxcrt/fx_basic.h"
8 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
9 #include <sys/types.h>
10 #include <dirent.h>
11 #else
12 #include <direct.h>
13 #endif
~CFX_PrivateData()14 CFX_PrivateData::~CFX_PrivateData()
15 {
16 ClearAll();
17 }
FreeData()18 void FX_PRIVATEDATA::FreeData()
19 {
20 if (m_pData == NULL) {
21 return;
22 }
23 if (m_bSelfDestruct) {
24 delete (CFX_DestructObject*)m_pData;
25 } else if (m_pCallback) {
26 m_pCallback(m_pData);
27 }
28 }
AddData(FX_LPVOID pModuleId,FX_LPVOID pData,PD_CALLBACK_FREEDATA callback,FX_BOOL bSelfDestruct)29 void CFX_PrivateData::AddData(FX_LPVOID pModuleId, FX_LPVOID pData, PD_CALLBACK_FREEDATA callback, FX_BOOL bSelfDestruct)
30 {
31 if (pModuleId == NULL) {
32 return;
33 }
34 FX_PRIVATEDATA* pList = m_DataList.GetData();
35 int count = m_DataList.GetSize();
36 for (int i = 0; i < count; i ++) {
37 if (pList[i].m_pModuleId == pModuleId) {
38 pList[i].FreeData();
39 pList[i].m_pData = pData;
40 pList[i].m_pCallback = callback;
41 return;
42 }
43 }
44 FX_PRIVATEDATA data = {pModuleId, pData, callback, bSelfDestruct};
45 m_DataList.Add(data);
46 }
SetPrivateData(FX_LPVOID pModuleId,FX_LPVOID pData,PD_CALLBACK_FREEDATA callback)47 void CFX_PrivateData::SetPrivateData(FX_LPVOID pModuleId, FX_LPVOID pData, PD_CALLBACK_FREEDATA callback)
48 {
49 AddData(pModuleId, pData, callback, FALSE);
50 }
SetPrivateObj(FX_LPVOID pModuleId,CFX_DestructObject * pObj)51 void CFX_PrivateData::SetPrivateObj(FX_LPVOID pModuleId, CFX_DestructObject* pObj)
52 {
53 AddData(pModuleId, pObj, NULL, TRUE);
54 }
RemovePrivateData(FX_LPVOID pModuleId)55 FX_BOOL CFX_PrivateData::RemovePrivateData(FX_LPVOID pModuleId)
56 {
57 if (pModuleId == NULL) {
58 return FALSE;
59 }
60 FX_PRIVATEDATA* pList = m_DataList.GetData();
61 int count = m_DataList.GetSize();
62 for (int i = 0; i < count; i ++) {
63 if (pList[i].m_pModuleId == pModuleId) {
64 m_DataList.RemoveAt(i);
65 return TRUE;
66 }
67 }
68 return FALSE;
69 }
GetPrivateData(FX_LPVOID pModuleId)70 FX_LPVOID CFX_PrivateData::GetPrivateData(FX_LPVOID pModuleId)
71 {
72 if (pModuleId == NULL) {
73 return NULL;
74 }
75 FX_PRIVATEDATA* pList = m_DataList.GetData();
76 int count = m_DataList.GetSize();
77 for (int i = 0; i < count; i ++) {
78 if (pList[i].m_pModuleId == pModuleId) {
79 return pList[i].m_pData;
80 }
81 }
82 return NULL;
83 }
ClearAll()84 void CFX_PrivateData::ClearAll()
85 {
86 FX_PRIVATEDATA* pList = m_DataList.GetData();
87 int count = m_DataList.GetSize();
88 for (int i = 0; i < count; i ++) {
89 pList[i].FreeData();
90 }
91 m_DataList.RemoveAll();
92 }
FX_atonum(FX_BSTR strc,FX_BOOL & bInteger,void * pData)93 void FX_atonum(FX_BSTR strc, FX_BOOL& bInteger, void* pData)
94 {
95 if (FXSYS_memchr(strc.GetPtr(), '.', strc.GetLength()) == NULL) {
96 bInteger = TRUE;
97 int cc = 0, integer = 0;
98 FX_LPCSTR str = strc.GetCStr();
99 int len = strc.GetLength();
100 FX_BOOL bNegative = FALSE;
101 if (str[0] == '+') {
102 cc++;
103 } else if (str[0] == '-') {
104 bNegative = TRUE;
105 cc++;
106 }
107 while (cc < len) {
108 if (str[cc] < '0' || str[cc] > '9') {
109 break;
110 }
111 integer = integer * 10 + str[cc] - '0';
112 if (integer < 0) {
113 break;
114 }
115 cc ++;
116 }
117 if (bNegative) {
118 integer = -integer;
119 }
120 *(int*)pData = integer;
121 } else {
122 bInteger = FALSE;
123 *(FX_FLOAT*)pData = FX_atof(strc);
124 }
125 }
FX_atof(FX_BSTR strc)126 FX_FLOAT FX_atof(FX_BSTR strc)
127 {
128 if (strc.GetLength() == 0) {
129 return 0.0;
130 }
131 int cc = 0;
132 FX_BOOL bNegative = FALSE;
133 FX_LPCSTR str = strc.GetCStr();
134 int len = strc.GetLength();
135 if (str[0] == '+') {
136 cc++;
137 } else if (str[0] == '-') {
138 bNegative = TRUE;
139 cc++;
140 }
141 while (cc < len) {
142 if (str[cc] != '+' && str[cc] != '-') {
143 break;
144 }
145 cc ++;
146 }
147 FX_FLOAT value = 0;
148 while (cc < len) {
149 if (str[cc] == '.') {
150 break;
151 }
152 value = value * 10 + str[cc] - '0';
153 cc ++;
154 }
155 static const FX_FLOAT fraction_scales[] = {0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f,
156 0.0000001f, 0.00000001f, 0.000000001f, 0.0000000001f, 0.00000000001f
157 };
158 int scale = 0;
159 if (cc < len && str[cc] == '.') {
160 cc ++;
161 while (cc < len) {
162 value += fraction_scales[scale] * (str[cc] - '0');
163 scale ++;
164 if (scale == sizeof fraction_scales / sizeof(FX_FLOAT)) {
165 break;
166 }
167 cc ++;
168 }
169 }
170 return bNegative ? -value : value;
171 }
FX_IsDigit(FX_BYTE ch)172 static FX_BOOL FX_IsDigit(FX_BYTE ch)
173 {
174 return (ch >= '0' && ch <= '9') ? TRUE : FALSE;
175 }
FX_IsXDigit(FX_BYTE ch)176 static FX_BOOL FX_IsXDigit(FX_BYTE ch)
177 {
178 return (FX_IsDigit(ch) || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) ? TRUE : FALSE;
179 }
FX_MakeUpper(FX_BYTE ch)180 static FX_BYTE FX_MakeUpper(FX_BYTE ch)
181 {
182 if (ch < 'a' || ch > 'z') {
183 return ch;
184 }
185 return ch - 32;
186 }
FX_HexToI(FX_BYTE ch)187 static int FX_HexToI(FX_BYTE ch)
188 {
189 ch = FX_MakeUpper(ch);
190 return FX_IsDigit(ch) ? (ch - '0') : (ch - 55);
191 }
192 static const unsigned char url_encodeTable[128] = {
193 1, 1, 1, 1, 1, 1, 1, 1,
194 1, 1, 1, 1, 1, 1, 1, 1,
195 1, 1, 1, 1, 1, 1, 1, 1,
196 1, 1, 1, 1, 1, 1, 1, 1,
197 1, 0, 1, 1, 0, 1, 0, 0,
198 0, 0, 0, 0, 0, 0, 0, 0,
199 0, 0, 0, 0, 0, 0, 0, 0,
200 0, 0, 0, 0, 1, 0, 1, 0,
201 0, 0, 0, 0, 0, 0, 0, 0,
202 0, 0, 0, 0, 0, 0, 0, 0,
203 0, 0, 0, 0, 0, 0, 0, 0,
204 0, 0, 0, 1, 1, 1, 1, 0,
205 1, 0, 0, 0, 0, 0, 0, 0,
206 0, 0, 0, 0, 0, 0, 0, 0,
207 0, 0, 0, 0, 0, 0, 0, 0,
208 0, 0, 0, 1, 1, 1, 1, 1,
209 };
FX_UrlEncode(const CFX_WideString & wsUrl)210 CFX_ByteString FX_UrlEncode(const CFX_WideString& wsUrl)
211 {
212 const char arDigits[] = "0123456789ABCDEF";
213 CFX_ByteString rUrl;
214 int nLength = wsUrl.GetLength();
215 for (int i = 0; i < nLength; i++) {
216 FX_DWORD word = wsUrl.GetAt(i);
217 if (word > 0x7F || url_encodeTable[word] == 1) {
218 CFX_ByteString bsUri = CFX_ByteString::FromUnicode((FX_WORD)word);
219 int nByte = bsUri.GetLength();
220 for (int j = 0; j < nByte; j++) {
221 rUrl += '%';
222 FX_BYTE code = bsUri.GetAt(j);
223 rUrl += arDigits[code >> 4];
224 rUrl += arDigits[code & 0x0F];
225 }
226 } else {
227 rUrl += CFX_ByteString::FromUnicode((FX_WORD)word);
228 }
229 }
230 return rUrl;
231 }
FX_UrlDecode(const CFX_ByteString & bsUrl)232 CFX_WideString FX_UrlDecode(const CFX_ByteString& bsUrl)
233 {
234 CFX_ByteString rUrl;
235 int nLength = bsUrl.GetLength();
236 for (int i = 0; i < nLength; i++) {
237 if (i < nLength - 2 && bsUrl[i] == '%' && FX_IsXDigit(bsUrl[i + 1]) && FX_IsXDigit(bsUrl[i + 2])) {
238 rUrl += (FX_HexToI(bsUrl[i + 1]) << 4 | FX_HexToI(bsUrl[i + 2]));
239 i += 2;
240 } else {
241 rUrl += bsUrl[i];
242 }
243 }
244 return CFX_WideString::FromLocal(rUrl);
245 }
FX_EncodeURI(const CFX_WideString & wsURI)246 CFX_ByteString FX_EncodeURI(const CFX_WideString& wsURI)
247 {
248 const char arDigits[] = "0123456789ABCDEF";
249 CFX_ByteString rURI;
250 CFX_ByteString bsUri = wsURI.UTF8Encode();
251 int nLength = bsUri.GetLength();
252 for (int i = 0; i < nLength; i++) {
253 FX_BYTE code = bsUri.GetAt(i);
254 if (code > 0x7F || url_encodeTable[code] == 1) {
255 rURI += '%';
256 rURI += arDigits[code >> 4];
257 rURI += arDigits[code & 0x0F];
258 } else {
259 rURI += code;
260 }
261 }
262 return rURI;
263 }
FX_DecodeURI(const CFX_ByteString & bsURI)264 CFX_WideString FX_DecodeURI(const CFX_ByteString& bsURI)
265 {
266 CFX_ByteString rURI;
267 int nLength = bsURI.GetLength();
268 for (int i = 0; i < nLength; i++) {
269 if (i < nLength - 2 && bsURI[i] == '%' && FX_IsXDigit(bsURI[i + 1]) && FX_IsXDigit(bsURI[i + 2])) {
270 rURI += (FX_HexToI(bsURI[i + 1]) << 4 | FX_HexToI(bsURI[i + 2]));
271 i += 2;
272 } else {
273 rURI += bsURI[i];
274 }
275 }
276 return CFX_WideString::FromUTF8(rURI);
277 }
278 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
279 class CFindFileData : public CFX_Object
280 {
281 public:
~CFindFileData()282 virtual ~CFindFileData() {}
283 HANDLE m_Handle;
284 FX_BOOL m_bEnd;
285 };
286 class CFindFileDataA : public CFindFileData
287 {
288 public:
~CFindFileDataA()289 virtual ~CFindFileDataA() {}
290 WIN32_FIND_DATAA m_FindData;
291 };
292 class CFindFileDataW : public CFindFileData
293 {
294 public:
~CFindFileDataW()295 virtual ~CFindFileDataW() {}
296 WIN32_FIND_DATAW m_FindData;
297 };
298 #endif
FX_OpenFolder(FX_LPCSTR path)299 void* FX_OpenFolder(FX_LPCSTR path)
300 {
301 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
302 #ifndef _WIN32_WCE
303 CFindFileDataA* pData = FX_NEW CFindFileDataA;
304 if (!pData) {
305 return NULL;
306 }
307 #ifdef _FX_WINAPI_PARTITION_DESKTOP_
308 pData->m_Handle = FindFirstFileA(CFX_ByteString(path) + "/*.*", &pData->m_FindData);
309 #else
310 pData->m_Handle = FindFirstFileExA(CFX_ByteString(path) + "/*.*", FindExInfoStandard, &pData->m_FindData, FindExSearchNameMatch, NULL, 0);
311 #endif
312 #else
313 CFindFileDataW* pData = FX_NEW CFindFileDataW;
314 if (!pData) {
315 return NULL;
316 }
317 pData->m_Handle = FindFirstFileW(CFX_WideString::FromLocal(path) + L"/*.*", &pData->m_FindData);
318 #endif
319 if (pData->m_Handle == INVALID_HANDLE_VALUE) {
320 delete pData;
321 return NULL;
322 }
323 pData->m_bEnd = FALSE;
324 return pData;
325 #else
326 DIR* dir = opendir(path);
327 return dir;
328 #endif
329 }
FX_OpenFolder(FX_LPCWSTR path)330 void* FX_OpenFolder(FX_LPCWSTR path)
331 {
332 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
333 CFindFileDataW* pData = FX_NEW CFindFileDataW;
334 if (!pData) {
335 return NULL;
336 }
337 #ifdef _FX_WINAPI_PARTITION_DESKTOP_
338 pData->m_Handle = FindFirstFileW(CFX_WideString(path) + L"/*.*", &pData->m_FindData);
339 #else
340 pData->m_Handle = FindFirstFileExW(CFX_WideString(path) + L"/*.*", FindExInfoStandard, &pData->m_FindData, FindExSearchNameMatch, NULL, 0);
341 #endif
342 if (pData->m_Handle == INVALID_HANDLE_VALUE) {
343 delete pData;
344 return NULL;
345 }
346 pData->m_bEnd = FALSE;
347 return pData;
348 #else
349 DIR* dir = opendir(CFX_ByteString::FromUnicode(path));
350 return dir;
351 #endif
352 }
FX_GetNextFile(void * handle,CFX_ByteString & filename,FX_BOOL & bFolder)353 FX_BOOL FX_GetNextFile(void* handle, CFX_ByteString& filename, FX_BOOL& bFolder)
354 {
355 if (handle == NULL) {
356 return FALSE;
357 }
358 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
359 #ifndef _WIN32_WCE
360 CFindFileDataA* pData = (CFindFileDataA*)handle;
361 if (pData->m_bEnd) {
362 return FALSE;
363 }
364 filename = pData->m_FindData.cFileName;
365 bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
366 if (!FindNextFileA(pData->m_Handle, &pData->m_FindData)) {
367 pData->m_bEnd = TRUE;
368 }
369 return TRUE;
370 #else
371 CFindFileDataW* pData = (CFindFileDataW*)handle;
372 if (pData->m_bEnd) {
373 return FALSE;
374 }
375 filename = CFX_ByteString::FromUnicode(pData->m_FindData.cFileName);
376 bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
377 if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) {
378 pData->m_bEnd = TRUE;
379 }
380 return TRUE;
381 #endif
382 #elif defined(__native_client__)
383 abort();
384 return FALSE;
385 #else
386 struct dirent *de = readdir((DIR*)handle);
387 if (de == NULL) {
388 return FALSE;
389 }
390 filename = de->d_name;
391 bFolder = de->d_type == DT_DIR;
392 return TRUE;
393 #endif
394 }
FX_GetNextFile(void * handle,CFX_WideString & filename,FX_BOOL & bFolder)395 FX_BOOL FX_GetNextFile(void* handle, CFX_WideString& filename, FX_BOOL& bFolder)
396 {
397 if (handle == NULL) {
398 return FALSE;
399 }
400 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
401 CFindFileDataW* pData = (CFindFileDataW*)handle;
402 if (pData->m_bEnd) {
403 return FALSE;
404 }
405 filename = pData->m_FindData.cFileName;
406 bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
407 if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) {
408 pData->m_bEnd = TRUE;
409 }
410 return TRUE;
411 #elif defined(__native_client__)
412 abort();
413 return FALSE;
414 #else
415 struct dirent *de = readdir((DIR*)handle);
416 if (de == NULL) {
417 return FALSE;
418 }
419 filename = CFX_WideString::FromLocal(de->d_name);
420 bFolder = de->d_type == DT_DIR;
421 return TRUE;
422 #endif
423 }
FX_CloseFolder(void * handle)424 void FX_CloseFolder(void* handle)
425 {
426 if (handle == NULL) {
427 return;
428 }
429 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
430 CFindFileData* pData = (CFindFileData*)handle;
431 FindClose(pData->m_Handle);
432 delete pData;
433 #else
434 closedir((DIR*)handle);
435 #endif
436 }
FX_GetFolderSeparator()437 FX_WCHAR FX_GetFolderSeparator()
438 {
439 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
440 return '\\';
441 #else
442 return '/';
443 #endif
444 }
445