Create ChangePassword for pdf

This commit is contained in:
Svetlana Kulikova
2023-12-26 17:31:19 +03:00
parent 96929ac63a
commit 59fcd227ea
10 changed files with 243 additions and 13 deletions

View File

@ -54,6 +54,7 @@
#include "SrcWriter/Info.h"
#include "SrcWriter/Annotation.h"
#include "SrcWriter/ResourcesDictionary.h"
#include "SrcWriter/Streams.h"
#define AddToObject(oVal)\
{\
@ -1441,6 +1442,191 @@ void CPdfFile::AddMetaData(const std::wstring& sMetaName, BYTE* pMetaData, DWORD
return;
m_pInternal->pWriter->AddMetaData(sMetaName, pMetaData, nMetaLength);
}
HRESULT CPdfFile::ChangePassword(const std::wstring& wsPath, const std::wstring& wsPassword)
{
RELEASEOBJECT(m_pInternal->pWriter);
m_pInternal->pWriter = new CPdfWriter(m_pInternal->pAppFonts, false, this, false);
PDFDoc* pPDFDocument = m_pInternal->pReader->GetPDFDocument();
if (!pPDFDocument)
return S_FALSE;
XRef* xref = pPDFDocument->getXRef();
if (!xref)
return S_FALSE;
Object* trailerDict = xref->getTrailerDict();
if (!trailerDict)
return S_FALSE;
PdfWriter::CDocument* pDoc = m_pInternal->pWriter->m_pDocument;
PdfWriter::CXref* pXref = new PdfWriter::CXref(pDoc, 0);
PdfWriter::CXref* m_pXref = new PdfWriter::CXref(pDoc, xref->getNumObjects()); // Для новых объектов
if (!xref || !pDoc || !pXref || !m_pXref)
{
RELEASEOBJECT(pXref);
RELEASEOBJECT(m_pXref);
return S_FALSE;
}
pXref->SetPrev(m_pXref);
for (int i = 0; i < xref->getSize(); ++i)
{
XRefEntry* pEntry = xref->getEntry(i);
if (pEntry->type == xrefEntryFree)
continue;
if (i != pXref->GetSizeXRef())
{
PdfWriter::CXref* pXref2 = new PdfWriter::CXref(pDoc, i);
pXref2->SetPrev(pXref);
pXref = pXref2;
}
Object oTemp;
xref->fetch(i, pEntry->gen, &oTemp);
PdfWriter::CObjectBase* pObj = NULL;
switch (oTemp.getType())
{
case objBool:
{
pObj = new PdfWriter::CBoolObject(oTemp.getBool());
break;
}
case objInt:
{
pObj = new PdfWriter::CNumberObject(oTemp.getInt());
break;
}
case objReal:
{
pObj = new PdfWriter::CRealObject(oTemp.getReal());
break;
}
case objString:
{
TextString* s = new TextString(oTemp.getString());
std::string sValue = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
pObj = new PdfWriter::CStringObject(sValue.c_str());
delete s;
break;
}
case objName:
{
pObj = new PdfWriter::CNameObject(oTemp.getName());
break;
}
case objNull:
{
pObj = new PdfWriter::CNullObject();
break;
}
case objArray:
{
pObj = new PdfWriter::CArrayObject();
for (int nIndex = 0; nIndex < oTemp.arrayGetLength(); ++nIndex)
{
Object oT;
oTemp.arrayGetNF(nIndex, &oT);
DictToCDictObject(&oT, pObj, false, "");
oT.free();
}
break;
}
case objDict:
{
pObj = new PdfWriter::CDictObject();
for (int nIndex = 0; nIndex < oTemp.dictGetLength(); ++nIndex)
{
Object oT;
char* chKey = oTemp.dictGetKey(nIndex);
oTemp.dictGetValNF(nIndex, &oT);
DictToCDictObject(&oT, pObj, false, chKey);
oT.free();
}
break;
}
case objRef:
{
PdfWriter::CObjectBase* pBase = new PdfWriter::CObjectBase();
pBase->SetRef(oTemp.getRefNum(), oTemp.getRefGen());
pObj = new PdfWriter::CProxyObject(pBase, true);
break;
}
case objStream:
{
Dict* pDict = oTemp.streamGetDict();
Object oObjStm;
if (pDict->lookup("Type", &oObjStm)->isName("ObjStm"))
{
oObjStm.free();
break;
}
oObjStm.free();
PdfWriter::CDictObject* pDObj = new PdfWriter::CDictObject();
pObj = pDObj;
int nLength = 0;
for (int nIndex = 0; nIndex < pDict->getLength(); ++nIndex)
{
Object oT;
char* chKey = pDict->getKey(nIndex);
if (strcmp("Length", chKey) == 0)
{
Object oLength;
nLength = pDict->getVal(nIndex, &oLength)->isInt() ? oLength.getInt() : 0;
oLength.free();
continue;
}
pDict->getValNF(nIndex, &oT);
DictToCDictObject(&oT, pObj, false, chKey);
oT.free();
}
PdfWriter::CStream* pStream = new PdfWriter::CMemoryStream();
pDObj->SetStream(m_pXref, pStream, false);
Stream* pImage = oTemp.getStream()->getUndecodedStream();
pImage->reset();
for (int nI = 0; nI < nLength; ++nI)
pStream->WriteChar(pImage->getChar());
break;
}
case objNone:
case objCmd:
case objError:
case objEOF:
default:
break;
}
oTemp.free();
if (pObj)
pXref->Add(pObj);
}
PdfWriter::CDictObject* pTrailer = pXref->GetTrailer();
for (int nIndex = 0; nIndex < trailerDict->dictGetLength(); ++nIndex)
{
Object oTemp;
char* chKey = trailerDict->dictGetKey(nIndex);
if (strcmp("Root", chKey) == 0 || strcmp("Info", chKey) == 0)
{
trailerDict->dictGetValNF(nIndex, &oTemp);
DictToCDictObject(&oTemp, pTrailer, true, chKey);
}
oTemp.free();
}
bool bRes = pDoc->SaveNewWithPassword(pXref, m_pXref, wsPath, wsPassword, wsPassword, pTrailer);
RELEASEOBJECT(pXref);
return bRes ? S_OK : S_FALSE;
}
HRESULT CPdfFile::OnlineWordToPdf(const std::wstring& wsSrcFile, const std::wstring& wsDstFile, CConvertFromBinParams* pParams)
{
#ifndef BUILDING_WASM_MODULE

View File

@ -150,6 +150,7 @@ public:
void SetDocumentInfo(const std::wstring& wsTitle, const std::wstring& wsCreator, const std::wstring& wsSubject, const std::wstring& wsKeywords);
void AddMetaData(const std::wstring& sMetaName, BYTE* pMetaData, DWORD nMetaLength);
HRESULT ChangePassword(const std::wstring& wsPath, const std::wstring& wsPassword = L"");
HRESULT OnlineWordToPdf (const std::wstring& wsSrcFile, const std::wstring& wsDstFile, CConvertFromBinParams* pParams = NULL);
HRESULT OnlineWordToPdfFromBinary(const std::wstring& wsSrcFile, const std::wstring& wsDstFile, CConvertFromBinParams* pParams = NULL);
HRESULT AddToPdfFromBinary(BYTE* pBuffer, unsigned int nLen, CConvertFromBinParams* pParams = NULL);

View File

@ -94,7 +94,7 @@ static const long c_BrushTypeRadialGradient = 8002;
// CPdfRenderer
//
//----------------------------------------------------------------------------------------
CPdfWriter::CPdfWriter(NSFonts::IApplicationFonts* pAppFonts, bool isPDFA, IRenderer* pRenderer) : m_oCommandManager(this)
CPdfWriter::CPdfWriter(NSFonts::IApplicationFonts* pAppFonts, bool isPDFA, IRenderer* pRenderer, bool bCreate) : m_oCommandManager(this)
{
// Создаем менеджер шрифтов с собственным кэшем
m_pFontManager = pAppFonts->GenerateFontManager();
@ -108,7 +108,7 @@ CPdfWriter::CPdfWriter(NSFonts::IApplicationFonts* pAppFonts, bool isPDFA, IRend
if (isPDFA)
m_pDocument->SetPDFAConformanceMode(true);
if (!m_pDocument || !m_pDocument->CreateNew())
if (!m_pDocument || (bCreate && !m_pDocument->CreateNew()))
{
SetError();
return;

View File

@ -66,7 +66,7 @@ namespace Aggplus
class CPdfWriter
{
public:
CPdfWriter(NSFonts::IApplicationFonts* pAppFonts, bool isPDFA = false, IRenderer* pRenderer = NULL);
CPdfWriter(NSFonts::IApplicationFonts* pAppFonts, bool isPDFA = false, IRenderer* pRenderer = NULL, bool bCreate = true);
~CPdfWriter();
int SaveToFile(const std::wstring& wsPath);
void SetPassword(const std::wstring& wsPassword);

View File

@ -218,10 +218,10 @@ namespace PdfWriter
m_pFreeTypeLibrary = NULL;
}
}
bool CDocument::SaveToFile(const std::wstring& wsPath, bool bAdd)
bool CDocument::SaveToFile(const std::wstring& wsPath)
{
CFileStream* pStream = new CFileStream();
if (!pStream || !pStream->OpenFile(wsPath, bAdd))
if (!pStream || !pStream->OpenFile(wsPath, true))
return false;
if (m_pJbig2)
@ -264,6 +264,32 @@ namespace PdfWriter
m_pXref->WriteToStream(pStream, pEncrypt);
}
bool CDocument::SaveNewWithPassword(CXref* pXref, CXref* _pXref, const std::wstring& wsPath, const std::wstring& wsOwnerPassword, const std::wstring& wsUserPassword, CDictObject* pTrailer)
{
if (!pXref || !pTrailer || !_pXref)
return false;
m_pTrailer = pTrailer;
CEncrypt* pEncrypt = NULL;
if (!wsOwnerPassword.empty())
{
m_pEncryptDict = new CEncryptDict(_pXref);
m_pEncryptDict->SetPasswords(wsOwnerPassword, wsUserPassword);
m_pTrailer->Add("Encrypt", m_pEncryptDict);
pEncrypt = m_pEncryptDict->GetEncrypt();
PrepareEncryption();
}
CFileStream* pStream = new CFileStream();
if (!pStream || !pStream->OpenFile(wsPath, true))
return false;
pStream->WriteStr(c_sPdfHeader);
pXref->WriteToStream(pStream, pEncrypt);
return true;
}
void CDocument::PrepareEncryption()
{
CEncrypt* pEncrypt = m_pEncryptDict->GetEncrypt();

View File

@ -103,7 +103,8 @@ namespace PdfWriter
bool CreateNew();
void Close();
bool SaveToFile(const std::wstring& wsPath, bool bAdd = true);
bool SaveToFile(const std::wstring& wsPath);
bool SaveNewWithPassword(CXref* pXref, CXref* _pXref, const std::wstring& wsPath, const std::wstring& wsOwnerPassword, const std::wstring& wsUserPassword, CDictObject* pTrailer);
void SetPasswords(const std::wstring & wsOwnerPassword, const std::wstring & wsUserPassword);
void SetPermission(unsigned int unPermission);

View File

@ -651,7 +651,7 @@ namespace PdfWriter
}
}
}
void CDictObject::SetStream(CXref* pXref, CStream* pStream)
void CDictObject::SetStream(CXref* pXref, CStream* pStream, bool bThis)
{
if (m_pStream)
delete m_pStream;
@ -661,7 +661,8 @@ namespace PdfWriter
CNumberObject* pLength = new CNumberObject(0);
// Только stream object добавляются в таблицу xref автоматически
pXref->Add((CObjectBase*)this);
if (bThis)
pXref->Add((CObjectBase*)this);
pXref->Add((CObjectBase*)pLength);
Add("Length", (CObjectBase*)pLength);
@ -852,7 +853,7 @@ namespace PdfWriter
unsigned int unMaxObjId = m_pPrev ? pPrev->m_arrEntries.size() + pPrev->m_unStartOffset : m_arrEntries.size() + m_unStartOffset;
m_pTrailer->Add("Size", unMaxObjId);
if (m_pPrev)
if (m_pPrev && pPrev->m_unAddr)
m_pTrailer->Add("Prev", pPrev->m_unAddr);
pStream->WriteStr("trailer\012");
@ -916,7 +917,7 @@ namespace PdfWriter
CDictObject* pTrailer = m_pTrailer;
pTrailer->Add("Type", "XRef");
pTrailer->Add("Size", unMaxObjId + 1);
if (m_pPrev)
if (m_pPrev && pPrev->m_unAddr)
pTrailer->Add("Prev", pPrev->m_unAddr);
CArrayObject* pW = new CArrayObject();
pTrailer->Add("W", pW);

View File

@ -468,7 +468,7 @@ namespace PdfWriter
{
m_unFilter = unFiler;
}
void SetStream(CXref* pXref, CStream* pStream);
void SetStream(CXref* pXref, CStream* pStream, bool bThis = true);
virtual void BeforeWrite(){}
virtual void Write(CStream* pStream){}

View File

@ -589,7 +589,6 @@ namespace PdfWriter
// Добавляем запись Filter
if (pDict->GetStream())
{
pDict->Remove("Filter");
unsigned int unFilter = pDict->GetFilter();
if (STREAM_FILTER_NONE != unFilter)
{

View File

@ -281,7 +281,7 @@ TEST_F(CPdfFileTest, EditPdf)
TEST_F(CPdfFileTest, EditPdfFromBase64)
{
// GTEST_SKIP();
GTEST_SKIP();
LoadFromFile();
ASSERT_TRUE(pdfFile->EditPdf(wsDstFile));
@ -368,3 +368,19 @@ TEST_F(CPdfFileTest, EditPdfSign)
RELEASEOBJECT(pCertificate);
}
TEST_F(CPdfFileTest, ChangePasswordToEmpty)
{
// GTEST_SKIP();
LoadFromFile();
EXPECT_HRESULT_SUCCEEDED(pdfFile->ChangePassword(wsDstFile));
}
TEST_F(CPdfFileTest, ChangePasswordToPassword)
{
GTEST_SKIP();
LoadFromFile();
EXPECT_HRESULT_SUCCEEDED(pdfFile->ChangePassword(wsDstFile, L"123456"));
}