CPkgReader.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #include "CPkgReader.h"
  2. namespace WallpaperEngine::Irrlicht
  3. {
  4. CArchiveLoaderPkg::CArchiveLoaderPkg (CContext* context) :
  5. m_context (context)
  6. {
  7. #ifdef _DEBUG
  8. setDebugName("CArchiveLoaderPKG");
  9. #endif
  10. }
  11. bool CArchiveLoaderPkg::isALoadableFileFormat(const irr::io::path& filename) const
  12. {
  13. return irr::core::hasFileExtension (filename, "pkg");
  14. }
  15. irr::io::IFileArchive* CArchiveLoaderPkg::createArchive(const irr::io::path& filename, bool ignoreCase, bool ignorePaths) const
  16. {
  17. irr::io::IFileArchive *archive = nullptr;
  18. irr::io::IReadFile* file = this->m_context->getDevice ()->getFileSystem ()->createAndOpenFile(filename);
  19. if (file)
  20. {
  21. archive = this->createArchive (file, ignoreCase, ignorePaths);
  22. file->drop ();
  23. }
  24. return archive;
  25. }
  26. irr::io::IFileArchive* CArchiveLoaderPkg::createArchive(irr::io::IReadFile* file, bool ignoreCase, bool ignorePaths) const
  27. {
  28. irr::io::IFileArchive *archive = nullptr;
  29. if (file)
  30. {
  31. file->seek (0);
  32. archive = new CPkgReader (this->m_context, file, ignoreCase, ignorePaths);
  33. }
  34. return archive;
  35. }
  36. bool CArchiveLoaderPkg::isALoadableFileFormat(irr::io::IReadFile* file) const
  37. {
  38. unsigned int size;
  39. char* pointer;
  40. file->read (&size, 4);
  41. // the string doesnt include the null terminator
  42. size ++;
  43. pointer = new char [size];
  44. memset (pointer, 0, size);
  45. file->read (pointer, size - 1);
  46. if (
  47. strcmp ("PKGV0007", pointer) != 0 &&
  48. strcmp ("PKGV0002", pointer) != 0 &&
  49. strcmp ("PKGV0001", pointer) != 0)
  50. {
  51. delete [] pointer;
  52. return false;
  53. }
  54. delete [] pointer;
  55. return true;
  56. }
  57. //! Check to see if the loader can create archives of this type.
  58. bool CArchiveLoaderPkg::isALoadableFileFormat(irr::io::E_FILE_ARCHIVE_TYPE fileType) const
  59. {
  60. return false;
  61. }
  62. CPkgReader::CPkgReader (CContext* context, irr::io::IReadFile* file, bool ignoreCase, bool ignorePaths)
  63. : CFileList((file ? file->getFileName() : irr::io::path("")), ignoreCase, ignorePaths),
  64. m_file(file),
  65. m_context (context)
  66. {
  67. if (this->m_file)
  68. {
  69. this->m_file->grab ();
  70. this->scanPkgHeader ();
  71. }
  72. }
  73. CPkgReader::~CPkgReader()
  74. {
  75. if (this->m_file)
  76. this->m_file->drop();
  77. }
  78. irr::io::E_FILE_ARCHIVE_TYPE CPkgReader::getType() const
  79. {
  80. return irr::io::E_FILE_ARCHIVE_TYPE::EFAT_ZIP;
  81. }
  82. const irr::io::IFileList* CPkgReader::getFileList() const
  83. {
  84. return this;
  85. }
  86. void CPkgReader::scanPkgHeader ()
  87. {
  88. char* headerVersion = this->readSizedString ();
  89. if (
  90. strcmp ("PKGV0007", headerVersion) != 0 &&
  91. strcmp ("PKGV0002", headerVersion) != 0 &&
  92. strcmp ("PKGV0001", headerVersion) != 0)
  93. {
  94. delete [] headerVersion;
  95. this->m_context->getDevice ()->getLogger ()->log (
  96. "unexpected package header", this->m_file->getFileName ().c_str (), irr::ELL_ERROR
  97. );
  98. return;
  99. }
  100. delete [] headerVersion;
  101. irr::u32 entriesCount;
  102. this->m_file->read (&entriesCount, 4);
  103. for (irr::u32 i = 0; i < entriesCount; i ++)
  104. {
  105. char* filename = this->readSizedString ();
  106. irr::u32 offset, length;
  107. this->m_file->read (&offset, 4);
  108. this->m_file->read (&length, 4);
  109. this->addItem (filename, offset, length, false);
  110. delete [] filename;
  111. }
  112. // after the header is read we have to update the actual offsets
  113. for (irr::u32 i = 0; i < this->m_files.size (); i ++)
  114. {
  115. this->m_files [i].Offset += this->m_file->getPos ();
  116. }
  117. }
  118. char* CPkgReader::readSizedString ()
  119. {
  120. unsigned int size;
  121. char* pointer;
  122. this->m_file->read (&size, 4);
  123. // the string doesnt include the null terminator
  124. size ++;
  125. pointer = new char [size];
  126. memset (pointer, 0, size);
  127. this->m_file->read (pointer, size - 1);
  128. return pointer;
  129. }
  130. irr::io::IReadFile* CPkgReader::createAndOpenFile (const irr::io::path& filename)
  131. {
  132. irr::s32 index = this->findFile (filename, false);
  133. if (index != -1)
  134. return createAndOpenFile (index);
  135. return nullptr;
  136. }
  137. irr::io::IReadFile* CPkgReader::createAndOpenFile (irr::u32 index)
  138. {
  139. if (index > this->m_files.size ())
  140. return nullptr;
  141. const SFileListEntry entry = m_files [index];
  142. return irr::io::createLimitReadFile (entry.FullName, m_file, entry.Offset, entry.Size);
  143. }
  144. }