#include "x2tTester.h" #include #include "../../../X2tConverter/src/run.h" class CFormatsList; class Cx2tTester; class CConverter; std::wstring GetFileExtLower(const std::wstring& file) { std::wstring input_ext = NSFile::GetFileExtention(file); for (auto& c : input_ext) c = std::tolower(c); return input_ext; } CFormatsList::CFormatsList() { } CFormatsList::CFormatsList(const CFormatsList& list) { *this = list; } CFormatsList& CFormatsList::operator=(const CFormatsList& list) { m_documents.clear(); m_presentations.clear(); m_spreadsheets.clear(); m_images.clear(); m_crossplatform.clear(); for(auto& val : list.m_documents) m_documents.push_back(val); for(auto& val : list.m_presentations) m_presentations.push_back(val); for(auto& val : list.m_spreadsheets) m_spreadsheets.push_back(val); for(auto& val : list.m_images) m_images.push_back(val); for(auto& val : list.m_draw) m_draw.push_back(val); for(auto& val : list.m_crossplatform) m_crossplatform.push_back(val); m_pdf = list.m_pdf; return *this; } std::vector CFormatsList::GetDocuments() const { return m_documents; } std::vector CFormatsList::GetPresentations() const { return m_presentations; } std::vector CFormatsList::GetSpreadsheets() const { return m_spreadsheets; } std::vector CFormatsList::GetCrossplatform() const { return m_crossplatform; } std::vector CFormatsList::GetDraw() const { return m_draw; } std::vector CFormatsList::GetImages() const { return m_images; } std::wstring CFormatsList::GetPdf() const { return m_pdf; } bool CFormatsList::IsDocument(const std::wstring& ext) const { return std::find(m_documents.begin(), m_documents.end(), ext) != m_documents.end(); } bool CFormatsList::IsPresentation(const std::wstring& ext) const { return std::find(m_presentations.begin(), m_presentations.end(), ext) != m_presentations.end(); } bool CFormatsList::IsSpreadsheet(const std::wstring& ext) const { return std::find(m_spreadsheets.begin(), m_spreadsheets.end(), ext) != m_spreadsheets.end(); } bool CFormatsList::IsCrossplatform(const std::wstring& ext) const { return std::find(m_crossplatform.begin(), m_crossplatform.end(), ext) != m_crossplatform.end(); } bool CFormatsList::IsDraw(const std::wstring& ext) const { return std::find(m_draw.begin(), m_draw.end(), ext) != m_draw.end(); } bool CFormatsList::IsImage(const std::wstring& ext) const { return std::find(m_images.begin(), m_images.end(), ext) != m_images.end(); } bool CFormatsList::IsPdf(const std::wstring& ext) const { return ext == m_pdf; } bool CFormatsList::IsAny(const std::wstring& ext) const { return IsDocument(ext) || IsPresentation(ext) || IsSpreadsheet(ext) || IsCrossplatform(ext) || IsImage(ext) || IsPdf(ext) || IsDraw(ext); } void CFormatsList::AddDocument(const std::wstring& ext) { m_documents.push_back(ext); } void CFormatsList::AddPresentation(const std::wstring& ext) { m_presentations.push_back(ext); } void CFormatsList::AddSpreadsheet(const std::wstring& ext) { m_spreadsheets.push_back(ext); } void CFormatsList::AddCrossplatform(const std::wstring& ext) { m_crossplatform.push_back(ext); } void CFormatsList::AddDraw(const std::wstring& ext) { m_draw.push_back(ext); } void CFormatsList::AddImage(const std::wstring& ext) { m_images.push_back(ext); } std::vector CFormatsList::GetAllExts() const { std::vector all_formats; for (const auto& val : m_documents) all_formats.push_back(val); for (const auto& val : m_presentations) all_formats.push_back(val); for (const auto& val : m_spreadsheets) all_formats.push_back(val); for (const auto& val : m_images) all_formats.push_back(val); for (const auto& val : m_crossplatform) all_formats.push_back(val); for (const auto& val : m_draw) all_formats.push_back(val); if (!m_pdf.empty()) all_formats.push_back(m_pdf); return all_formats; } CFormatsList CFormatsList::GetDefaultExts() { CFormatsList list; list.m_documents.push_back(L"doct"); list.m_documents.push_back(L"doc"); list.m_documents.push_back(L"docm"); list.m_documents.push_back(L"docx"); list.m_documents.push_back(L"docxf"); list.m_documents.push_back(L"dot"); list.m_documents.push_back(L"dotm"); list.m_documents.push_back(L"dotx"); list.m_documents.push_back(L"epub"); list.m_documents.push_back(L"fb2"); list.m_documents.push_back(L"fodt"); list.m_documents.push_back(L"htm"); list.m_documents.push_back(L"html"); list.m_documents.push_back(L"md"); list.m_documents.push_back(L"hwp"); list.m_documents.push_back(L"hwpx"); list.m_documents.push_back(L"mht"); list.m_documents.push_back(L"odt"); list.m_documents.push_back(L"ott"); list.m_documents.push_back(L"oxps"); list.m_documents.push_back(L"pages"); list.m_documents.push_back(L"rtf"); list.m_documents.push_back(L"stw"); list.m_documents.push_back(L"sxw"); list.m_documents.push_back(L"txt"); list.m_documents.push_back(L"wps"); list.m_documents.push_back(L"wpt"); list.m_presentations.push_back(L"pptt"); list.m_presentations.push_back(L"dps"); list.m_presentations.push_back(L"dpt"); list.m_presentations.push_back(L"fodp"); list.m_presentations.push_back(L"key"); list.m_presentations.push_back(L"odg"); list.m_presentations.push_back(L"odp"); list.m_presentations.push_back(L"otp"); list.m_presentations.push_back(L"pot"); list.m_presentations.push_back(L"potm"); list.m_presentations.push_back(L"potx"); list.m_presentations.push_back(L"pps"); list.m_presentations.push_back(L"ppsm"); list.m_presentations.push_back(L"ppsx"); list.m_presentations.push_back(L"ppt"); list.m_presentations.push_back(L"pptm"); list.m_presentations.push_back(L"pptx"); list.m_presentations.push_back(L"sxi"); list.m_spreadsheets.push_back(L"xlst"); list.m_spreadsheets.push_back(L"csv"); list.m_spreadsheets.push_back(L"et"); list.m_spreadsheets.push_back(L"ett"); list.m_spreadsheets.push_back(L"fods"); list.m_spreadsheets.push_back(L"numbers"); list.m_spreadsheets.push_back(L"ods"); list.m_spreadsheets.push_back(L"ots"); list.m_spreadsheets.push_back(L"sxc"); list.m_spreadsheets.push_back(L"xls"); list.m_spreadsheets.push_back(L"xlsb"); list.m_spreadsheets.push_back(L"xlsm"); list.m_spreadsheets.push_back(L"xlsx"); list.m_spreadsheets.push_back(L"xlt"); list.m_spreadsheets.push_back(L"xltm"); list.m_spreadsheets.push_back(L"xltx"); list.m_crossplatform.push_back(L"djvu"); list.m_crossplatform.push_back(L"xps"); list.m_crossplatform.push_back(L"ofd"); list.m_draw.push_back(L"vsdx"); list.m_pdf = L"pdf"; return list; } CFormatsList CFormatsList::GetOutputExts() { CFormatsList list; list.m_documents.push_back(L"doct"); list.m_documents.push_back(L"docm"); list.m_documents.push_back(L"docx"); list.m_documents.push_back(L"docxf"); list.m_documents.push_back(L"dotm"); list.m_documents.push_back(L"dotx"); list.m_documents.push_back(L"epub"); list.m_documents.push_back(L"fb2"); list.m_documents.push_back(L"html"); list.m_documents.push_back(L"odt"); list.m_documents.push_back(L"ott"); list.m_documents.push_back(L"rtf"); list.m_documents.push_back(L"txt"); list.m_presentations.push_back(L"pptt"); list.m_presentations.push_back(L"odp"); list.m_presentations.push_back(L"otp"); list.m_presentations.push_back(L"potm"); list.m_presentations.push_back(L"potx"); list.m_presentations.push_back(L"ppsm"); list.m_presentations.push_back(L"ppsx"); list.m_presentations.push_back(L"pptm"); list.m_presentations.push_back(L"pptx"); list.m_spreadsheets.push_back(L"xlst"); list.m_spreadsheets.push_back(L"csv"); list.m_spreadsheets.push_back(L"ods"); list.m_spreadsheets.push_back(L"ots"); list.m_spreadsheets.push_back(L"xlsb"); list.m_spreadsheets.push_back(L"xlsm"); list.m_spreadsheets.push_back(L"xlsx"); list.m_spreadsheets.push_back(L"xltm"); list.m_spreadsheets.push_back(L"xltx"); list.m_crossplatform.push_back(L"djvu"); list.m_crossplatform.push_back(L"xps"); list.m_images.push_back(L"jpg"); list.m_images.push_back(L"png"); list.m_pdf = L"pdf"; return list; } CFormatsList CFormatsList::GetExtractExts() { CFormatsList list; list.m_images.push_back(L"emf"); list.m_images.push_back(L"wmf"); return list; } Cx2tTester::Cx2tTester(const std::wstring& configPath) { m_bIsUseSystemFonts = true; m_bIsErrorsOnly = false; m_bIsTimestamp = true; m_bIsDeleteOk = false; m_bIsFilenameCsvTxtParams = true; m_bIsFilenamePassword = true; m_bTroughConversion = false; m_bSaveEnvironment = false; m_bExtract = false; m_bConvertBeforeExtract = false; m_defaultCsvDelimiter = L";"; m_defaultCsvTxtEndcoding = L"UTF-8"; m_inputFormatsList = CFormatsList::GetDefaultExts(); m_outputFormatsList = CFormatsList::GetOutputExts(); m_extractFormatsList = CFormatsList::GetExtractExts(); m_timeout = 5 * 60; // 5 min SetConfig(configPath); m_errorsXmlDirectory = m_outputDirectory + FILE_SEPARATOR_STR + L"_errors"; m_troughConversionDirectory = m_outputDirectory + FILE_SEPARATOR_STR + L"_t"; m_tempDirectory = m_outputDirectory + FILE_SEPARATOR_STR + L"_temp"; m_fontsDirectory = NSFile::GetProcessDirectory() + FILE_SEPARATOR_STR + L"fonts"; // CorrectPathW works strange with directories starts with "./" if(m_outputDirectory.find(L"./") == 0) m_outputDirectory.erase(0, 2); // no slash at the end if(m_outputDirectory.size() > 2 && m_outputDirectory[m_outputDirectory.size() - 1] == L'/') m_outputDirectory.erase(m_outputDirectory.size() - 1, 1); // on linux the backslash can be part of the filename #ifdef WIN32 if(m_outputDirectory.size() > 2 && m_outputDirectory[m_outputDirectory.size() - 1] == L'\\') m_outputDirectory.erase(m_outputDirectory.size() - 1, 1); #endif if(m_bIsTimestamp) { time_t now = time(0); std::tm* time = std::localtime(&now); std::wstring timestamp = std::to_wstring(time->tm_mday) + L"_" + std::to_wstring(time->tm_mon + 1) + L"_" + std::to_wstring(time->tm_year + 1900) + L"_" + std::to_wstring(time->tm_hour) + L"_" + std::to_wstring(time->tm_min) + L"_" + std::to_wstring(time->tm_sec); std::wstring report_ext = NSFile::GetFileExtention(m_reportFile); m_reportFile = m_reportFile.substr(0, m_reportFile.size() - report_ext.size() - 1); m_reportFile += L"_" + timestamp + L"." + report_ext; } if(NSFile::CFileBinary::Exists(m_reportFile)) NSFile::CFileBinary::Remove(m_reportFile); if(!m_reportStream.CreateFileW(m_reportFile)) { std::cerr << "Report file is not open!" << std::endl; exit(-1); } m_coresCS.InitializeCriticalSection(); m_reportCS.InitializeCriticalSection(); m_outputCS.InitializeCriticalSection(); m_currentProc = 0; WriteReportHeader(); } Cx2tTester::~Cx2tTester() { m_coresCS.DeleteCriticalSection(); m_reportCS.DeleteCriticalSection(); m_outputCS.DeleteCriticalSection(); m_reportStream.CloseFile(); for(auto&& val : m_deleteLaterFiles) NSFile::CFileBinary::Remove(val); for(auto&& val : m_deleteLaterDirectories) NSDirectory::DeleteDirectory(val); } void Cx2tTester::SetConfig(const std::wstring& configPath) { bool default_input_formats = true; bool default_output_formats = true; XmlUtils::CXmlNode root; std::vector nodes; if(root.FromXmlFile(configPath) && root.GetChilds(nodes)) { for(size_t i = 0; i < nodes.size(); i++) { XmlUtils::CXmlNode node = nodes[i]; std::wstring name = node.GetName(); // key-value if(name == L"reportPath") m_reportFile = node.GetText(); else if(name == L"inputDirectory") m_inputDirectory = node.GetText(); else if(name == L"outputDirectory") m_outputDirectory = node.GetText(); else if(name == L"x2tPath") m_x2tPath = node.GetText(); else if(name == L"cores") m_maxProc = std::stoi(node.GetText()); else if(name == L"errorsOnly" && !node.GetText().empty()) m_bIsErrorsOnly = std::stoi(node.GetText()); else if(name == L"timestamp" && !node.GetText().empty()) m_bIsTimestamp = std::stoi(node.GetText()); else if(name == L"deleteOk" && !node.GetText().empty()) m_bIsDeleteOk = std::stoi(node.GetText()); else if(name == L"timeout" && !node.GetText().empty()) m_timeout = std::stoi(node.GetText()); else if(name == L"filenameCsvTxtParams" && !node.GetText().empty()) m_bIsFilenameCsvTxtParams = std::stoi(node.GetText()); else if(name == L"filenamePassword" && !node.GetText().empty()) m_bIsFilenamePassword = std::stoi(node.GetText()); else if(name == L"troughConversion" && !node.GetText().empty()) m_bTroughConversion = std::stoi(node.GetText()); else if(name == L"saveEnvironment" && !node.GetText().empty()) m_bSaveEnvironment = std::stoi(node.GetText()); else if(name == L"defaultCsvTxtEncoding" && !node.GetText().empty()) m_defaultCsvTxtEndcoding = node.GetText(); else if(name == L"extract" && !node.GetText().empty()) m_bExtract = std::stoi(node.GetText()); else if(name == L"convertBeforeExtract" && !node.GetText().empty()) m_bConvertBeforeExtract = std::stoi(node.GetText()); else if(name == L"defaultCsvDelimiter" && !node.GetText().empty()) m_defaultCsvDelimiter = (wchar_t)std::stoi(node.GetText(), nullptr, 16); else if(name == L"inputFilesList" && !node.GetText().empty()) { XmlUtils::CXmlNode files_list_root; std::vector files_list_nodes; std::wstring files_list = node.GetText(); if(files_list_root.FromXmlFile(files_list) && files_list_root.GetChilds(files_list_nodes)) { for(size_t j = 0; j < files_list_nodes.size(); j++) { XmlUtils::CXmlNode &n = files_list_nodes[j]; m_inputFiles.push_back(n.GetText()); } } else { std::cerr << "Input files list is not open!" << std::endl; } } else if(name == L"input" && !node.GetText().empty()) { default_input_formats = false; std::wstring extensions = node.GetText(); extensions += L' '; m_inputExts = ParseExtensionsString(extensions, m_inputFormatsList); } else if(name == L"output" && !node.GetText().empty()) { default_output_formats = false; std::wstring extensions = node.GetText(); extensions += L' '; m_outputExts = ParseExtensionsString(extensions, m_outputFormatsList); } else if (name == L"fonts") { m_bIsUseSystemFonts = (1 == node.ReadAttributeInt(L"system", 1)) ? true : false; std::vector oNodeFontDirs = node.ReadNodesNoNS(L"directory"); for (size_t nIndex = 0, nCount = oNodeFontDirs.size(); nIndex < nCount; ++nIndex) { XmlUtils::CXmlNode &oNodeDir = oNodeFontDirs[nIndex]; m_arAdditionalFontsDirs.push_back(oNodeDir.GetText()); } } } } else { std::cerr << "Config file is not open!" << std::endl; exit(-1); } if (default_input_formats) m_inputExts = m_inputFormatsList.GetAllExts(); if (default_output_formats) { if (m_bExtract) m_outputExts = m_extractFormatsList.GetAllExts(); else m_outputExts = m_outputFormatsList.GetAllExts(); } } void Cx2tTester::Start() { // setup timer m_timeStart = NSTimers::GetTickCount(); m_outputDirectory = CorrectPathW(m_outputDirectory); m_errorsXmlDirectory = CorrectPathW(m_errorsXmlDirectory); m_troughConversionDirectory = CorrectPathW(m_troughConversionDirectory); m_tempDirectory = CorrectPathW(m_tempDirectory); // setup & clear output folder if(NSDirectory::Exists(m_outputDirectory)) NSDirectory::DeleteDirectory(m_outputDirectory); NSDirectory::CreateDirectory(m_outputDirectory); // setup & clear errors folder if(NSDirectory::Exists(m_errorsXmlDirectory)) NSDirectory::DeleteDirectory(m_errorsXmlDirectory); NSDirectory::CreateDirectory(m_errorsXmlDirectory); // check fonts CApplicationFontsWorker fonts_worker; fonts_worker.m_sDirectory = m_fontsDirectory; if (!NSDirectory::Exists(fonts_worker.m_sDirectory)) NSDirectory::CreateDirectory(fonts_worker.m_sDirectory); fonts_worker.m_bIsUseSystemFonts = m_bIsUseSystemFonts; for (std::vector::iterator i = m_arAdditionalFontsDirs.begin(); i != m_arAdditionalFontsDirs.end(); i++) { std::wstring sFolder = *i; if (0 == sFolder.find(L".")) sFolder = NSFile::GetProcessDirectory() + FILE_SEPARATOR_STR + sFolder; fonts_worker.m_arAdditionalFolders.push_back(sFolder); } fonts_worker.m_bIsNeedThumbnails = false; NSFonts::IApplicationFonts* pFonts = fonts_worker.Check(); RELEASEINTERFACE(pFonts); std::vector files = NSDirectory::GetFiles(m_inputDirectory, true); for(int i = 0; i < files.size(); i++) { std::wstring& input_file = files[i]; std::wstring input_filename = NSFile::GetFileName(input_file); std::wstring input_ext = GetFileExtLower(input_file); // if no format in input formats - skip if(std::find(m_inputExts.begin(), m_inputExts.end(), input_ext) == m_inputExts.end() || (std::find(m_inputFiles.begin(), m_inputFiles.end(), input_filename) == m_inputFiles.end() && !m_inputFiles.empty())) { files.erase(files.begin() + i); i--; } } if (m_bExtract) { COfficeFileFormatChecker checker; COfficeUtils utils; std::vector files_to_convert; for (size_t i = 0; i < files.size(); i++) if (utils.IsArchive(files[i]) == S_FALSE && checker.isOfficeFile(files[i])) { if (m_bConvertBeforeExtract) files_to_convert.push_back(files[i]); files.erase(files.begin() + i); } if (!files_to_convert.empty()) { if(NSDirectory::Exists(m_tempDirectory)) NSDirectory::DeleteDirectory(m_tempDirectory); NSDirectory::CreateDirectories(m_tempDirectory); auto copy_inputDirectory = m_inputDirectory; auto copy_outputDirectory = m_outputDirectory; auto copy_outputExts = m_outputExts; m_outputDirectory = m_tempDirectory; m_outputExts = {L"docx"}; Convert(files_to_convert, true, true); m_outputDirectory = copy_outputDirectory; m_outputExts = copy_outputExts; m_inputDirectory = m_tempDirectory; std::vector temp_files = NSDirectory::GetFiles(m_tempDirectory, true); Extract(temp_files); m_inputDirectory = copy_inputDirectory; } Extract(files); if(NSDirectory::Exists(m_tempDirectory)) NSDirectory::DeleteDirectory(m_tempDirectory); return; } // conversion in _t directory -> _t directory to output if(m_bTroughConversion) { if(NSDirectory::Exists(m_troughConversionDirectory)) NSDirectory::DeleteDirectory(m_troughConversionDirectory); NSDirectory::CreateDirectory(m_troughConversionDirectory); auto copy_outputDirectory = m_outputDirectory; auto copy_outputExts = m_outputExts; m_outputDirectory = m_troughConversionDirectory; m_outputExts = {L"doct", L"xlst", L"pptt"}; Convert(files, true, true); m_outputDirectory = copy_outputDirectory; m_inputExts = m_outputExts; m_outputExts = copy_outputExts; m_inputDirectory = m_troughConversionDirectory; files = NSDirectory::GetFiles(m_troughConversionDirectory, true); } Convert(files); WriteTime(); } void Cx2tTester::Convert(const std::vector& files, bool bNoDirectory, bool bTrough) { if(files.size() < m_maxProc) m_maxProc = files.size(); for(int i = 0; i < files.size(); i++) { const std::wstring& input_file = files[i]; std::wstring input_filename = NSFile::GetFileName(input_file); std::wstring input_ext = GetFileExtLower(input_file); std::wstring input_file_directory = NSFile::GetDirectoryName(input_file); // takes full directory after input folder std::wstring input_subfolders = input_file_directory.substr(m_inputDirectory.size(), input_file_directory.size() - m_inputDirectory.size()); std::wstring output_files_directory = m_outputDirectory + input_subfolders; if(!bNoDirectory) output_files_directory += FILE_SEPARATOR_STR + input_filename; // setup output_formats for file std::vector output_file_exts; for(auto& ext : m_outputExts) { // documents -> documents if(((m_outputFormatsList.IsDocument(ext) && m_inputFormatsList.IsDocument(input_ext)) // spreadsheets -> spreadsheets || (m_outputFormatsList.IsSpreadsheet(ext) && m_inputFormatsList.IsSpreadsheet(input_ext)) //presentations -> presentations || (m_outputFormatsList.IsPresentation(ext) && m_inputFormatsList.IsPresentation(input_ext)) // xps -> docx || (ext == L"docx" && input_ext == L"xps") // pdf -> docx || (ext == L"docx" && m_inputFormatsList.IsPdf(input_ext)) // pdf/pptx -> txt || (ext == L"txt" && (input_ext == L"pdf" || input_ext == L"pptx")) // all formats -> images || m_outputFormatsList.IsImage(ext) // all formats -> pdf || m_outputFormatsList.IsPdf(ext)) // input format != output format && ext != input_ext // any good input ext && m_inputFormatsList.IsAny(input_ext)) { output_file_exts.push_back(ext); } } if(output_file_exts.empty()) continue; // setup & clear output subfolder if (!NSDirectory::Exists(output_files_directory)) NSDirectory::CreateDirectories(output_files_directory); std::wstring csvTxtEncodingS = m_defaultCsvTxtEndcoding; std::wstring csvDelimiter = m_defaultCsvDelimiter; // setup csv & txt additional params if(m_bIsFilenameCsvTxtParams || input_ext == L"txt" || input_ext == L"csv") { std::wstring find_str = L"[cp"; size_t pos1 = input_filename.find(find_str); size_t pos2 = input_filename.find(L"]", pos1 + 1); if(pos1 != std::wstring::npos && pos2 != std::wstring::npos) csvTxtEncodingS = input_filename.substr(pos1 + find_str.size(), pos2 - pos1 - find_str.size()); } int csvTxtEncoding; for(auto &val : NSUnicodeConverter::Encodings) if(val.Name == U_TO_UTF8(csvTxtEncodingS)) { csvTxtEncoding = val.Index; break; } if(m_bIsFilenameCsvTxtParams || input_ext == L"csv") { std::wstring find_str = L"[del%"; size_t pos1 = input_filename.find(find_str); size_t pos2 = input_filename.find(L"]", pos1 + 1); if(pos1 != std::wstring::npos && pos2 != std::wstring::npos) csvDelimiter = (wchar_t)std::stoi(input_filename.substr(pos1 + find_str.size(), pos2 - pos1 - find_str.size()), nullptr, 16); } std::wstring password; if(m_bIsFilenamePassword) { std::wstring find_str = L"[pass"; size_t pos1 = input_filename.find(find_str); size_t pos2 = input_filename.find(L"]", pos1 + 1); if(pos1 != std::wstring::npos && pos2 != std::wstring::npos) password = input_filename.substr(pos1 + find_str.size(), pos2 - pos1 - find_str.size()); } // waiting... do { NSThreads::Sleep(50); } while(IsAllBusy()); m_coresCS.Enter(); // setup & start new coverter CConverter *converter = new CConverter(this); converter->SetInputFile(input_file); converter->SetInputExt(input_ext); converter->SetOutputFilesDirectory(output_files_directory); converter->SetOutputExts(output_file_exts); converter->SetFontsDirectory(m_fontsDirectory); converter->SetX2tPath(m_x2tPath); converter->SetErrorsOnly(m_bIsErrorsOnly); converter->SetDeleteOk(m_bIsDeleteOk); converter->SetTrough(bTrough); converter->SetXmlErrorsDirectory(m_errorsXmlDirectory); converter->SetCsvTxtEncoding(csvTxtEncoding); converter->SetCsvDelimiter(csvDelimiter); converter->SetPassword(password); converter->SetTimeout(m_timeout); converter->SetFilesCount(files.size(), i + 1); converter->SetSaveEnvironment(m_bSaveEnvironment); converter->DestroyOnFinish(); m_currentProc++; m_coresCS.Leave(); converter->Start(0); } // waiting all procs end while(!IsAllFree()) NSThreads::Sleep(150); } void Cx2tTester::Extract(const std::vector& files) { if(files.size() < m_maxProc) m_maxProc = files.size(); for (int i = 0; i < files.size(); i++) { const std::wstring& input_file = files[i]; std::wstring input_filename = NSFile::GetFileName(input_file); std::wstring input_file_directory = NSFile::GetDirectoryName(input_file); std::wstring input_subfolders = input_file_directory.substr(m_inputDirectory.size(), input_file_directory.size() - m_inputDirectory.size()); std::wstring output_files_directory = m_outputDirectory + input_subfolders + FILE_SEPARATOR_STR + input_filename; if(!NSDirectory::Exists(output_files_directory)) NSDirectory::CreateDirectories(output_files_directory); // waiting... do { NSThreads::Sleep(50); } while(IsAllBusy()); m_coresCS.Enter(); // setup & start new extractor CExtractor *extractor = new CExtractor(this); extractor->SetInputFile(input_file); extractor->SetOutputFilesDirectory(output_files_directory); extractor->SetExtractExts(m_outputExts); extractor->SetFilesCount(files.size(), i + 1); extractor->DestroyOnFinish(); m_currentProc++; m_coresCS.Leave(); extractor->Start(0); } // waiting all procs end while(!IsAllFree()) NSThreads::Sleep(150); } void Cx2tTester::WriteReportHeader() { CTemporaryCS CS(&m_reportCS); m_reportStream.WriteStringUTF8(L"Input file\t", true); m_reportStream.WriteStringUTF8(L"Output file\t", false); m_reportStream.WriteStringUTF8(L"Direction\t", false); m_reportStream.WriteStringUTF8(L"Time\t", false); m_reportStream.WriteStringUTF8(L"Input size\t", false); m_reportStream.WriteStringUTF8(L"Output size\t", false); m_reportStream.WriteStringUTF8(L"Exit code\t", false); m_reportStream.WriteStringUTF8(L"Log\n", false); } void Cx2tTester::WriteReport(const Report& report) { CTemporaryCS CS(&m_reportCS); m_reportStream.WriteStringUTF8(report.inputFile + L"\t", false); m_reportStream.WriteStringUTF8(report.outputFile + L"\t", false); m_reportStream.WriteStringUTF8(report.direction + L"\t", false); m_reportStream.WriteStringUTF8(std::to_wstring(report.time) + L"\t", false); m_reportStream.WriteStringUTF8(std::to_wstring(report.inputSize) + L"\t", false); m_reportStream.WriteStringUTF8(std::to_wstring(report.outputSize) + L"\t", false); m_reportStream.WriteStringUTF8(report.exitCode + L"\t", false); m_reportStream.WriteStringUTF8(report.log + L"\n", false); } void Cx2tTester::WriteReports(const std::vector& reports) { CTemporaryCS CS(&m_reportCS); for(auto& report : reports) { m_reportStream.WriteStringUTF8(report.inputFile + L"\t", false); m_reportStream.WriteStringUTF8(report.outputFile + L"\t", false); m_reportStream.WriteStringUTF8(report.direction + L"\t", false); m_reportStream.WriteStringUTF8(std::to_wstring(report.time) + L"\t", false); m_reportStream.WriteStringUTF8(std::to_wstring(report.inputSize) + L"\t", false); m_reportStream.WriteStringUTF8(std::to_wstring(report.outputSize) + L"\t", false); m_reportStream.WriteStringUTF8(report.exitCode + L"\t", false); m_reportStream.WriteStringUTF8(report.log + L"\n", false); } } void Cx2tTester::WriteTime() { CTemporaryCS CS(&m_reportCS); unsigned long time = NSTimers::GetTickCount() - m_timeStart; m_reportStream.WriteStringUTF8(L"Time: " + std::to_wstring(time)); } void Cx2tTester::AddDeleteLaterFile(const std::wstring& file) { m_deleteLaterFiles.push_back(file); } void Cx2tTester::AddDeleteLaterDirectory(const std::wstring& directory) { m_deleteLaterDirectories.push_back(directory); } bool Cx2tTester::IsAllBusy() { CTemporaryCS CS(&m_coresCS); return m_currentProc == m_maxProc; } bool Cx2tTester::IsAllFree() { CTemporaryCS CS(&m_coresCS); return m_currentProc == 0; } std::vector Cx2tTester::ParseExtensionsString(std::wstring extensions, const CFormatsList& fl) { std::vector exts; int pos = 0; while ((pos = extensions.find(' ')) != std::wstring::npos) { std::wstring ext = extensions.substr(0, pos); for (auto& c : ext) c = std::tolower(c); if(ext == L"documents") exts = fl.GetDocuments(); else if(ext == L"presentations") exts = fl.GetPresentations(); else if(ext == L"spreadsheets") exts = fl.GetSpreadsheets(); else if (pos != 0) exts.push_back(ext); extensions.erase(0, pos + 1); } return exts; } CConverter::CConverter(Cx2tTester* internal) : m_internal(internal) { } CConverter::~CConverter() { Stop(); } void CConverter::SetInputFile(const std::wstring& inputFile) { m_inputFile = inputFile; } void CConverter::SetInputExt(const std::wstring& inputExt) { m_inputExt = inputExt; } void CConverter::SetOutputFilesDirectory(const std::wstring& outputFilesDirectory) { m_outputFilesDirectory = outputFilesDirectory; } void CConverter::SetOutputExts(const std::vector& outputExts) { m_outputExts = outputExts; } void CConverter::SetFontsDirectory(const std::wstring& fontsDirectory) { m_fontsDirectory = fontsDirectory; } void CConverter::SetX2tPath(const std::wstring& x2tPath) { m_x2tPath = x2tPath; } void CConverter::SetErrorsOnly(bool bIsErrorsOnly) { m_bIsErrorsOnly = bIsErrorsOnly; } void CConverter::SetDeleteOk(bool bIsDeleteOk) { m_bIsDeleteOk = bIsDeleteOk; } void CConverter::SetTrough(bool bIsTrough) { m_bIsTrough = bIsTrough; } void CConverter::SetXmlErrorsDirectory(const std::wstring& errorsXmlDirectory) { m_errorsXmlDirectory = errorsXmlDirectory; } void CConverter::SetCsvTxtEncoding(int csvTxtEncoding) { m_csvTxtEncoding = csvTxtEncoding; } void CConverter::SetCsvDelimiter(const std::wstring& csvDelimiter) { m_csvDelimiter = csvDelimiter; } void CConverter::SetPassword(const std::wstring& password) { m_password = password; } void CConverter::SetTimeout(unsigned long timeout) { m_timeout = timeout; } void CConverter::SetFilesCount(int totalFiles, int currFile) { m_totalFiles = totalFiles; m_currFile = currFile; } void CConverter::SetSaveEnvironment(bool bSaveEnvironment) { m_bSaveEnvironment = bSaveEnvironment; } DWORD CConverter::ThreadProc() { std::vector reports; std::wstring input_filename = NSFile::GetFileName(m_inputFile); std::wstring input_ext = L'.' + NSFile::GetFileExtention(input_filename); std::wstring input_filename_no_ext = input_filename.substr(0, input_filename.size() - input_ext.size()); unsigned long time_file_start = NSTimers::GetTickCount(); bool is_all_ok = true; #ifdef WIN32 // x2t cannot work with normalized paths in xml if(m_outputFilesDirectory.find(L"\\\\?\\") == 0) m_outputFilesDirectory.erase(0, 4); #endif // WIN32 // input_format in many output exts for(int i = 0; i < m_outputExts.size(); i++) { std::wstring output_ext = L"."+ m_outputExts[i]; int output_format = m_checker.GetFormatByExtension(output_ext); std::wstring xml_params_filename = input_filename + L"_" + output_ext + L".xml"; std::wstring xml_params_file = m_outputFilesDirectory + FILE_SEPARATOR_STR + xml_params_filename; std::wstring output_file = m_outputFilesDirectory + FILE_SEPARATOR_STR + input_filename_no_ext + output_ext; std::wstring output_filename = NSFile::GetFileName(output_file); xml_params_file = CorrectPathW(xml_params_file); // creating temporary xml file with params NSStringUtils::CStringBuilder builder; builder.WriteString(L""); builder.WriteString(L""); builder.WriteString(L""); builder.WriteEncodeXmlString(m_inputFile); builder.WriteString(L""); builder.WriteString(L""); builder.WriteEncodeXmlString(output_file); builder.WriteString(L""); builder.WriteString(L""); if (output_format & AVS_OFFICESTUDIO_FILE_IMAGE) builder.WriteString(std::to_wstring(AVS_OFFICESTUDIO_FILE_IMAGE)); else builder.WriteString(std::to_wstring(output_format)); builder.WriteString(L""); builder.WriteString(L"./"); builder.WriteString(L"true"); builder.WriteString(L""); builder.WriteEncodeXmlString(m_fontsDirectory + FILE_SEPARATOR_STR + L"AllFonts.js"); builder.WriteString(L""); builder.WriteString(L""); builder.WriteEncodeXmlString(m_fontsDirectory); builder.WriteString(L""); if (output_format & AVS_OFFICESTUDIO_FILE_IMAGE) { builder.WriteString(L""); if (AVS_OFFICESTUDIO_FILE_IMAGE_JPG == output_format) builder.WriteString(L"3"); else builder.WriteString(L"4"); builder.WriteString(L"2falsefalse10001000"); } // csv & txt needs encoding param if(m_inputExt == L"txt" || m_inputExt == L"csv") { builder.WriteString(L""); builder.WriteEncodeXmlString(std::to_wstring(m_csvTxtEncoding)); builder.WriteString(L""); } // csv needs delimiter param if(m_inputExt == L"csv") { builder.WriteString(L""); builder.WriteEncodeXmlString(m_csvDelimiter); builder.WriteString(L""); } // password if(!m_password.empty()) { builder.WriteString(L""); builder.WriteEncodeXmlString(m_password); builder.WriteString(L""); } builder.WriteString(L"{"spreadsheetLayout":{"gridLines":true,"headings":true,"fitToHeight":1,"fitToWidth":1,"orientation":"landscape"}}"); builder.WriteString(L""); std::wstring xml_params = builder.GetData(); NSFile::CFileBinary o_xml_file; bool is_created = o_xml_file.CreateFileW(xml_params_file); if(!is_created) { m_internal->m_outputCS.Enter(); std::cout << "Error creating XML conversion file!" << std::endl; m_internal->m_outputCS.Leave(); continue; } o_xml_file.WriteStringUTF8(xml_params, true); o_xml_file.CloseFile(); #ifdef WIN32 // x2t cannot work with normalized paths in xml if(xml_params_file.find(L"\\\\?\\") == 0) xml_params_file.erase(0, 4); #endif // WIN32 bool is_timeout = false; int exit_code = NSX2T::Convert(NSFile::GetDirectoryName(m_x2tPath), xml_params_file, m_timeout, &is_timeout, m_bSaveEnvironment); bool exist; if(output_format & AVS_OFFICESTUDIO_FILE_IMAGE) exist = NSDirectory::Exists(output_file); else exist = NSFile::CFileBinary::Exists(output_file); // is everything ok bool ok = !exit_code && exist && !is_timeout; int input_size = 0; int output_size = 0; NSFile::CFileBinary b_file; b_file.OpenFile(m_inputFile); input_size = b_file.GetFileSize(); b_file.CloseFile(); // get sizes if (ok) { if(output_format & AVS_OFFICESTUDIO_FILE_IMAGE) { int total_size = 0; std::vector pages = NSDirectory::GetFiles(output_file); for(int j = 0; j < pages.size(); j++) { b_file.OpenFile(pages[j]); total_size += b_file.GetFileSize(); b_file.CloseFile(); } output_size = total_size; } else { b_file.OpenFile(output_file); output_size = b_file.GetFileSize(); b_file.CloseFile(); } } // save param xml of error conversion if(!ok) { std::wstring err_xml_file = m_errorsXmlDirectory + FILE_SEPARATOR_STR + xml_params_filename; err_xml_file = CorrectPathW(err_xml_file); NSFile::CFileBinary::SaveToFile(err_xml_file, xml_params, true); } // writing report if(!m_bIsErrorsOnly || !ok) { Cx2tTester::Report report; report.inputFile = input_filename; report.outputFile = output_filename; report.direction = m_inputExt + L"-" + output_ext.substr(1, output_ext.size() - 1); report.time = NSTimers::GetTickCount() - time_file_start; report.inputSize = input_size; report.outputSize = output_size; if(is_timeout) report.exitCode = L"TIMEOUT"; else report.exitCode = std::to_wstring(exit_code); report.log = xml_params; reports.push_back(report); } if(ok) NSFile::CFileBinary::Remove(xml_params_file); std::string input_file_UTF8 = U_TO_UTF8(input_filename); std::string output_file_UTF8 = U_TO_UTF8(output_filename); // output_CS start m_internal->m_outputCS.Enter(); std::cout << "[" << m_currFile << "/" << m_totalFiles << "](" << i + 1 << "/" << m_outputExts.size() << ") "; std::cout << "(" << m_internal->m_currentProc << " processes now) "; std::cout << input_file_UTF8 << " to " << output_file_UTF8 << " "; if(ok) std::cout << "OK"; else { is_all_ok = false; std::cout << "BAD "; if(is_timeout) std::cout << "TIMEOUT"; else if(exit_code) std::cout << exit_code; else std::cout << "NOT EXIST"; } std::cout << std::endl; m_internal->m_outputCS.Leave(); if(m_bIsDeleteOk && ok) { if(m_bIsTrough) { if(output_format & AVS_OFFICESTUDIO_FILE_IMAGE) m_internal->AddDeleteLaterDirectory(output_file); else m_internal->AddDeleteLaterFile(output_file); } else { if(output_format & AVS_OFFICESTUDIO_FILE_IMAGE) NSDirectory::DeleteDirectory(output_file); else NSFile::CFileBinary::Remove(output_file); } } } m_internal->WriteReports(reports); if(m_bIsDeleteOk && is_all_ok && !m_bIsTrough) NSDirectory::DeleteDirectory(m_outputFilesDirectory); CTemporaryCS CS(&m_internal->m_coresCS); m_internal->m_currentProc--; return 0; } CExtractor::CExtractor(Cx2tTester* internal) : m_internal(internal) { } CExtractor::~CExtractor() { Stop(); } void CExtractor::SetInputFile(const std::wstring& inputFile) { m_inputFile = inputFile; } void CExtractor::SetOutputFilesDirectory(const std::wstring& outputFilesDirectory) { m_outputFilesDirectory = outputFilesDirectory; } void CExtractor::SetExtractExts(const std::vector& extractExts) { m_extractExts = extractExts; } void CExtractor::SetFilesCount(int totalFiles, int currFile) { m_totalFiles = totalFiles; m_currFile = currFile; } DWORD CExtractor::ThreadProc() { std::wstring input_filename = NSFile::GetFileName(m_inputFile); std::wstring input_ext = L'.' + NSFile::GetFileExtention(input_filename); std::wstring input_filename_no_ext = input_filename.substr(0, input_filename.size() - input_ext.size()); for (size_t i = 0; i < m_extractExts.size(); i++) { const std::wstring& extract_ext = m_extractExts[i]; std::wstring output_folder = m_outputFilesDirectory + FILE_SEPARATOR_STR + extract_ext; // output_CS start m_internal->m_outputCS.Enter(); std::cout << "[" << m_currFile << "/" << m_totalFiles << "](" << i + 1 << "/" << m_extractExts.size() << ") "; std::cout << "(" << m_internal->m_currentProc << " processes now) "; std::cout << U_TO_UTF8(input_filename) << " extract " << U_TO_UTF8(extract_ext) << " "; std::cout << std::endl; m_internal->m_outputCS.Leave(); if (NSDirectory::Exists(output_folder)) NSDirectory::DeleteDirectory(output_folder); NSDirectory::CreateDirectories(output_folder); std::wstring temp_folder = NSDirectory::CreateDirectoryWithUniqueName(output_folder); m_utils.ExtractToDirectory(m_inputFile, temp_folder, nullptr, false); auto unzip_files = NSDirectory::GetFiles(temp_folder, true); bool delete_empty = true; for (const auto& file : unzip_files) { if (NSFile::GetFileExtention(file) == m_extractExts[i]) { delete_empty = false; NSFile::CFileBinary::Move(file, output_folder + FILE_SEPARATOR_STR +NSFile::GetFileName(file)); } } if (delete_empty) NSDirectory::DeleteDirectory(output_folder); NSDirectory::DeleteDirectory(temp_folder); } if (NSDirectory::GetFilesCount(m_outputFilesDirectory, true) == 0) NSDirectory::DeleteDirectory(m_outputFilesDirectory); m_internal->m_currentProc--; return 0; }