From 4f0b889f046f9f3ad0314ad54550289e227602e7 Mon Sep 17 00:00:00 2001 From: Oleg Korshul Date: Mon, 11 Sep 2017 18:44:52 +0300 Subject: [PATCH] first version zip reader (doctrenderer) --- DesktopEditor/doctrenderer/nativecontrol.cpp | 112 +++++++++++++ DesktopEditor/doctrenderer/nativecontrol.h | 136 ++++++++++++++++ .../fontengine/application_generate_fonts.h | 114 +------------ .../application_generate_fonts_common.h | 153 ++++++++++++++++++ 4 files changed, 402 insertions(+), 113 deletions(-) create mode 100644 DesktopEditor/fontengine/application_generate_fonts_common.h diff --git a/DesktopEditor/doctrenderer/nativecontrol.cpp b/DesktopEditor/doctrenderer/nativecontrol.cpp index 72af84f368..94ec1dc7e8 100644 --- a/DesktopEditor/doctrenderer/nativecontrol.cpp +++ b/DesktopEditor/doctrenderer/nativecontrol.cpp @@ -305,6 +305,112 @@ void _SaveChanges(const v8::FunctionCallbackInfo& args) pNative->DumpChanges(to_cstringA(args[0]), args[1]->Int32Value(), args[2]->Int32Value()); } +/// ZIP ----- +void _zipOpenFile(const v8::FunctionCallbackInfo& args) +{ + if (args.Length() < 1) + { + args.GetReturnValue().Set(v8::Null(v8::Isolate::GetCurrent())); + return; + } + + CNativeControl* pNative = unwrap_nativeobject(args.This()); + bool bIsOpen = pNative->m_oZipWorker.Open(to_cstring(args[0])); + if (!bIsOpen) + { + args.GetReturnValue().Set(v8::Null(v8::Isolate::GetCurrent())); + return; + } + + v8::Local obj = v8::Object::New(v8::Isolate::GetCurrent()); + for (std::vector::iterator i = pNative->m_oZipWorker.m_arFiles.begin(); i != pNative->m_oZipWorker.m_arFiles.end(); i++) + { + std::string sFile = NSFile::CUtf8Converter::GetUtf8StringFromUnicode(*i); + + v8::Local _k = v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), sFile.c_str(), v8::String::kNormalString, -1); + v8::Local _v = v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), sFile.c_str(), v8::String::kNormalString, -1); + + obj->Set(_k, _v); + } + + args.GetReturnValue().Set(obj); +} + +void _zipOpenFileBase64(const v8::FunctionCallbackInfo& args) +{ + if (args.Length() < 1) + { + args.GetReturnValue().Set(v8::Null(v8::Isolate::GetCurrent())); + return; + } + + CNativeControl* pNative = unwrap_nativeobject(args.This()); + bool bIsOpen = pNative->m_oZipWorker.OpenBase64(to_cstringA(args[0])); + if (!bIsOpen) + { + args.GetReturnValue().Set(v8::Null(v8::Isolate::GetCurrent())); + return; + } + + v8::Local obj = v8::Object::New(v8::Isolate::GetCurrent()); + for (std::vector::iterator i = pNative->m_oZipWorker.m_arFiles.begin(); i != pNative->m_oZipWorker.m_arFiles.end(); i++) + { + std::string sFile = NSFile::CUtf8Converter::GetUtf8StringFromUnicode(*i); + + v8::Local _k = v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), sFile.c_str(), v8::String::kNormalString, -1); + v8::Local _v = v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), sFile.c_str(), v8::String::kNormalString, -1); + + obj->Set(_k, _v); + } + + args.GetReturnValue().Set(obj); +} + +void _zipGetFileAsString(const v8::FunctionCallbackInfo& args) +{ + if (args.Length() < 1) + { + args.GetReturnValue().Set(v8::Null(v8::Isolate::GetCurrent())); + return; + } + + CNativeControl* pNative = unwrap_nativeobject(args.This()); + + BYTE* pData = NULL; + DWORD len = 0; + pNative->m_oZipWorker.GetFileData(to_cstring(args[0]), pData, len); + + args.GetReturnValue().Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), (char*)pData, v8::String::kNormalString, len)); +} + +void _zipGetFileAsBinary(const v8::FunctionCallbackInfo& args) +{ + if (args.Length() < 1) + { + args.GetReturnValue().Set(v8::Null(v8::Isolate::GetCurrent())); + return; + } + + CNativeControl* pNative = unwrap_nativeobject(args.This()); + + BYTE* pData = NULL; + DWORD len = 0; + pNative->m_oZipWorker.GetFileData(to_cstring(args[0]), pData, len); + + v8::Local _buffer = v8::ArrayBuffer::New(v8::Isolate::GetCurrent(), (void*)pData, (size_t)len); + v8::Local _array = v8::Uint8Array::New(_buffer, 0, (size_t)len); + + args.GetReturnValue().Set(_array); +} + +void _zipCloseFile(const v8::FunctionCallbackInfo& args) +{ + CNativeControl* pNative = unwrap_nativeobject(args.This()); + args.GetReturnValue().Set(v8::Undefined(v8::Isolate::GetCurrent())); + pNative->m_oZipWorker.Close(); +} +/// --------- + void _AddImageInChanges(const v8::FunctionCallbackInfo& args) { args.GetReturnValue().Set(v8::Undefined(v8::Isolate::GetCurrent())); @@ -397,6 +503,12 @@ v8::Handle CreateNativeControlTemplateBuilder(v8::Isolate* i result->Set(v8::String::NewFromUtf8(current, "SaveChanges"), v8::FunctionTemplate::New(current, _SaveChanges)); + result->Set(v8::String::NewFromUtf8(current, "ZipOpen"), v8::FunctionTemplate::New(current, _zipOpenFile)); + result->Set(v8::String::NewFromUtf8(current, "ZipOpenBase64"), v8::FunctionTemplate::New(current, _zipOpenFileBase64)); + result->Set(v8::String::NewFromUtf8(current, "ZipFileAsString"), v8::FunctionTemplate::New(current, _zipGetFileAsString)); + result->Set(v8::String::NewFromUtf8(current, "ZipFileAsBinary"), v8::FunctionTemplate::New(current, _zipGetFileAsBinary)); + result->Set(v8::String::NewFromUtf8(current, "ZipClose"), v8::FunctionTemplate::New(current, _zipCloseFile)); + // возвращаем временный хэндл хитрым образом, который переносит наш хэндл в предыдущий HandleScope и не дает ему // уничтожиться при уничтожении "нашего" HandleScope - handle_scope diff --git a/DesktopEditor/doctrenderer/nativecontrol.h b/DesktopEditor/doctrenderer/nativecontrol.h index fd8db72015..c2071bacd6 100644 --- a/DesktopEditor/doctrenderer/nativecontrol.h +++ b/DesktopEditor/doctrenderer/nativecontrol.h @@ -37,6 +37,130 @@ #include "../fontengine/ApplicationFonts.h" #include #include "../../graphics/Timer.h" +#include "../../common/Directory.h" +#include "../../../../OfficeUtils/src/OfficeUtils.h" +#include "../../fontengine/application_generate_fonts_common.h" + +class CZipWorker +{ +public: + std::wstring m_sTmpFolder; + + std::vector m_arFiles; + + std::wstring m_sWorkerFolder; + +public: + + CZipWorker() + { + m_sWorkerFolder = L""; + } + + ~CZipWorker() + { + Close(); + } + + void Close() + { + if (!m_sTmpFolder.empty()) + NSDirectory::DeleteDirectory(m_sTmpFolder); + + m_sTmpFolder = L""; + + m_arFiles.clear(); + } + + bool Open(const std::wstring& sFile) + { + m_sTmpFolder = m_sWorkerFolder + L"/nativeZip"; + COfficeUtils oUtils; + if (S_OK != oUtils.ExtractToDirectory(sFile, m_sTmpFolder, NULL, 0)) + return false; + + CheckDirectory(); + return true; + } + + bool OpenBase64(const std::string& sData) + { + BYTE* pRawData = NULL; + int nRawSize = 0; + if (true != NSFile::CBase64Converter::Decode(sData.c_str(), (int)sData.length(), pRawData, nRawSize)) + return false; + + std::wstring sTmpFile = NSFile::CFileBinary::CreateTempFileWithUniqueName(NSDirectory::GetTempPathW(), L"ZIP"); + if (NSFile::CFileBinary::Exists(sTmpFile)) + NSFile::CFileBinary::Remove(sTmpFile); + + NSFile::CFileBinary oFile; + oFile.CreateFileW(sTmpFile); + oFile.WriteFile(pRawData, (DWORD)nRawSize); + oFile.CloseFile(); + + m_sTmpFolder = m_sWorkerFolder + L"/nativeZip"; + + COfficeUtils oUtils; + if (S_OK != oUtils.ExtractToDirectory(sTmpFile, m_sTmpFolder, NULL, 0)) + { + NSFile::CFileBinary::Remove(sTmpFile); + return false; + } + + NSFile::CFileBinary::Remove(sTmpFile); + CheckDirectory(); + return true; + } + + void CheckDirectory() + { + std::vector arFiles = NSDirectory::GetFiles(m_sTmpFolder, true); + + url_correct2(m_sTmpFolder); + int nStart = m_sTmpFolder.length(); + for (std::vector::iterator i = arFiles.begin(); i != arFiles.end(); i++) + { + std::wstring sTmp = *i; + url_correct2(sTmp); + + m_arFiles.push_back(sTmp.substr(nStart + 1)); + } + } + + void GetFileData(const std::wstring& strFile, BYTE*& pData, DWORD& dwLen) + { + NSFile::CFileBinary oFile; + oFile.OpenFile(m_sTmpFolder + L"/" + strFile); + dwLen = (DWORD)oFile.GetFileSize(); + pData = (BYTE*)malloc((size_t)dwLen); + DWORD dwSizeRead = 0; + oFile.ReadFile(pData, dwLen, dwSizeRead); + oFile.CloseFile(); + } + +private: + + void url_correct2(std::wstring& url) + { + NSCommon::string_replace(url, L"/./", L"/"); + + size_t posn = 0; + while (std::wstring::npos != (posn = url.find(L"/../"))) + { + std::wstring::size_type pos2 = url.rfind(L"/", posn - 1); + + if (std::wstring::npos != pos2) + { + url.erase(pos2, posn - pos2 + 3); + } + } + + NSCommon::string_replace(url, L"\\\\", L"\\"); + NSCommon::string_replace(url, L"//", L"/"); + NSCommon::string_replace(url, L"\\", L"/"); + } +}; // string convert std::wstring to_cstring(v8::Local v); @@ -76,6 +200,8 @@ public: std::wstring m_sChangesBuilderPath; int m_nCurrentChangesBuilderIndex; + CZipWorker m_oZipWorker; + public: CMemoryStream* m_pStream; @@ -152,6 +278,8 @@ public: void SetFilePath(const std::wstring& strPath) { m_strFilePath = strPath; + + m_oZipWorker.m_sWorkerFolder = NSCommon::GetDirectoryName(strPath); } std::wstring GetFilePath() { @@ -324,6 +452,14 @@ void _ConsoleLog(const v8::FunctionCallbackInfo& args); void _SaveChanges(const v8::FunctionCallbackInfo& args); +/// ZIP ----- +void _zipOpenFile(const v8::FunctionCallbackInfo& args); +void _zipOpenFileBase64(const v8::FunctionCallbackInfo& args); +void _zipGetFileAsString(const v8::FunctionCallbackInfo& args); +void _zipGetFileAsBinary(const v8::FunctionCallbackInfo& args); +void _zipCloseFile(const v8::FunctionCallbackInfo& args); +/// --------- + void _AddImageInChanges(const v8::FunctionCallbackInfo& args); v8::Handle CreateNativeControlTemplate(v8::Isolate* isolate); diff --git a/DesktopEditor/fontengine/application_generate_fonts.h b/DesktopEditor/fontengine/application_generate_fonts.h index 3bd681a27b..aad005dcae 100644 --- a/DesktopEditor/fontengine/application_generate_fonts.h +++ b/DesktopEditor/fontengine/application_generate_fonts.h @@ -44,70 +44,7 @@ #include "../graphics/GraphicsRenderer.h" #endif -namespace NSCommon -{ - static void string_replace(std::wstring& text, const std::wstring& replaceFrom, const std::wstring& replaceTo) - { - size_t posn = 0; - while (std::wstring::npos != (posn = text.find(replaceFrom, posn))) - { - text.replace(posn, replaceFrom.length(), replaceTo); - posn += replaceTo.length(); - } - } - static void string_replaceA(std::string& text, const std::string& replaceFrom, const std::string& replaceTo) - { - size_t posn = 0; - while (std::string::npos != (posn = text.find(replaceFrom, posn))) - { - text.replace(posn, replaceFrom.length(), replaceTo); - posn += replaceTo.length(); - } - } - - static void url_correct(std::wstring& url) - { - string_replace(url, L"/./", L"/"); - - size_t posn = 0; - while (std::wstring::npos != (posn = url.find(L"/../"))) - { - std::wstring::size_type pos2 = url.rfind(L"/", posn - 1); - - if (std::wstring::npos != pos2) - { - url.erase(pos2, posn - pos2 + 3); - } - } - - // MAC - if (0 == url.find(L"file:/") && 0 != url.find(L"file://")) - { - url.replace(0, 6, L"file:///"); - } - } - - static void makeUpper(std::string& url) - { - int nLen = (int)url.length(); - char* pStr = (char*)url.c_str(); - - for (int i = 0; i < nLen; ++i) - { - if (pStr[i] >= 'a' && pStr[i] <= 'z') - pStr[i] = pStr[i] + 'A' - 'a'; - } - } - - static void WriteLog(const std::string& sLogFile, const std::wstring& sData) - { - FILE* f = fopen(sLogFile.c_str(), "a+"); - std::string sDataA = U_TO_UTF8(sData); - fprintf(f, sDataA.c_str()); - fprintf(f, "\n"); - fclose(f); - } -} +#include "./application_generate_fonts_common.h" /////////////////////////////////////////////////////// //#define _GENERATE_FONT_MAP_ @@ -116,55 +53,6 @@ namespace NSCommon #include "../../freetype_names/FontMaps/FontDictionary.h" #endif -namespace NSCommon -{ - static std::wstring GetFileExtention(const std::wstring& sPath) - { - std::wstring::size_type nPos = sPath.rfind('.'); - if (nPos != std::wstring::npos) - return sPath.substr(nPos + 1); - return sPath; - } - static std::wstring GetFileName(const std::wstring& sPath) - { - std::wstring::size_type nPos1 = sPath.rfind('\\'); - std::wstring::size_type nPos2 = sPath.rfind('/'); - std::wstring::size_type nPos = std::wstring::npos; - - if (nPos1 != std::wstring::npos) - { - nPos = nPos1; - if (nPos2 != std::wstring::npos && nPos2 > nPos) - nPos = nPos2; - } - else - nPos = nPos2; - - if (nPos == std::wstring::npos) - return sPath; - return sPath.substr(nPos + 1); - } - static std::wstring GetDirectoryName(const std::wstring& sPath) - { - std::wstring::size_type nPos1 = sPath.rfind('\\'); - std::wstring::size_type nPos2 = sPath.rfind('/'); - std::wstring::size_type nPos = std::wstring::npos; - - if (nPos1 != std::wstring::npos) - { - nPos = nPos1; - if (nPos2 != std::wstring::npos && nPos2 > nPos) - nPos = nPos2; - } - else - nPos = nPos2; - - if (nPos == std::wstring::npos) - return sPath; - return sPath.substr(0, nPos); - } -} - namespace NSCommon { class CFontInfoJS diff --git a/DesktopEditor/fontengine/application_generate_fonts_common.h b/DesktopEditor/fontengine/application_generate_fonts_common.h new file mode 100644 index 0000000000..1847e27321 --- /dev/null +++ b/DesktopEditor/fontengine/application_generate_fonts_common.h @@ -0,0 +1,153 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2017 + * + * 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 Lubanas st. 125a-25, Riga, Latvia, + * EU, LV-1021. + * + * 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 APPLICATION_GENERATE_FONTS_COMMON_H +#define APPLICATION_GENERATE_FONTS_COMMON_H + +#include "../common/File.h" +#include "../common/Directory.h" +#include "../common/StringBuilder.h" + +namespace NSCommon +{ + static void string_replace(std::wstring& text, const std::wstring& replaceFrom, const std::wstring& replaceTo) + { + size_t posn = 0; + while (std::wstring::npos != (posn = text.find(replaceFrom, posn))) + { + text.replace(posn, replaceFrom.length(), replaceTo); + posn += replaceTo.length(); + } + } + static void string_replaceA(std::string& text, const std::string& replaceFrom, const std::string& replaceTo) + { + size_t posn = 0; + while (std::string::npos != (posn = text.find(replaceFrom, posn))) + { + text.replace(posn, replaceFrom.length(), replaceTo); + posn += replaceTo.length(); + } + } + + static void url_correct(std::wstring& url) + { + string_replace(url, L"/./", L"/"); + + size_t posn = 0; + while (std::wstring::npos != (posn = url.find(L"/../"))) + { + std::wstring::size_type pos2 = url.rfind(L"/", posn - 1); + + if (std::wstring::npos != pos2) + { + url.erase(pos2, posn - pos2 + 3); + } + } + + // MAC + if (0 == url.find(L"file:/") && 0 != url.find(L"file://")) + { + url.replace(0, 6, L"file:///"); + } + } + + static void makeUpper(std::string& url) + { + int nLen = (int)url.length(); + char* pStr = (char*)url.c_str(); + + for (int i = 0; i < nLen; ++i) + { + if (pStr[i] >= 'a' && pStr[i] <= 'z') + pStr[i] = pStr[i] + 'A' - 'a'; + } + } + + static void WriteLog(const std::string& sLogFile, const std::wstring& sData) + { + FILE* f = fopen(sLogFile.c_str(), "a+"); + std::string sDataA = U_TO_UTF8(sData); + fprintf(f, sDataA.c_str()); + fprintf(f, "\n"); + fclose(f); + } +} + +namespace NSCommon +{ + static std::wstring GetFileExtention(const std::wstring& sPath) + { + std::wstring::size_type nPos = sPath.rfind('.'); + if (nPos != std::wstring::npos) + return sPath.substr(nPos + 1); + return sPath; + } + static std::wstring GetFileName(const std::wstring& sPath) + { + std::wstring::size_type nPos1 = sPath.rfind('\\'); + std::wstring::size_type nPos2 = sPath.rfind('/'); + std::wstring::size_type nPos = std::wstring::npos; + + if (nPos1 != std::wstring::npos) + { + nPos = nPos1; + if (nPos2 != std::wstring::npos && nPos2 > nPos) + nPos = nPos2; + } + else + nPos = nPos2; + + if (nPos == std::wstring::npos) + return sPath; + return sPath.substr(nPos + 1); + } + static std::wstring GetDirectoryName(const std::wstring& sPath) + { + std::wstring::size_type nPos1 = sPath.rfind('\\'); + std::wstring::size_type nPos2 = sPath.rfind('/'); + std::wstring::size_type nPos = std::wstring::npos; + + if (nPos1 != std::wstring::npos) + { + nPos = nPos1; + if (nPos2 != std::wstring::npos && nPos2 > nPos) + nPos = nPos2; + } + else + nPos = nPos2; + + if (nPos == std::wstring::npos) + return sPath; + return sPath.substr(0, nPos); + } +} + +#endif // APPLICATION_GENERATE_FONTS_COMMON_H