MPQFile::MPQFile(const char* filename): eof(false), buffer(0), pointer(0), size(0) { for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i) { mpq_archive *mpq_a = (*i)->mpq_a; uint32 filenum; if (libmpq__file_number(mpq_a, filename, &filenum)) continue; libmpq__off_t transferred; libmpq__file_unpacked_size(mpq_a, filenum, &size); // HACK: in patch.mpq some files don't want to open and give 1 for filesize if (size<=1) { // printf("info: file %s has size %d; considered dummy file.\n", filename, size); eof = true; buffer = 0; return; } buffer = new char[size]; //libmpq_file_getdata libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); /*libmpq_file_getdata(&mpq_a, hash, fileno, (unsigned char*)buffer);*/ return; } eof = true; buffer = 0; }
FILE* MPQManager::GetFileFrom( std::string path, MPQArchive* file ) { ACE_GUARD_RETURN(ACE_Thread_Mutex, g, mutex, NULL); mpq_archive* mpq_a = file->mpq_a; uint32_t filenum; if(libmpq__file_number(mpq_a, path.c_str(), &filenum)) return NULL; libmpq__off_t transferred; libmpq__off_t size = 0; libmpq__file_unpacked_size(mpq_a, filenum, &size); // HACK: in patch.mpq some files don't want to open and give 1 for filesize if (size <= 1) return NULL; uint8* buffer = new uint8[size]; //libmpq_file_getdata libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); // Pack the return into a FILE stream FILE* ret = tmpfile(); fwrite(buffer, sizeof(uint8), size, ret); return ret; }
FILE* MPQManager::GetFileFrom(const std::string& path, MPQArchive* file ) { ACE_GUARD_RETURN(ACE_Thread_Mutex, g, mutex, NULL); mpq_archive* mpq_a = file->mpq_a; uint32_t filenum; if(libmpq__file_number(mpq_a, path.c_str(), &filenum)) return NULL; libmpq__off_t transferred; libmpq__off_t size = 0; libmpq__file_unpacked_size(mpq_a, filenum, &size); // HACK: in patch.mpq some files don't want to open and give 1 for filesize if (size <= 1) return NULL; uint8* buffer = new uint8[size]; //libmpq_file_getdata libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); // Pack the return into a FILE stream FILE* ret = tmpfile(); if (!ret) { printf("Could not create temporary file. Please run as Administrator or root\n"); exit(1); } fwrite(buffer, sizeof(uint8), size, ret); fseek(ret, 0, SEEK_SET); delete[] buffer; return ret; }
MPQFile::MPQFile(const char* filename): eof(false), buffer(0), pointer(0), size(0) { for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i) { mpq_archive *mpq_a = (*i)->mpq_a; uint32 filenum; if(libmpq__file_number(mpq_a, filename, &filenum)) continue; libmpq__off_t transferred; libmpq__file_unpacked_size(mpq_a, filenum, &size); // file should not be loaded if (size<=1) { eof = true; buffer = 0; return; } buffer = new char[size]; //libmpq_file_getdata libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); /*libmpq_file_getdata(&mpq_a, hash, fileno, (unsigned char*)buffer);*/ return; } eof = true; buffer = 0; }
//------------------------------------------------------------------------------ bool MpqHandler::getFile( const std::string &filename, BufferS_t *buffer ) const { libmpq__off_t unpacked = 0; libmpq__off_t bytes = 0; uint32_t file_num = 0; int32_t err = 0; // convert filename to lower case string std::string fn_lc( filename ); std::transform( fn_lc.begin(), fn_lc.end(), fn_lc.begin(), ::tolower ); // search for filename in our map MpqArchiveMap_t::const_iterator f = _mpqArchiveMap.find( fn_lc ); if ( f != _mpqArchiveMap.end() ) { mpq_archive_s *mpq_arc = f->second; // get file number from mpq archive err = libmpq__file_number( mpq_arc, filename.c_str(), &file_num ); err = libmpq__file_unpacked_size( mpq_arc, file_num, &unpacked ); // resize buffer and load file into that buffer buffer->resize( unpacked ); uint8_t *buf_p = (uint8_t*)&(*buffer)[0]; err = libmpq__file_read( mpq_arc, file_num, buf_p, unpacked, &bytes ); } return bytes > 0; }
//------------------------------------------------------------------------------ libmpq__off_t MpqHandler::getListFile( const std::string &filename, mpq_archive_s **mpq_arc, uint8_t **buffer ) const { int32_t err = 0; std::string mpq_file = _dataDirectory + std::string( "/" ) + filename; try { // open mpq archive err = libmpq__archive_open( mpq_arc, mpq_file.c_str(), -1 ); if ( err != LIBMPQ_SUCCESS ) { throw( std::string( "libmpq__archive_open failed" ) ); } // get file number of the list file which contains all names in the archive uint32_t file_num = 0; err = libmpq__file_number( *mpq_arc, LIBMPQ_LISTFILE_NAME, &file_num ); if ( err != LIBMPQ_SUCCESS ) { throw( std::string( "libmpq__file_number failed" ) ); } // read file from archive...get file size and reserve space libmpq__off_t file_size; err = libmpq__file_unpacked_size( *mpq_arc, file_num, &file_size ); if ( err != LIBMPQ_SUCCESS ) { throw( std::string( "libmpq__file_unpacked_size failed" ) ); } // read file from archive to buffer *buffer = new uint8_t[file_size]; err = libmpq__file_read( *mpq_arc, file_num, *buffer, file_size, NULL ); if ( err != LIBMPQ_SUCCESS ) { throw( std::string( "libmpq__file_read failed" ) ); } return file_size; } catch( std::string err_msg ) { // if an archive has been opened close it if ( *mpq_arc ) { libmpq__archive_close( *mpq_arc ); } delete [] *buffer; // quit application std::stringstream ss; ss << "Cannot open " << mpq_file << " " << err_msg; quitApp( ss.str() ); } return -1; }
MPQFile* MPQArchiveImpl::getFile( const MPQArchive* self, const std::string& filename ) const { uint32_t number = 0; ::off_t size = 0, actualsize = 0; uint8_t* buffer = 0; libmpq__file_number( archive_, filename.c_str(), &number ); libmpq__file_unpacked_size( archive_, number, &size ); buffer = new uint8_t[size]; libmpq__file_read( archive_, number, buffer, size, &actualsize ); return new MPQFile( filename, buffer, actualsize ); }
/* this function read the given file from archive into a buffer. */ int32_t libmpq__file_read(mpq_archive_s *mpq_archive, uint32_t file_number, uint8_t *out_buf, libmpq__off_t out_size, libmpq__off_t *transferred) { /* some common variables. */ uint32_t i; uint32_t blocks = 0; int32_t result = 0; libmpq__off_t file_offset = 0; libmpq__off_t unpacked_size = 0; libmpq__off_t transferred_block = 0; libmpq__off_t transferred_total = 0; /* check if given file number is not out of range. */ if (file_number < 0 || file_number > mpq_archive->files - 1) { /* file number is out of range. */ return LIBMPQ_ERROR_EXIST; } /* get target size of block. */ libmpq__file_unpacked_size(mpq_archive, file_number, &unpacked_size); /* check if target buffer is to small. */ if (unpacked_size > out_size) { /* output buffer size is to small or block size is unknown. */ return LIBMPQ_ERROR_SIZE; } /* fetch file offset. */ libmpq__file_offset(mpq_archive, file_number, &file_offset); /* get block count for file. */ libmpq__file_blocks(mpq_archive, file_number, &blocks); /* open the packed block offset table. */ if ((result = libmpq__block_open_offset(mpq_archive, file_number)) < 0) { /* something on opening packed block offset table failed. */ return result; } /* loop through all blocks. */ for (i = 0; i < blocks; i++) { /* cleanup size variable. */ unpacked_size = 0; /* get unpacked block size. */ libmpq__block_unpacked_size(mpq_archive, file_number, i, &unpacked_size); /* read block. */ if ((result = libmpq__block_read(mpq_archive, file_number, i, out_buf + transferred_total, unpacked_size, &transferred_block)) < 0) { /* close the packed block offset table. */ libmpq__block_close_offset(mpq_archive, file_number); /* something on reading block failed. */ return result; } transferred_total += transferred_block; } /* close the packed block offset table. */ libmpq__block_close_offset(mpq_archive, file_number); /* check for null pointer. */ if (transferred != NULL) { /* store transferred bytes. */ *transferred = transferred_total; } /* if no error was found, return zero. */ return LIBMPQ_SUCCESS; }