diff --git a/DesktopEditor/doctrenderer/drawingfile.h b/DesktopEditor/doctrenderer/drawingfile.h index 24bd1fd258..92f8365969 100644 --- a/DesktopEditor/doctrenderer/drawingfile.h +++ b/DesktopEditor/doctrenderer/drawingfile.h @@ -245,7 +245,18 @@ public: return 0; } - + bool CheckOwnerPassword(const std::wstring& sPassword) + { + if (m_nType == 0) + return ((CPdfFile*)m_pFile)->CheckOwnerPassword(sPassword); + return true; + } + bool CheckPerm(int nPerm) + { + if (m_nType == 0) + return ((CPdfFile*)m_pFile)->CheckPerm(nPerm); + return true; + } BYTE* GetInfo() { NSWasm::CData oRes; diff --git a/DesktopEditor/graphics/pro/js/drawingfile.json b/DesktopEditor/graphics/pro/js/drawingfile.json index 98efabcb3c..f1b3f34b50 100644 --- a/DesktopEditor/graphics/pro/js/drawingfile.json +++ b/DesktopEditor/graphics/pro/js/drawingfile.json @@ -56,6 +56,8 @@ "_UnmergePages", "_RedactPage", "_UndoRedact", + "_CheckOwnerPassword", + "_CheckPerm", "_GetImageBase64", "_GetImageBase64Len", "_GetImageBase64Ptr", diff --git a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js index ba24184e09..1f855cf6b2 100644 --- a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js +++ b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile.js @@ -145,6 +145,14 @@ CFile.prototype["isNeedPassword"] = function() { return this._isNeedPassword; }; +CFile.prototype["CheckOwnerPassword"] = function(password) +{ + return this._CheckOwnerPassword(password); +}; +CFile.prototype["CheckPerm"] = function(perm) +{ + return this._CheckPerm(perm); +}; 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..ea1605fa14 100644 --- a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_native.js +++ b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_native.js @@ -146,6 +146,16 @@ CFile.prototype._UndoRedact = function() return g_native_drawing_file["UndoRedact"](); }; +CFile.prototype._CheckOwnerPassword = function(password) +{ + return true; +} + +CFile.prototype._CheckPerm = function(perm) +{ + return true; +} + // FONTS CFile.prototype._isNeedCMap = function() { diff --git a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_wasm.js b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_wasm.js index be1c6a32d4..28e047fe80 100644 --- a/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_wasm.js +++ b/DesktopEditor/graphics/pro/js/wasm/js/drawingfile_wasm.js @@ -224,6 +224,29 @@ CFile.prototype._UndoRedact = function() return Module["_UndoRedact"](this.nativeFile) == 1; }; +CFile.prototype._CheckOwnerPassword = function(password) +{ + let passwordPtr = 0; + if (password) + { + let passwordBuf = password.toUtf8(); + passwordPtr = Module["_malloc"](passwordBuf.length); + Module["HEAP8"].set(passwordBuf, passwordPtr); + } + + let bRes = Module["_CheckOwnerPassword"](this.nativeFile, passwordPtr); + + if (passwordPtr) + Module["_free"](passwordPtr); + + return bRes == 1; +} + +CFile.prototype._CheckPerm = function(perm) +{ + return Module["_CheckPerm"](this.nativeFile, perm) == 1; +} + // 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..f048a13f7d 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile.cpp @@ -191,6 +191,17 @@ WASM_EXPORT int UndoRedact(CDrawingFile* pFile) { return pFile->UndoRedact() ? 1 : 0; } +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 int CheckPerm(CDrawingFile* pFile, int nPermFlag) +{ + return pFile->CheckPerm(nPermFlag) ? 1 : 0; +} WASM_EXPORT void* GetImageBase64(CDrawingFile* pFile, int rId) { diff --git a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp index 1629ee7d95..a418ba0b4a 100644 --- a/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp +++ b/DesktopEditor/graphics/pro/js/wasm/src/drawingfile_test.cpp @@ -1125,6 +1125,18 @@ int main(int argc, char* argv[]) } } + // OWNER PASSWORD + if (true) + { + std::string sPassword = "gfhjkmgfhjkm"; + std::cout << "CheckPerm 4 Edit " << CheckPerm(pGrFile, 4) << std::endl; + std::cout << "CheckPerm 4 Print " << CheckPerm(pGrFile, 3) << std::endl; + + std::cout << "CheckOwnerPassword " << CheckOwnerPassword(pGrFile, sPassword.c_str()) << std::endl; + std::cout << "CheckPerm 4 Edit " << CheckPerm(pGrFile, 4) << std::endl; + std::cout << "CheckPerm 4 Print " << CheckPerm(pGrFile, 3) << std::endl; + } + BYTE* pColor = new BYTE[12] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // REDACT if (false) @@ -1230,7 +1242,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..8c9193ea14 100644 --- a/PdfFile/PdfFile.cpp +++ b/PdfFile/PdfFile.cpp @@ -373,9 +373,27 @@ 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; +} +bool CPdfFile::CheckPerm(int nPerm) +{ + if (!m_pInternal->pReader) + return false; + return m_pInternal->pReader->CheckPerm(nPerm); +} int CPdfFile::GetRotate(int nPageIndex) { if (!m_pInternal->pReader) diff --git a/PdfFile/PdfFile.h b/PdfFile/PdfFile.h index 711e5b1426..f078d95ab3 100644 --- a/PdfFile/PdfFile.h +++ b/PdfFile/PdfFile.h @@ -133,6 +133,8 @@ 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); + bool CheckPerm(int nPerm); int GetRotate(int nPageIndex); int GetMaxRefID(); BYTE* GetWidgets(); diff --git a/PdfFile/PdfReader.cpp b/PdfFile/PdfReader.cpp index 2bd9891a1b..da8f6c0925 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) @@ -806,6 +807,59 @@ 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; +} +bool CPdfReader::CheckPerm(int nPerm) +{ + PDFDoc* pDoc = m_vPDFContext.front()->m_pDocument; + XRef* xref = pDoc->getXRef(); + + if (!xref->isEncrypted()) + return true; + + CryptAlgorithm encAlgorithm; + GBool ownerPasswordOk; + int permFlags, keyLength, encVersion; + xref->getEncryption(&permFlags, &ownerPasswordOk, &keyLength, &encVersion, &encAlgorithm); + + return ownerPasswordOk || (permFlags & (1 << --nPerm)); +} void CPdfReader::DrawPageOnRenderer(IRenderer* pRenderer, int _nPageIndex, bool* pbBreak) { PDFDoc* pDoc = NULL; diff --git a/PdfFile/PdfReader.h b/PdfFile/PdfReader.h index 8e2ae637c3..f9deedd859 100644 --- a/PdfFile/PdfReader.h +++ b/PdfFile/PdfReader.h @@ -95,6 +95,8 @@ public: bool UnmergePages(); bool RedactPage(int nPageIndex, double* arrRedactBox, int nLengthX8, BYTE* pChanges, int nLength); bool UndoRedact(); + bool CheckOwnerPassword(const std::wstring& sPassword); + bool CheckPerm(int nPerm); void GetPageInfo(int nPageIndex, double* pdWidth, double* pdHeight, double* pdDpiX, double* pdDpiY); void DrawPageOnRenderer(IRenderer* pRenderer, int nPageIndex, bool* pBreak); std::wstring GetInfo();