diff --git a/ASCOfficePPTXFile/Editor/BinaryFileReaderWriter.cpp b/ASCOfficePPTXFile/Editor/BinaryFileReaderWriter.cpp index b3cd75c8d6..f4db46a578 100644 --- a/ASCOfficePPTXFile/Editor/BinaryFileReaderWriter.cpp +++ b/ASCOfficePPTXFile/Editor/BinaryFileReaderWriter.cpp @@ -2128,9 +2128,9 @@ namespace NSBinPptxRW { _UINT16 nValue = GetUChar(); if(0 != (nValue & 0x80)) - { + { BYTE nPart = GetUChar(); - nValue = (nValue & 0x7F) | ((nPart & 0x7F) << 7); + nValue = (nValue & 0x7F) | ((nPart & 0x7F) << 7); } return nValue; } @@ -2140,7 +2140,7 @@ namespace NSBinPptxRW } _UINT32 CBinaryFileReader::XlsbReadRecordLength() { - _UINT16 nValue = 0; + _UINT32 nValue = 0; for (int i = 0; i < 4; ++i) { BYTE nPart = GetUChar(); diff --git a/ASCOfficePPTXFile/Editor/BinaryFileReaderWriter.h b/ASCOfficePPTXFile/Editor/BinaryFileReaderWriter.h index 857bfcd3e4..dc37940486 100644 --- a/ASCOfficePPTXFile/Editor/BinaryFileReaderWriter.h +++ b/ASCOfficePPTXFile/Editor/BinaryFileReaderWriter.h @@ -512,7 +512,7 @@ namespace NSBinPptxRW class CBinaryFileReader { - private: + protected: BYTE* m_pData; LONG m_lSize; LONG m_lPos; diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFRecord.cpp b/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFRecord.cpp index 5716ad7965..f148552a12 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFRecord.cpp +++ b/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFRecord.cpp @@ -129,6 +129,58 @@ CFRecord::CFRecord(NSFile::CFileBinary &file, GlobalWorkbookInfoPtr global_info) } } +CFRecord::CFRecord(NSBinPptxRW::CBinaryFileReader &reader, GlobalWorkbookInfoPtr global_info) +: rdPtr(0), + size_(0), + data_(NULL), + global_info_(global_info) +{ + file_ptr = reinterpret_cast(reader.GetPointer(0)) ; + BYTE lenght = 0; + _UINT32 size = 0; + if (reader.GetPos() + 2 < reader.GetSize()) + { + type_id_= reader.XlsbReadRecordType(); + size = reader.XlsbReadRecordLength(); + + std::bitset<16> typeIdBits(type_id_); + std::bitset<32> sizeBits(size); + + if(typeIdBits[7] != 0) + lenght += 2; + else lenght += 1; + + if(sizeBits[23] == 1) + lenght += 4; + else if(sizeBits[15] == 1) + lenght += 3; + else if(sizeBits[7] == 1) + lenght += 2; + else + lenght += 1; + } + + file_ptr += lenght; + /* auto lambdaDetectBusyByteCount = [] (int val) -> { + for (int i = 0; i < 4; ++i) + { + BYTE nPart = GetUChar(); + nValue |= (nPart & 0x7F) << (7 * i); + if(0 == (nPart & 0x80)) + { + break; + } + } + };*/ + if (reader.GetPos() + lenght + size_< reader.GetSize()) + { + size_ = size; + data_ = new char[size_]; + + reader.GetArray(reinterpret_cast(&data_), size_); + } +} + // Create an empty record CFRecord::CFRecord(CFRecordType::TypeId type_id, GlobalWorkbookInfoPtr global_info) : type_id_(type_id), @@ -152,15 +204,15 @@ bool CFRecord::isBOF() { switch(type_id_) { - case rt_BOF_BIFF8: + case rt_BOF_BIFF8: case rt_BOF_BIFF4: case rt_BOF_BIFF3: case rt_BOF_BIFF2: return true; default: - return false; + return false; } - return false; + return false; } const CFRecordType::TypeId CFRecord::getTypeId() const { diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFRecord.h b/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFRecord.h index 5cfa26eba9..c2a25f030e 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFRecord.h +++ b/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFRecord.h @@ -40,6 +40,8 @@ #include "../Auxiliary/HelpFunc.h" #include "../../../../ASCOfficeDocFile/DocDocxConverter/OfficeDrawing/Record.h" #include "../../../../DesktopEditor/common/File.h" +#include "../../../../ASCOfficePPTXFile/Editor/BinaryFileReaderWriter.h" +#include "../../../Common/DocxFormat/Source/XlsbFormat/RecordTypes.h" namespace XLS { @@ -48,6 +50,7 @@ class CFRecord public: CFRecord(CFStreamPtr stream, GlobalWorkbookInfoPtr global_info); // Create a record an read its data from the stream CFRecord(NSFile::CFileBinary &file, GlobalWorkbookInfoPtr global_info); // Create a record an read its data from the data stream + CFRecord(NSBinPptxRW::CBinaryFileReader &reader, GlobalWorkbookInfoPtr global_info); // Create a record an read its data from the data stream CFRecord(CFRecordType::TypeId type_id, GlobalWorkbookInfoPtr global_info); // Create an empty record ~CFRecord(); diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFStreamCacheReader.cpp b/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFStreamCacheReader.cpp index 7ed8713d61..06ff8f797f 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFStreamCacheReader.cpp +++ b/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFStreamCacheReader.cpp @@ -408,4 +408,146 @@ bool FileStreamCacheReader::isEOF() return !records_cache.size() && (file_.GetFilePosition() >= file_.GetFileSize()); } +//--------------------------------------------------------------------------------------------------------- +BinaryStreamCacheReader::BinaryStreamCacheReader( std::shared_ptr& binaryStream, GlobalWorkbookInfoPtr global_info) + : StreamCacheReader(global_info) +{ + binaryStream_ = std::make_shared(*binaryStream); +} +BinaryStreamCacheReader::~BinaryStreamCacheReader() +{ + +} +// Skip the specified number of unsigned chars without processing +void BinaryStreamCacheReader::skipNunBytes(const size_t n) +{ + binaryStream_->Seek(n); +} +// Reads the next CFRecord from the CFStream and if its type is not the desired one, caches it for the next call +CFRecordPtr BinaryStreamCacheReader::getNextRecord(const CFRecordType::TypeId desirable_type, const bool gen_except) +{ + CFRecordType::TypeId what_we_actually_read = rt_NONE; + + while(readFromStream(1)) + { + CFRecordType::TypeString rec_name = records_cache.front()->getTypeString(); + + Log::warning(rec_name); + + if (desirable_type == rt_MsoDrawingGroup) // объединяем rt_MsoDrawingGroup + rt_Continue в один блок + { + if (checkNextRecord(desirable_type, 1)) + { + readFromStream(2); + + for(std::list::iterator good = records_cache.begin(), it = ++records_cache.begin(); + it != records_cache.end(); ++it, ++good) + { + while ((it != records_cache.end()) && (desirable_type == (*it)->getTypeId())) + { + (*good)->appendRawData(*it); + records_cache.erase(it); + if (binaryStream_->GetPos() < binaryStream_->GetSize()) + { + records_cache.push_back(CFRecordPtr(new CFRecord(*binaryStream_, global_info_))); + } + it = good; + ++it; + } + } + } + } + + if(0 == rec_name.length()) + { + Log::warning(L"The extracted record has obsoleted or unknown type(0x" + STR::int2hex_wstr(records_cache.front()->getTypeId(), sizeof(CFRecordType::TypeId)) + L")"); + records_cache.pop_front(); + continue; + } + if(skippable_records_names.end() != std::find(skippable_records_names.begin(), skippable_records_names.end(), rec_name)) + { + //Log::warning("The extracted record has been skipped (" + rec_name + ")"); + records_cache.pop_front(); + continue; + } + break; + } + + if(0 != records_cache.size()) + { + what_we_actually_read = records_cache.front()->getTypeId(); + + // if we get what was requested + if ( desirable_type == what_we_actually_read || + desirable_type == CFRecordType::ANY_TYPE || + (desirable_type == rt_BOF_BIFF8 && (what_we_actually_read == rt_BOF_BIFF4 || + what_we_actually_read == rt_BOF_BIFF3 || what_we_actually_read == rt_BOF_BIFF2))) + { + CFRecordPtr ret = records_cache.front(); + records_cache.pop_front(); + return ret; + } + } + + if(gen_except) + { + // теги разные + std::string inType = XLS::CFRecordType::getStringById(desirable_type); + std::string outType = CFRecordType::getStringById(what_we_actually_read); + + Log::warning("The extracted record is not of requested type.\nRequested: \"" + + XLS::CFRecordType::getStringById(desirable_type) + "\" Extracted: \"" + CFRecordType::getStringById(what_we_actually_read) + "\""); + } + return CFRecordPtr(); +} +// Make sure the internal buffer has concrete number of records. Returns number of records read +const size_t BinaryStreamCacheReader::readFromStream(const size_t num_of_records_min_necessary) +{ + const size_t current_records_num = records_cache.size(); + if (current_records_num >= num_of_records_min_necessary) + { + return current_records_num; + } + + while (records_cache.size() < num_of_records_min_necessary && binaryStream_->GetPos() < binaryStream_->GetSize()) + { + records_cache.push_back(CFRecordPtr(new CFRecord(*binaryStream_, global_info_))); + } + + checkAndAppendContinueData(); + return records_cache.size(); +} + +// Checks whether the next record is Continue and append its data to the real record if so +void BinaryStreamCacheReader::checkAndAppendContinueData() +{ + if (!records_cache.size()) + { + return; + } + + for (std::list::iterator good = records_cache.begin(), it = ++records_cache.begin(); + it != records_cache.end(); ++it, ++good) + { + size_t typeRecord = (*it)->getTypeId(); + while (it != records_cache.end() && (rt_Continue == (*it)->getTypeId()) ) + { + (*good)->appendRawData(*it); + records_cache.erase(it); // now 'it' is invalid + if (binaryStream_->GetPos() < binaryStream_->GetSize()) + { + records_cache.push_back(CFRecordPtr(new CFRecord(*binaryStream_, global_info_))); + } + it = good; + ++it; // Now it may became end(), checked in 'for' + } + } +} + +bool BinaryStreamCacheReader::isEOF() +{ + return !records_cache.size() && (binaryStream_->GetPos() >= binaryStream_->GetSize()); +} + + } // namespace XLS diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFStreamCacheReader.h b/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFStreamCacheReader.h index fcaa258479..a92a5244cb 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFStreamCacheReader.h +++ b/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFStreamCacheReader.h @@ -35,6 +35,7 @@ #include "BinSmartPointers.h" #include "../Logic/GlobalWorkbookInfo.h" #include "../Logic/Biff_structures/ODRAW/OfficeArtRecordHeader.h" +#include "../../../../ASCOfficePPTXFile/Editor/BinaryFileReaderWriter.h" namespace XLS { @@ -113,4 +114,19 @@ private: virtual const size_t readFromStream(const size_t num_of_records_min_necessary); NSFile::CFileBinary file_; }; + +class BinaryStreamCacheReader : public StreamCacheReader +{ +public: + BinaryStreamCacheReader(std::shared_ptr& binaryStream, const GlobalWorkbookInfoPtr global_info); + virtual ~BinaryStreamCacheReader(); + + CFRecordPtr getNextRecord(const CFRecordType::TypeId desirable_type, const bool gen_except = false) override; + void skipNunBytes(const size_t n) override; + void checkAndAppendContinueData() override; + bool isEOF() override; +private: + const size_t readFromStream(const size_t num_of_records_min_necessary) override; + std::shared_ptr binaryStream_; +}; } // namespace XLS diff --git a/Common/DocxFormat/Source/Utility/SafeQueue.h b/Common/DocxFormat/Source/Utility/SafeQueue.h deleted file mode 100644 index 5baab30d54..0000000000 --- a/Common/DocxFormat/Source/Utility/SafeQueue.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef SAFEQUEUE_H -#define SAFEQUEUE_H - -#include -#include -#include - -// A threadsafe-queue. -template -class SafeQueue -{ -public: - SafeQueue(void) - : q() - , m() - , c() - , isEmpty(true) - {} - - ~SafeQueue(void) - {} - - // Add an element to the queue. - void enqueue(T t) - { - std::lock_guard lock(m); - q.push(t); - isEmpty = false; - c.notify_one(); - } - - // Get the "front"-element. - // If the queue is empty, wait till a element is avaiable. - T dequeue(void) - { - std::unique_lock lock(m); - while(q.empty()) - { - // release lock as long as the wait and reaquire it afterwards. - if(isEmpty) - return nullptr; - c.wait(lock); - if(isEmpty) - return nullptr; - } - T val = q.front(); - q.pop(); - return val; - } - - void stopwait() - { - isEmpty = true; - c.notify_one(); - } - -private: - std::queue q; - mutable std::mutex m; - std::condition_variable c; - bool isEmpty; -}; -#endif // SAFEQUEUE_H diff --git a/Common/DocxFormat/Source/XlsbFormat/BaseRecord.h b/Common/DocxFormat/Source/XlsbFormat/Biff12RecordBase.h similarity index 100% rename from Common/DocxFormat/Source/XlsbFormat/BaseRecord.h rename to Common/DocxFormat/Source/XlsbFormat/Biff12RecordBase.h diff --git a/Common/DocxFormat/Source/XlsbFormat/BIFF12Reader.h b/Common/DocxFormat/Source/XlsbFormat/Biff12StreamReader.h similarity index 100% rename from Common/DocxFormat/Source/XlsbFormat/BIFF12Reader.h rename to Common/DocxFormat/Source/XlsbFormat/Biff12StreamReader.h diff --git a/Common/DocxFormat/Source/XlsbFormat/Biff12Structures/Biff12StructureBase.h b/Common/DocxFormat/Source/XlsbFormat/Biff12Structures/Biff12StructureBase.h new file mode 100644 index 0000000000..8fa4255f4a --- /dev/null +++ b/Common/DocxFormat/Source/XlsbFormat/Biff12Structures/Biff12StructureBase.h @@ -0,0 +1,84 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2021 + * + * This program is a free software product. You can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License (AGPL) + * version 3 as published by the Free Software Foundation. In accordance with + * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect + * that Ascensio System SIA expressly excludes the warranty of non-infringement + * of any third-party rights. + * + * This program is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For + * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html + * + * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha + * street, Riga, Latvia, EU, LV-1050. + * + * The interactive user interfaces in modified source and object code versions + * of the Program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU AGPL version 3. + * + * Pursuant to Section 7(b) of the License you must retain the original Product + * logo when distributing the program. Pursuant to Section 7(e) we decline to + * grant you any rights under trademark law for use of our trademarks. + * + * All the Product's GUI elements, including illustrations and icon sets, as + * well as technical writing content are licensed under the terms of the + * Creative Commons Attribution-ShareAlike 4.0 International. See the License + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * + */ + +#ifndef BASERECORD_H +#define BASERECORD_H + + +#include "../../../../DesktopEditor/common/Types.h" +#include "../Base/Types_32.h" +#include "../XlsxFormat/WritingElement.h" +//#include "../../../mnt/HDD_DATA/Work/core/DesktopEditor/common/File.h" +#include +#include +#include +#include "RecordTypes.h" +#include "Common/BinaryBiff12StreamReader.h" +typedef BYTE *LPBYTE; + +namespace XLSB { + + class CBiff12RecordBase + { + //DWORD m_nReclen; + //BYTE* m_pData; + //CF_RECORD_TYPE m_eRecordType; + + public: + virtual void Read(LPBYTE p, DWORD recid, DWORD reclen) { + /* m_pData = p; + m_nReclen = reclen; + m_eRecordType = biff12TypeRecord.find(recid) != biff12TypeRecord.end()? + biff12TypeRecord.find(recid)->second : rt_UNKNOWN;*/ + } + + virtual std::string GetTag() { + return "OVERRIDETHIS"; + } + + virtual CF_RECORD_TYPE GetRecordType() { + return rt_UNKNOWN; + } + + //DWORD getLengthRecord() + //{ + // return m_nReclen; + //} + + virtual ~CBiff12RecordBase() {} + + }; + +} + +#endif // BASERECORD_H +