#include #include #include #include #include #include #include #include #include namespace LOTRO_DAT { DatExporter::DatExporter(DatFile *datFilePtr) : dat(datFilePtr) { } /*! * \author Gi1dor * \date 05.07.2018 * Извлечение в папку всех файлов, имеющих заданный тип * \param[in] type Тип файлов * \param[in] output_directory_path путь к папке, куда будут записаны файлы. Имя экспортируемого файла - file_id.ext, где file_id - id файла, ext - его расширение * * \returns DatOperationResult.value - количество извлечённых файлов */ DatOperationResult DatExporter::ExtractAllFilesByType(const FILE_TYPE &type, std::string output_directory_path) { int success_exported = 0; int iterated_files = 0; dat->GetStatusModule().SetStatus(DatStatus::E_EXTRACTING); dat->GetStatusModule().SetPercentage(0); dat->GetStatusModule().SetDebugMessage("Starting extracting files of type " + std::to_string(type)); LOG(INFO) << "Extracting files by type " + std::to_string(type) + "to database..."; auto operation = dat->GetFileSystem().PerformOperationOnAllFiles([&iterated_files, &success_exported, this, type, &output_directory_path](std::shared_ptr& file) -> void { iterated_files++; dat->GetStatusModule().SetPercentage(iterated_files * 100u / dat->GetFileSystem().GetInitialisedFilesNumber()); if ((file->FileType() & type) == NO_TYPE) return; SubfileData export_file = file->PrepareForExport(dat->GetFileSystem().GetFileData(*file, 8).value); dat->GetStatusModule().SetDebugMessage("Extracting file " + std::to_string(file->file_id()) + " (Files by type -> directory)"); if (export_file.Empty()) return; bool result; if (type == TEXT) result = WriteStringToFile(export_file.text_data, output_directory_path + std::to_string(file->file_id()) + file->Extension()).result; else result = export_file.binary_data.WriteToFile(output_directory_path + std::to_string(file->file_id()) + file->Extension()); if (result) success_exported++; }); LOG(INFO) << "Extracting files: successfully exported " << success_exported << " files"; dat->GetStatusModule().ClearAll(); return DatOperationResult(success_exported, SUCCESS); } /*! * \author Gi1dor * \date 05.07.2018 * Извлечение файла по его id * \param[in] file_id id файла * \param[in] output_filename - имя файла, куда будет записаны данные. */ DatOperationResult<> DatExporter::ExtractFileById(long long file_id, std::string output_filename) { dat->GetStatusModule().SetStatus(DatStatus::E_EXTRACTING); dat->GetStatusModule().SetPercentage(0); dat->GetStatusModule().SetDebugMessage("Extracting file " + std::to_string(file_id) + " to file " + output_filename); auto operation_GetFile = dat->GetFileSystem().GetFile(file_id); if (operation_GetFile.result == ERROR) { dat->GetStatusModule().ClearAll(); return DatOperationResult<>(ERROR, "EXTRACTFILEBYID: File not found! id = " + std::to_string(file_id)); } std::shared_ptr file = operation_GetFile.value; auto operation_GetFileData = dat->GetFileSystem().GetFileData(*file, 8); if (operation_GetFileData.result == ERROR) { dat->GetStatusModule().ClearAll(); return DatOperationResult<>(ERROR, "EXTRACTFILEBYID: Can't get data for id = " + std::to_string(file_id)); } SubfileData export_data = file->PrepareForExport(operation_GetFileData.value); bool result; if (file->FileType() == TEXT) result = WriteStringToFile(export_data.text_data, output_filename + file->Extension()).result; else result = export_data.binary_data.WriteToFile(output_filename + file->Extension()); dat->GetStatusModule().ClearAll(); if (!result) return DatOperationResult<>(ERROR, "EXTRACTFILEBYID: Cannot write to file" + output_filename + file->Extension()); return DatOperationResult<>(SUCCESS); } /*! * \author Gi1dor * \date 05.07.2018 * Извлечение в базу данных всех файлов, имеющих заданный тип * \param[in] type Тип файлов * \param[in] db Указатель на объект базы данных * * \returns DatOperationResult.value - количество извлечённых файлов */ DatOperationResult DatExporter::ExtractAllFilesByType(const FILE_TYPE &type, Database *db) { if (!db) return DatOperationResult(0, ERROR, "EXTRACTALLBYTYPETODB: database is nullptr"); dat->GetStatusModule().SetStatus(DatStatus::E_EXTRACTING); dat->GetStatusModule().SetPercentage(0); dat->GetStatusModule().SetDebugMessage("Initialising extraction of files by type " + std::to_string(type) + "to database..."); LOG(INFO) << "Extracting files by type " + std::to_string(type) + "to database..."; int success_exported = 0; int iterated_files = 0; auto operation = dat->GetFileSystem().PerformOperationOnAllFiles([&success_exported, &iterated_files, this, type, db](std::shared_ptr& file) { iterated_files++; dat->GetStatusModule().SetPercentage(iterated_files * 100u / dat->GetFileSystem().GetInitialisedFilesNumber()); if ((file->FileType() & type) == NO_TYPE) return; dat->GetStatusModule().SetDebugMessage("Extracting file " + std::to_string(file->file_id()) + " (Files by type -> database)"); SubfileData export_file = file->PrepareForExport(dat->GetFileSystem().GetFileData(*file, 8).value); bool result = db->PushFile(export_file); if (result) success_exported++; }); LOG(INFO) << "Extracting files: successfully exported " << success_exported << " files"; dat->GetStatusModule().ClearAll(); return DatOperationResult(success_exported, SUCCESS); } /*! * \author Ivan Arkhipov * \date 21.10.2018 * Извлечение в базу данных файла с заданным id * \param[in] file_id ID файла * \param[in] db Указатель на объект базы данных */ DatOperationResult<> DatExporter::ExtractFileById(long long file_id, Database *db) { if (!db) return DatOperationResult<>(ERROR, "EXTRACTFILEBYIDTODB: database is nullptr"); dat->GetStatusModule().SetStatus(DatStatus::E_EXTRACTING); dat->GetStatusModule().SetPercentage(50); LOG(INFO) << "Extracting file with id = " << file_id << "to database..."; auto operation_GetFile = dat->GetFileSystem().GetFile(file_id); if (operation_GetFile.result == ERROR) { dat->GetStatusModule().ClearAll(); return DatOperationResult<>(ERROR, "EXTRACTFILEBYIDTODB: File not found! id = " + std::to_string(file_id)); } std::shared_ptr file = operation_GetFile.value; auto operation_GetFileData = dat->GetFileSystem().GetFileData(*file, 8); if (operation_GetFileData.result == ERROR) { dat->GetStatusModule().ClearAll(); return DatOperationResult<>(ERROR, "EXTRACTFILEBYIDTODB: Can't get data for id = " + std::to_string(file_id)); } SubfileData export_data = file->PrepareForExport(operation_GetFileData.value); bool result = db->PushFile(export_data); dat->GetStatusModule().ClearAll(); if (!result) return DatOperationResult<>(ERROR, "EXTRACTFILEBYIDTODB: Cannot export file" + std::to_string(file_id)); LOG(INFO) << "Successfully exported file " << file_id << " to database"; return DatOperationResult<>(SUCCESS); } /*! * \author Gi1dor * \date 05.07.2018 * Запись строки в формате UTF-16 в файл * \param[in] str Строка для записи в файл * \param[in] path Путь к файлу, в который строка будет записана * * \warning Путь к файлу должен быть корректным (папки должны существовать). Если и сам файл существует, то он будет перезаписан */ DatOperationResult<> DatExporter::WriteStringToFile(const std::u16string &str, const std::string &path) { std::basic_ofstream output_stream(path, std::ios::out); if (!output_stream.is_open()) return DatOperationResult<>(ERROR, "WRITESTRINGTOFILE: cant open file " + path); output_stream << str; output_stream.close(); return DatOperationResult<>(); } };