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 14 CFX_PrivateData::~CFX_PrivateData() 15 { 16 ClearAll(); 17 } 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 } 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 } 47 void CFX_PrivateData::SetPrivateData(FX_LPVOID pModuleId, FX_LPVOID pData, PD_CALLBACK_FREEDATA callback) 48 { 49 AddData(pModuleId, pData, callback, FALSE); 50 } 51 void CFX_PrivateData::SetPrivateObj(FX_LPVOID pModuleId, CFX_DestructObject* pObj) 52 { 53 AddData(pModuleId, pObj, NULL, TRUE); 54 } 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 } 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 } 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 } 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 } 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 } 172 static FX_BOOL FX_IsDigit(FX_BYTE ch) 173 { 174 return (ch >= '0' && ch <= '9') ? TRUE : FALSE; 175 } 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 } 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 } 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 }; 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 } 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 } 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 } 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: 282 virtual ~CFindFileData() {} 283 HANDLE m_Handle; 284 FX_BOOL m_bEnd; 285 }; 286 class CFindFileDataA : public CFindFileData 287 { 288 public: 289 virtual ~CFindFileDataA() {} 290 WIN32_FIND_DATAA m_FindData; 291 }; 292 class CFindFileDataW : public CFindFileData 293 { 294 public: 295 virtual ~CFindFileDataW() {} 296 WIN32_FIND_DATAW m_FindData; 297 }; 298 #endif 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 } 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 } 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 } 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 } 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 } 437 FX_WCHAR FX_GetFolderSeparator() 438 { 439 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ 440 return '\\'; 441 #else 442 return '/'; 443 #endif 444 } 445