From 1e18352e7756bc4099126cc9a26b473a47a98f54 Mon Sep 17 00:00:00 2001 From: Svetlana Kulikova Date: Wed, 19 Nov 2025 18:23:23 +0300 Subject: [PATCH] Create CheckOwnerPassword --- DesktopEditor/doctrenderer/drawingfile.h | 7 ++- .../graphics/pro/js/wasm/js/drawingfile.js | 4 ++ .../pro/js/wasm/js/drawingfile_native.js | 7 +++ .../graphics/pro/js/wasm/src/drawingfile.cpp | 7 +++ .../pro/js/wasm/src/drawingfile_test.cpp | 9 +++- PdfFile/PdfFile.cpp | 14 +++++- PdfFile/PdfFile.h | 1 + PdfFile/PdfReader.cpp | 47 ++++++++++++++++--- PdfFile/PdfReader.h | 1 + 9 files changed, 88 insertions(+), 9 deletions(-) diff --git a/DesktopEditor/doctrenderer/drawingfile.h b/DesktopEditor/doctrenderer/drawingfile.h index 24bd1fd258..6b0aa5ab05 100644 --- a/DesktopEditor/doctrenderer/drawingfile.h +++ b/DesktopEditor/doctrenderer/drawingfile.h @@ -245,7 +245,12 @@ public: return 0; } - + bool CheckOwnerPassword(const std::wstring& sPassword) + { + if (m_nType == 0) + return ((CPdfFile*)m_pFile)->CheckOwnerPassword(sPassword); + return true; + } BYTE* GetInfo() { NSWasm::CData oRes; diff --git a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js index ba24184e09..71fc269052 100644 --- a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js +++ b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js @@ -145,6 +145,10 @@ CFile.prototype["isNeedPassword"] = function() { return this._isNeedPassword; }; +CFile.prototype["CheckOwnerPassword"] = function(password) +{ + return this._CheckOwnerPassword(password); +}; CFile.prototype["SplitPages"] = function(arrOriginIndex, arrayBufferChanges) { let ptr = this._SplitPages(arrOriginIndex, arrayBufferChanges); diff --git a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_native.js b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_native.js index fb8f660041..534be022d4 100644 --- a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_native.js +++ b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_native.js @@ -146,6 +146,13 @@ CFile.prototype._UndoRedact = function() return g_native_drawing_file["UndoRedact"](); }; +CFile.prototype._CheckOwnerPassword = function(password) +{ + if (!password) + password = ""; + return g_native_drawing_file["CheckOwnerPassword"](password); +} + // FONTS CFile.prototype._isNeedCMap = function() { diff --git a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp index e73a0557b8..ca193864d2 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp @@ -96,6 +96,13 @@ WASM_EXPORT int GetErrorCode(CDrawingFile* pFile) return -1; return pFile->GetErrorCode(); } +WASM_EXPORT int CheckOwnerPassword(CDrawingFile* pFile, const char* password) +{ + std::wstring sPassword = L""; + if (NULL != password) + sPassword = NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)password, strlen(password)); + return pFile->CheckOwnerPassword(sPassword) ? 1 : 0; +} WASM_EXPORT void Close(CDrawingFile* pFile) { delete pFile; diff --git a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp index 1629ee7d95..71aa194e60 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp @@ -1125,6 +1125,13 @@ int main(int argc, char* argv[]) } } + // OWNER PASSWORD + if (true) + { + std::string sPassword = ""; + std::cout << "CheckOwnerPassword " << CheckOwnerPassword(pGrFile, sPassword.c_str()) << std::endl; + } + BYTE* pColor = new BYTE[12] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // REDACT if (false) @@ -1230,7 +1237,7 @@ int main(int argc, char* argv[]) } // GLYPHS - if (false && nPagesCount > 0) + if (true && nPagesCount > 0) { BYTE* pGlyphs = GetGlyphs(pGrFile, nTestPage); nLength = READ_INT(pGlyphs); diff --git a/PdfFile/PdfFile.cpp b/PdfFile/PdfFile.cpp index ddd88ea6b2..fe51dfcb45 100644 --- a/PdfFile/PdfFile.cpp +++ b/PdfFile/PdfFile.cpp @@ -373,9 +373,21 @@ bool CPdfFile::RedactPage(int nPageIndex, double* arrRedactBox, int nLengthX8, B bool CPdfFile::UndoRedact() { if (!m_pInternal->pReader) - return false; + return true; return m_pInternal->pReader->UndoRedact(); } +bool CPdfFile::CheckOwnerPassword(const std::wstring& sPassword) +{ + if (!m_pInternal->pReader) + return false; + bool bRes = m_pInternal->pReader->CheckOwnerPassword(sPassword); + if (bRes) + m_pInternal->wsPassword = sPassword; + else if (!m_pInternal->wsPassword.empty()) + bRes = m_pInternal->pReader->CheckOwnerPassword(m_pInternal->wsPassword); + + return bRes; +} int CPdfFile::GetRotate(int nPageIndex) { if (!m_pInternal->pReader) diff --git a/PdfFile/PdfFile.h b/PdfFile/PdfFile.h index 711e5b1426..b93fc5b3f1 100644 --- a/PdfFile/PdfFile.h +++ b/PdfFile/PdfFile.h @@ -133,6 +133,7 @@ public: bool UnmergePages(); bool RedactPage(int nPageIndex, double* arrRedactBox, int nLengthX8, BYTE* pChanges = NULL, int nLength = 0); bool UndoRedact(); + bool CheckOwnerPassword(const std::wstring& sPassword); int GetRotate(int nPageIndex); int GetMaxRefID(); BYTE* GetWidgets(); diff --git a/PdfFile/PdfReader.cpp b/PdfFile/PdfReader.cpp index 457af2e38c..408eb4c913 100644 --- a/PdfFile/PdfReader.cpp +++ b/PdfFile/PdfReader.cpp @@ -54,6 +54,7 @@ #include "lib/xpdf/Link.h" #include "lib/xpdf/TextOutputDev.h" #include "lib/xpdf/AcroForm.h" +#include "lib/xpdf/SecurityHandler.h" #include "lib/goo/GList.h" NSFonts::IFontManager* InitFontManager(NSFonts::IApplicationFonts* pAppFonts) @@ -687,7 +688,6 @@ bool CPdfReader::MergePages(BYTE* pData, DWORD nLength, const std::wstring& wsPa return false; } - GString* owner_pswd = NSStrings::CreateString(wsPassword); GString* user_pswd = NSStrings::CreateString(wsPassword); Object obj; @@ -696,7 +696,7 @@ bool CPdfReader::MergePages(BYTE* pData, DWORD nLength, const std::wstring& wsPa // Время его жизни > copy и makeSubStream из MemStream BaseStream *str = new MemStream((char*)pData, 0, nLength, &obj, gTrue); CPdfReaderContext* pContext = new CPdfReaderContext(); - pContext->m_pDocument = new PDFDoc(str, owner_pswd, user_pswd); + pContext->m_pDocument = new PDFDoc(str, NULL, user_pswd); pContext->m_pFontList = new PdfReader::CPdfFontList(); pContext->m_sPrefixForm = sPrefixForm; if (nMaxID != 0) @@ -706,7 +706,6 @@ bool CPdfReader::MergePages(BYTE* pData, DWORD nLength, const std::wstring& wsPa PDFDoc* pDoc = pContext->m_pDocument; m_vPDFContext.push_back(pContext); - delete owner_pswd; delete user_pswd; m_eError = pDoc ? pDoc->getErrorCode() : errMemory; @@ -727,13 +726,12 @@ bool CPdfReader::MergePages(const std::wstring& wsFile, const std::wstring& wsPa { if (m_eError) return false; - GString* owner_pswd = NSStrings::CreateString(wsPassword); GString* user_pswd = NSStrings::CreateString(wsPassword); // конвертим путь в utf8 - под виндой они сконвертят в юникод, а на остальных - так и надо std::string sPathUtf8 = U_TO_UTF8(wsFile); CPdfReaderContext* pContext = new CPdfReaderContext(); - pContext->m_pDocument = new PDFDoc((char*)sPathUtf8.c_str(), owner_pswd, user_pswd); + pContext->m_pDocument = new PDFDoc((char*)sPathUtf8.c_str(), NULL, user_pswd); pContext->m_pFontList = new PdfReader::CPdfFontList(); pContext->m_sPrefixForm = sPrefixForm; if (nMaxID != 0) @@ -743,7 +741,6 @@ bool CPdfReader::MergePages(const std::wstring& wsFile, const std::wstring& wsPa PDFDoc* pDoc = pContext->m_pDocument; m_vPDFContext.push_back(pContext); - delete owner_pswd; delete user_pswd; m_eError = pDoc ? pDoc->getErrorCode() : errMemory; @@ -806,6 +803,44 @@ bool CPdfReader::UndoRedact() m_vRedact.pop_back(); return true; } +bool CPdfReader::CheckOwnerPassword(const std::wstring& wsPassword) +{ + PDFDoc* pDoc = m_vPDFContext.front()->m_pDocument; + XRef* xref = pDoc->getXRef(); + + if (!xref->isEncrypted()) + return true; + + Object* pTrailerDict = xref->getTrailerDict(); + Object encrypt; + SecurityHandler* secHdlr = NULL; + xref->offEncrypted(); + if (pTrailerDict->dictLookup("Encrypt", &encrypt) && encrypt.isDict()) + secHdlr = SecurityHandler::make(pDoc, &encrypt); + encrypt.free(); + + if (!secHdlr || secHdlr->isUnencrypted()) + { + RELEASEOBJECT(secHdlr); + xref->onEncrypted(); + return true; + } + + bool bRes = false; + GString* owner_pswd = NSStrings::CreateString(wsPassword); + if (secHdlr->checkEncryption(owner_pswd, NULL) && secHdlr->getOwnerPasswordOk()) + { + bRes = true; + xref->setEncryption(secHdlr->getPermissionFlags(), secHdlr->getOwnerPasswordOk(), secHdlr->getFileKey(), + secHdlr->getFileKeyLength(), secHdlr->getEncVersion(), secHdlr->getEncAlgorithm()); + } + else + xref->onEncrypted(); + + delete owner_pswd; + delete secHdlr; + return bRes; +} void CPdfReader::DrawPageOnRenderer(IRenderer* pRenderer, int _nPageIndex, bool* pbBreak) { PDFDoc* pDoc = NULL; diff --git a/PdfFile/PdfReader.h b/PdfFile/PdfReader.h index 8e2ae637c3..ba4ab1fdc5 100644 --- a/PdfFile/PdfReader.h +++ b/PdfFile/PdfReader.h @@ -95,6 +95,7 @@ public: bool UnmergePages(); bool RedactPage(int nPageIndex, double* arrRedactBox, int nLengthX8, BYTE* pChanges, int nLength); bool UndoRedact(); + bool CheckOwnerPassword(const std::wstring& sPassword); void GetPageInfo(int nPageIndex, double* pdWidth, double* pdHeight, double* pdDpiX, double* pdDpiY); void DrawPageOnRenderer(IRenderer* pRenderer, int nPageIndex, bool* pBreak); std::wstring GetInfo();