diff --git a/HtmlFile2/htmlfile2.cpp b/HtmlFile2/htmlfile2.cpp index 62304876c3..0fc17c61ab 100644 --- a/HtmlFile2/htmlfile2.cpp +++ b/HtmlFile2/htmlfile2.cpp @@ -116,7 +116,6 @@ public: NSCSS::CTree m_oTree; // Дерево body html-файла private: - int m_nImageId; // ID картинки int m_nFootnoteId; // ID сноски int m_nHyperlinkId; // ID ссылки int m_nCrossId; // ID перекрестной ссылки @@ -132,10 +131,11 @@ private: bool m_bWasPStyle; // записан? bool m_bWasSpace; // Был пробел? + std::vector m_arrImages; // Картинки std::map m_mFootnotes; // Сноски public: - CHtmlFile2_Private() : m_nImageId(1), m_nFootnoteId(1), m_nHyperlinkId(1), m_nCrossId(1), m_nNumberingId(1), m_bInP(false), m_bWasPStyle(false), m_bWasSpace(false) + CHtmlFile2_Private() : m_nFootnoteId(1), m_nHyperlinkId(1), m_nCrossId(1), m_nNumberingId(1), m_bInP(false), m_bWasPStyle(false), m_bWasSpace(false) { //Установим размер исходного и нового окна для Css калькулятора (должны быть одинаковые единицы измерения (желательно пункты)) //Это нужно для масштабирования некоторых значений @@ -1723,30 +1723,29 @@ private: sNote = L""; } - bool readBase64 (const std::wstring& sSrcM, std::wstring& sImageName) + bool readBase64 (const std::wstring& sSrcM, std::wstring& sExtention) { bool bRes = false; - size_t nBase = sSrcM.find(L"/", 4); nBase++; size_t nEndBase = sSrcM.find(L";", nBase); if (nEndBase == std::wstring::npos) return bRes; - std::wstring sType = sSrcM.substr(nBase, nEndBase - nBase); - if (sType == L"octet-stream") - sType = L"jpg"; - std::wstring sImageId = std::to_wstring(m_nImageId); - sImageName = sImageId + L"." + sType; + sExtention = sSrcM.substr(nBase, nEndBase - nBase); + if (sExtention == L"octet-stream") + sExtention = L"jpg"; nBase = sSrcM.find(L"base64", nEndBase); if (nBase == std::wstring::npos) return bRes; NSFile::CFileBinary oImageWriter; + std::wstring sImageName = std::to_wstring(m_arrImages.size()) + L'.' + sExtention; if (oImageWriter.CreateFileW(m_sDst + L"/word/media/i" + sImageName)) { - std::string sBase64 = m_oLightReader.GetTextA().substr(nBase + 7); + std::string sSrc = U_TO_UTF8(sSrcM); + std::string sBase64 = sSrc.substr(nBase + 7); int nSrcLen = (int)sBase64.length(); int nDecodeLen = NSBase64::Base64DecodeGetRequiredLength(nSrcLen); if (nDecodeLen != 0) @@ -1783,97 +1782,115 @@ private: return bRes; } - inline bool ValidExtension(const std::wstring& sSrc) + inline bool NotValidExtension(const std::wstring& sExtention) { - std::wstring sExtention = NSFile::GetFileExtention(sSrc); - std::transform(sExtention.begin(), sExtention.end(), sExtention.begin(), tolower); return sExtention != L"bmp" && sExtention != L"emf" && sExtention != L"emz" && sExtention != L"eps" && sExtention != L"fpx" && sExtention != L"gif" && sExtention != L"jpe" && sExtention != L"jpeg" && sExtention != L"jpg" && sExtention != L"jfif" && sExtention != L"pct" && sExtention != L"pict" && sExtention != L"png" && sExtention != L"pntg" && sExtention != L"psd" && sExtention != L"qtif" && sExtention != L"sgi" && sExtention != L"svg" && sExtention != L"tga" && sExtention != L"tpic" && sExtention != L"tiff" && sExtention != L"tif" && sExtention != L"wmf" && sExtention != L"wmz"; } + void ImageAlternative(NSStringUtils::CStringBuilder* oXml, std::vector& sSelectors, const CTextSettings& oTS, const std::wstring& wsAlt) + { + if (wsAlt.empty()) + return; + + wrP(oXml, sSelectors, oTS); + oXml->WriteString(L""); + wrR(oXml, sSelectors, oTS); + oXml->WriteString(L""); + oXml->WriteEncodeXmlString(wsAlt); + oXml->WriteString(L""); + } + void readImage (NSStringUtils::CStringBuilder* oXml, std::vector& sSelectors, const CTextSettings& oTS) { - std::wstring wsAlt; + std::wstring wsAlt, sSrcM; bool bRes = false; while (m_oLightReader.MoveToNextAttribute()) { std::wstring wsName = m_oLightReader.GetName(); if (wsName == L"alt") - { wsAlt = m_oLightReader.GetText(); - continue; - } - else if (wsName != L"src") - continue; - - bool bIsAllowExternalLocalFiles = true; - if (NSProcessEnv::IsPresent(NSProcessEnv::Converter::gc_allowPrivateIP)) - bIsAllowExternalLocalFiles = NSProcessEnv::GetBoolValue(NSProcessEnv::Converter::gc_allowPrivateIP); - - std::wstring sSrcM = m_oLightReader.GetText(); - std::wstring sImageName; - std::wstring sImageId = std::to_wstring(m_nImageId); - - // Предполагаем картинку в Base64 - if (sSrcM.length() > 4 && sSrcM.substr(0, 4) == L"data" && sSrcM.find(L"/", 4) != std::wstring::npos) - bRes = readBase64(sSrcM, sImageName); - - if (!bRes) - { - sImageName = NSFile::GetFileName(sSrcM); - sImageName.erase(std::remove_if(sImageName.begin(), sImageName.end(), [] (wchar_t ch) { return std::iswspace(ch) || - (ch == L'\\' || ch == L'/' || ch == L':' || ch == L'*' || ch == L'?' || ch == L'\"' || ch == L'<' || ch == L'>' || ch == L'|'); }), sImageName.end()); - - if (ValidExtension(sSrcM)) - break; - - std::wstring wsDst = m_sDst + L"/word/media/i" + sImageName; - - // Предполагаем картинку по локальному пути - if (!((!m_sBase.empty() && m_sBase.length() > 4 && m_sBase.substr(0, 4) == L"http") || (sSrcM.length() > 4 && sSrcM.substr(0, 4) == L"http"))) - { - if (!m_sBase.empty()) - { - if (!bRes) - bRes = CopyImage(NSSystemPath::Combine(m_sBase, sSrcM), wsDst, bIsAllowExternalLocalFiles); - if (!bRes) - bRes = CopyImage(NSSystemPath::Combine(m_sSrc, m_sBase + sSrcM), wsDst, bIsAllowExternalLocalFiles); - } - if (!bRes) - bRes = CopyImage(NSSystemPath::Combine(m_sSrc, sSrcM), wsDst, bIsAllowExternalLocalFiles); - if (!bRes) - bRes = CopyImage(m_sSrc + L"/" + NSFile::GetFileName(sSrcM), wsDst, bIsAllowExternalLocalFiles); - if (!bRes) - bRes = CopyImage(sSrcM, wsDst, bIsAllowExternalLocalFiles); - } - // Предполагаем картинку в сети - else - { - // Проверка gc_allowNetworkRequest предполагается в kernel_network - NSNetwork::NSFileTransport::CFileDownloader oDownloadImg(m_sBase + sSrcM, false); - oDownloadImg.SetFilePath(wsDst); - bRes = oDownloadImg.DownloadSync(); - } - } - - if (bRes) - { - wrP(oXml, sSelectors, oTS); - bRes = ImageRels(oXml, sImageId, L"i" + sImageName); - } + else if (wsName == L"src") + sSrcM = m_oLightReader.GetText(); } m_oLightReader.MoveToElement(); - if(!bRes) + if (sSrcM.empty()) + { + ImageAlternative(oXml, sSelectors, oTS, wsAlt); + return; + } + + bool bIsAllowExternalLocalFiles = true; + if (NSProcessEnv::IsPresent(NSProcessEnv::Converter::gc_allowPrivateIP)) + bIsAllowExternalLocalFiles = NSProcessEnv::GetBoolValue(NSProcessEnv::Converter::gc_allowPrivateIP); + + int nImageId = -1; + std::wstring sImageSrc, sExtention; + // Предполагаем картинку в Base64 + if (sSrcM.length() > 4 && sSrcM.substr(0, 4) == L"data" && sSrcM.find(L"/", 4) != std::wstring::npos) + bRes = readBase64(sSrcM, sExtention); + + if (!bRes) + { + // Проверка расширения + sExtention = NSFile::GetFileExtention(sSrcM); + std::transform(sExtention.begin(), sExtention.end(), sExtention.begin(), tolower); + if (NotValidExtension(sExtention)) + { + ImageAlternative(oXml, sSelectors, oTS, wsAlt); + return; + } + + // Проверка на повтор + std::vector::iterator nFind = std::find(m_arrImages.begin(), m_arrImages.end(), sSrcM); + if (nFind != m_arrImages.end()) + { + bRes = true; + nImageId = nFind - m_arrImages.begin(); + } + } + + if (!bRes) + { + sImageSrc = sSrcM; + std::wstring wsDst = m_sDst + L"/word/media/i" + std::to_wstring(m_arrImages.size()) + L'.' + sExtention; + + // Предполагаем картинку по локальному пути + if (!((!m_sBase.empty() && m_sBase.length() > 4 && m_sBase.substr(0, 4) == L"http") || (sSrcM.length() > 4 && sSrcM.substr(0, 4) == L"http"))) + { + if (!m_sBase.empty()) + { + if (!bRes) + bRes = CopyImage(NSSystemPath::Combine(m_sBase, sSrcM), wsDst, bIsAllowExternalLocalFiles); + if (!bRes) + bRes = CopyImage(NSSystemPath::Combine(m_sSrc, m_sBase + sSrcM), wsDst, bIsAllowExternalLocalFiles); + } + if (!bRes) + bRes = CopyImage(NSSystemPath::Combine(m_sSrc, sSrcM), wsDst, bIsAllowExternalLocalFiles); + if (!bRes) + bRes = CopyImage(m_sSrc + L"/" + NSFile::GetFileName(sSrcM), wsDst, bIsAllowExternalLocalFiles); + if (!bRes) + bRes = CopyImage(sSrcM, wsDst, bIsAllowExternalLocalFiles); + } + // Предполагаем картинку в сети + else + { + // Проверка gc_allowNetworkRequest предполагается в kernel_network + NSNetwork::NSFileTransport::CFileDownloader oDownloadImg(m_sBase + sSrcM, false); + oDownloadImg.SetFilePath(wsDst); + bRes = oDownloadImg.DownloadSync(); + } + } + + if (!bRes) + ImageAlternative(oXml, sSelectors, oTS, wsAlt); + else { wrP(oXml, sSelectors, oTS); - oXml->WriteString(L""); - wrR(oXml, sSelectors, oTS); - oXml->WriteString(L""); - oXml->WriteEncodeXmlString(wsAlt); - oXml->WriteString(L""); + ImageRels(oXml, nImageId, sImageSrc, sExtention); } } @@ -1967,24 +1984,34 @@ private: return sRStyle; } - bool ImageRels (NSStringUtils::CStringBuilder* oXml, const std::wstring& sImageId, const std::wstring& sImageName) + void ImageRels (NSStringUtils::CStringBuilder* oXml, int nImageId, const std::wstring& sImageSrc, const std::wstring& sExtention) { - CBgraFrame oBgraFrame; - if(!oBgraFrame.OpenFile(m_sDst + L"/word/media/" + sImageName)) - return false; + bool bNew = nImageId < 0; + if (bNew) + nImageId = m_arrImages.size(); + + std::wstring sImageId = std::to_wstring(nImageId); + std::wstring sImageName = sImageId + L'.' + sExtention; + CBgraFrame oBgraFrame; + if (!oBgraFrame.OpenFile(m_sDst + L"/word/media/i" + sImageName)) + return; - m_nImageId++; // Прописать рельсы - m_oDocXmlRels.WriteString(L""); + if (bNew) + { + m_arrImages.push_back(sImageSrc); + + m_oDocXmlRels.WriteString(L""); + } // Получаем размеры картинки int nHy = oBgraFrame.get_Height(); int nWx = oBgraFrame.get_Width(); - if(nWx > nHy) + if (nWx > nHy) { int nW = nWx * 9525; nW = (nW > 7000000 ? 7000000 : nW); @@ -1996,7 +2023,7 @@ private: int nH = nHy * 9525; nH = (nH > 8000000 ? 8000000 : nH); int nW = (int)((double)nWx * (double)nH / (double)nHy); - if(nW > 7000000) + if (nW > 7000000) { nW = 7000000; nHy = (int)((double)nHy * (double)nW / (double)nWx); @@ -2022,7 +2049,6 @@ private: oXml->WriteString(L"\" cy=\""); oXml->WriteString(std::to_wstring(nHy)); oXml->WriteString(L"\"/>"); - return true; } void readNote (NSStringUtils::CStringBuilder* oXml, std::vector& sSelectors, const std::wstring& sNote) @@ -2053,7 +2079,7 @@ private: // Сохранить как .svg картинку NSStringUtils::CStringBuilder oSVG; oSVG.WriteString(L"', nRef); size_t nHRef = sSVG.find(L"href", nRef); - if(nHRef == std::wstring::npos || nRefEnd == std::wstring::npos) + if (nHRef == std::wstring::npos || nRefEnd == std::wstring::npos) break; nHRef += 6; - if(nHRef > nRefEnd || sSVG.compare(nHRef, 4, L"http") == 0) + if (nHRef > nRefEnd || sSVG.compare(nHRef, 4, L"http") == 0) { nRef = sSVG.find(L"image", nRef + 5); continue; @@ -2107,9 +2133,9 @@ private: oSVG.WriteString(sSVG); oSVG.WriteString(L""); - std::wstring sImageId = std::to_wstring(m_nImageId); + std::wstring sImageId = std::to_wstring(m_arrImages.size()); NSFile::CFileBinary oSVGWriter; - std::wstring sImageFile = m_sDst + L"/word/media/" + sImageId + L".svg"; + std::wstring sImageFile = m_sDst + L"/word/media/i" + sImageId + L".svg"; if (oSVGWriter.CreateFileW(sImageFile)) { oSVGWriter.WriteStringUTF8(oSVG.GetData()); @@ -2120,15 +2146,15 @@ private: NSFonts::IApplicationFonts* pFonts = NSFonts::NSApplication::Create(); MetaFile::IMetaFile* pMetafile = MetaFile::Create(pFonts); bool bLoad = pMetafile->LoadFromFile(sImageFile.data()); - if(bLoad) + if (bLoad) { - std::wstring sPngFile = m_sDst + L"/word/media/" + sImageId + L".png"; + std::wstring sPngFile = m_sDst + L"/word/media/i" + sImageId + L".png"; pMetafile->ConvertToRaster(sPngFile.data(), 4, 1000); } pMetafile->Release(); pFonts->Release(); - ImageRels(oXml, sImageId, sImageId + L".png"); + ImageRels(oXml, -1, L"", L"png"); } };