MCPcopy Create free account
hub / github.com/BYVoid/OpenCC / Index

Method Index

src/ResourceProvider.cpp:299–370  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

297};
298
299void ZipResourceProvider::Internal::Index() {
300 const unsigned char* data = archive->data;
301 const size_t size = archive->size;
302 if (size < 22) {
303 throw InvalidFormat("Invalid zip archive: " + archive->fileName);
304 }
305
306 const size_t maxCommentSize = 65535;
307 const size_t searchStart =
308 size > maxCommentSize + 22 ? size - maxCommentSize - 22 : 0;
309 size_t eocdOffset = std::string::npos;
310 for (size_t pos = size - 22;; pos--) {
311 if (data[pos] == 0x50 && data[pos + 1] == 0x4b && data[pos + 2] == 0x05 &&
312 data[pos + 3] == 0x06) {
313 eocdOffset = pos;
314 break;
315 }
316 if (pos == searchStart) {
317 break;
318 }
319 }
320 if (eocdOffset == std::string::npos) {
321 throw InvalidFormat("Invalid zip archive: " + archive->fileName);
322 }
323
324 const uint16_t entryCount = ReadLe16(&data[eocdOffset + 10]);
325 const uint32_t centralDirectorySize = ReadLe32(&data[eocdOffset + 12]);
326 const uint32_t centralDirectoryOffset = ReadLe32(&data[eocdOffset + 16]);
327 if (centralDirectoryOffset > size ||
328 centralDirectorySize > size - centralDirectoryOffset) {
329 throw InvalidFormat("Invalid zip central directory: " + archive->fileName);
330 }
331
332 size_t pos = centralDirectoryOffset;
333 for (uint16_t i = 0; i < entryCount; i++) {
334 if (pos + 46 > size || ReadLe32(&data[pos]) != 0x02014b50) {
335 throw InvalidFormat("Invalid zip central directory: " + archive->fileName);
336 }
337 const uint16_t method = ReadLe16(&data[pos + 10]);
338 const uint32_t compressedSize = ReadLe32(&data[pos + 20]);
339 const uint32_t uncompressedSize = ReadLe32(&data[pos + 24]);
340 const uint16_t fileNameLength = ReadLe16(&data[pos + 28]);
341 const uint16_t extraLength = ReadLe16(&data[pos + 30]);
342 const uint16_t commentLength = ReadLe16(&data[pos + 32]);
343 const uint32_t localHeaderOffset = ReadLe32(&data[pos + 42]);
344 const size_t next = pos + 46 + fileNameLength + extraLength + commentLength;
345 if (next > size) {
346 throw InvalidFormat("Invalid zip central directory: " + archive->fileName);
347 }
348 const std::string name(
349 reinterpret_cast<const char*>(&data[pos + 46]), fileNameLength);
350 const std::string normalized = NormalizeResourceName(name);
351 if (!IsAbsolutePath(name) && !normalized.empty() &&
352 normalized.back() != '/' && IsSafeZipResourceName(normalized)) {
353 if (localHeaderOffset + 30 > size ||
354 ReadLe32(&data[localHeaderOffset]) != 0x04034b50) {
355 throw InvalidFormat("Invalid zip local header: " + archive->fileName);
356 }

Callers

nothing calls this directly

Calls 6

ReadLe16Function · 0.85
ReadLe32Function · 0.85
NormalizeResourceNameFunction · 0.85
IsSafeZipResourceNameFunction · 0.85
IsAbsolutePathFunction · 0.70
emptyMethod · 0.45

Tested by

no test coverage detected