mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-02-10 18:05:41 +08:00
Create PrepareSignature and FinalizeSignature
This commit is contained in:
@ -102,11 +102,23 @@ void CPdfFile::Close()
|
||||
else if (m_pInternal->pReader)
|
||||
m_pInternal->pReader->Close();
|
||||
}
|
||||
void CPdfFile::Sign(const double& dX, const double& dY, const double& dW, const double& dH, const std::wstring& wsPicturePath, ICertificate* pCertificate)
|
||||
void CPdfFile::Sign(const double& dX, const double& dY, const double& dW, const double& dH, const std::wstring& wsPicturePath)
|
||||
{
|
||||
if (!m_pInternal->pWriter)
|
||||
return;
|
||||
m_pInternal->pWriter->Sign(dX, dY, dW, dH, wsPicturePath, pCertificate);
|
||||
m_pInternal->pWriter->Sign(dX, dY, dW, dH, wsPicturePath);
|
||||
}
|
||||
bool CPdfFile::PrepareSignature(BYTE** pDataToSign, DWORD& dwDataLength)
|
||||
{
|
||||
if (!m_pInternal->pWriter)
|
||||
return false;
|
||||
return m_pInternal->pWriter->PrepareSignature(pDataToSign, dwDataLength);
|
||||
}
|
||||
bool CPdfFile::FinalizeSignature(BYTE* pSignedData, DWORD dwDataLength)
|
||||
{
|
||||
if (!m_pInternal->pWriter)
|
||||
return false;
|
||||
return m_pInternal->pWriter->FinalizeSignature(pSignedData, dwDataLength);
|
||||
}
|
||||
void CPdfFile::SetDocumentInfo(const std::wstring& wsTitle, const std::wstring& wsCreator, const std::wstring& wsSubject, const std::wstring& wsKeywords)
|
||||
{
|
||||
@ -134,6 +146,12 @@ bool CPdfFile::EditPdf(const std::wstring& wsDstFile)
|
||||
m_pInternal->pEditor = new CPdfEditor(m_pInternal->wsSrcFile, m_pInternal->wsPassword, wsDstFile, m_pInternal->pReader, m_pInternal->pWriter);
|
||||
return m_pInternal->pEditor->GetError() == 0;
|
||||
}
|
||||
void CPdfFile::EditClose()
|
||||
{
|
||||
if (m_pInternal->pEditor)
|
||||
m_pInternal->pEditor->Close();
|
||||
RELEASEOBJECT(m_pInternal->pEditor);
|
||||
}
|
||||
void CPdfFile::SetEditType(int nType)
|
||||
{
|
||||
if (!m_pInternal->pEditor)
|
||||
|
||||
@ -92,6 +92,7 @@ public:
|
||||
// --- EDIT ---
|
||||
// Переходит в режим редактирования. Pdf уже должен быть открыт на чтение - LoadFromFile/LoadFromMemory
|
||||
bool EditPdf(const std::wstring& wsDstFile = L"");
|
||||
void EditClose();
|
||||
void SetEditType(int nType);
|
||||
// Манипуляции со страницами возможны в режиме редактирования
|
||||
bool EditPage (int nPageIndex);
|
||||
@ -159,7 +160,9 @@ public:
|
||||
void RotatePage (int nRotate);
|
||||
void SetPassword (const std::wstring& wsPassword);
|
||||
void SetDocumentID(const std::wstring& wsDocumentID);
|
||||
void Sign(const double& dX, const double& dY, const double& dW, const double& dH, const std::wstring& wsPicturePath, ICertificate* pCertificate);
|
||||
void Sign(const double& dX, const double& dY, const double& dW, const double& dH, const std::wstring& wsPicturePath);
|
||||
bool PrepareSignature(BYTE** pDataToSign, DWORD& dwDataLength);
|
||||
bool FinalizeSignature(BYTE* pSignedData, DWORD dwDataLength);
|
||||
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);
|
||||
|
||||
|
||||
@ -3256,7 +3256,7 @@ void CPdfWriter::PageRotate(int nRotate)
|
||||
if (m_pPage)
|
||||
m_pPage->SetRotate(nRotate);
|
||||
}
|
||||
void CPdfWriter::Sign(const double& dX, const double& dY, const double& dW, const double& dH, const std::wstring& wsPicturePath, ICertificate* pCertificate)
|
||||
void CPdfWriter::Sign(const double& dX, const double& dY, const double& dW, const double& dH, const std::wstring& wsPicturePath)
|
||||
{
|
||||
PdfWriter::CImageDict* pImage = NULL;
|
||||
if (!wsPicturePath.empty())
|
||||
@ -3265,9 +3265,21 @@ void CPdfWriter::Sign(const double& dX, const double& dY, const double& dW, cons
|
||||
pImage = LoadImage(&oImage, 255);
|
||||
}
|
||||
|
||||
m_pDocument->Sign(PdfWriter::TRect(MM_2_PT(dX), m_pPage->GetHeight() - MM_2_PT(dY), MM_2_PT(dX + dW), m_pPage->GetHeight() - MM_2_PT(dY + dH)),
|
||||
pImage, pCertificate);
|
||||
m_pDocument->Sign(PdfWriter::TRect(MM_2_PT(dX), m_pPage->GetHeight() - MM_2_PT(dY), MM_2_PT(dX + dW), m_pPage->GetHeight() - MM_2_PT(dY + dH)), pImage);
|
||||
}
|
||||
bool CPdfWriter::PrepareSignature(BYTE** pDataToSign, DWORD& dwDataLength)
|
||||
{
|
||||
if (!m_pDocument)
|
||||
return false;
|
||||
return m_pDocument->PrepareSignature(pDataToSign, dwDataLength);
|
||||
}
|
||||
bool CPdfWriter::FinalizeSignature(BYTE* pSignedData, DWORD dwDataLength)
|
||||
{
|
||||
if (!m_pDocument)
|
||||
return false;
|
||||
return m_pDocument->FinalizeSignature(pSignedData, dwDataLength);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// Внутренние функции
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
@ -225,7 +225,9 @@ public:
|
||||
bool AddPage(int nPageIndex);
|
||||
bool EditClose();
|
||||
void PageRotate(int nRotate);
|
||||
void Sign(const double& dX, const double& dY, const double& dW, const double& dH, const std::wstring& wsPicturePath, ICertificate* pCertificate);
|
||||
void Sign(const double& dX, const double& dY, const double& dW, const double& dH, const std::wstring& wsPicturePath);
|
||||
bool PrepareSignature(BYTE** pDataToSign, DWORD& dwDataLength);
|
||||
bool FinalizeSignature(BYTE* pSignedData, DWORD dwDataLength);
|
||||
PdfWriter::CDocument* GetDocument();
|
||||
PdfWriter::CPage* GetPage();
|
||||
IRenderer* GetRenderer();
|
||||
|
||||
@ -1950,96 +1950,157 @@ namespace PdfWriter
|
||||
unsigned int nSizeXRef = m_pXref->GetSizeXRef() + (bNeedStreamXRef ? 1 : 0);
|
||||
m_pXref = m_pLastXref;
|
||||
Sign(wsPath, nSizeXRef, bNeedStreamXRef);
|
||||
RELEASEOBJECT(m_pEncryptDict);
|
||||
// TODO проверить RELEASEOBJECT(m_pEncryptDict);
|
||||
|
||||
return true;
|
||||
}
|
||||
void CDocument::Sign(const TRect& oRect, CImageDict* pImage, ICertificate* pCertificate)
|
||||
void CDocument::Sign(const TRect& oRect, CImageDict* pImage)
|
||||
{
|
||||
m_vSignatures.push_back({ oRect, m_pCurPage ? m_pCurPage : m_pPageTree->GetPage(0), pImage, pCertificate });
|
||||
m_vSignatures.push_back(new TSignatureInfo(oRect, m_pCurPage ? m_pCurPage : m_pPageTree->GetPage(0), pImage));
|
||||
}
|
||||
bool CDocument::PrepareSignature(BYTE** pDataToSign, DWORD& dwDataLength)
|
||||
{
|
||||
// Сначала нужно сохранить основной файл
|
||||
// Это должно быть сделано в AddToFile или SaveToFile ПЕРЕД вызовом этого метода
|
||||
|
||||
if (m_vSignatures.empty())
|
||||
return false;
|
||||
|
||||
TSignatureInfo* pSI = m_vSignatures[0];
|
||||
|
||||
std::wstring wsPath = pSI->wsPath;
|
||||
if (wsPath.empty())
|
||||
return false;
|
||||
|
||||
unsigned int nSizeXRef = pSI->nSizeXRef;
|
||||
bool bNeedStreamXRef = pSI->bNeedStreamXRef;
|
||||
|
||||
// Создаем новый XRef для этой подписи
|
||||
CXref* pXrefBefore = m_pXref;
|
||||
m_pXref = new CXref(this, nSizeXRef);
|
||||
if (!m_pXref)
|
||||
{
|
||||
m_pXref = pXrefBefore;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Создаем поле подписи
|
||||
CSignatureField* pField = CreateSignatureField();
|
||||
if (!pField)
|
||||
{
|
||||
delete m_pXref;
|
||||
m_pXref = pXrefBefore;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Настраиваем поле
|
||||
pSI->pField = pField;
|
||||
m_pAcroForm->Add("SigFlags", 3);
|
||||
pField->GetSignatureDict()->SetDate();
|
||||
pField->AddPageRect(pSI->pPage, pSI->oRect);
|
||||
pField->Add("F", 132);
|
||||
pField->SetFieldName("Sig" + std::to_string(++m_unFormFields));
|
||||
if (pSI->pImage)
|
||||
pField->SetAppearance(pSI->pImage);
|
||||
|
||||
// Открываем файл для дозаписи
|
||||
CFileStream* pStream = new CFileStream();
|
||||
if (!pStream || !pStream->OpenFile(wsPath, false))
|
||||
{
|
||||
delete m_pXref;
|
||||
m_pXref = pXrefBefore;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Вычисляем размер для Contents
|
||||
unsigned int nContentsSize = 7000 + pStream->Size() / 1000 + 1000;
|
||||
if (nContentsSize < 5000)
|
||||
nContentsSize = 5000;
|
||||
if (nContentsSize > 20000)
|
||||
nContentsSize = 20000;
|
||||
pField->GetSignatureDict()->SetContentsSize(nContentsSize);
|
||||
|
||||
// Записываем XRef и получаем информацию о расположении
|
||||
CXref* pXrefCatalog = new CXref(this, m_pCatalog->GetObjId());
|
||||
if (pXrefCatalog)
|
||||
{
|
||||
pXrefCatalog->Add(m_pCatalog->Copy(), m_pCatalog->GetGenNo());
|
||||
pXrefCatalog->SetPrev(m_pXref);
|
||||
}
|
||||
|
||||
CXref* pXrefPage = new CXref(this, pSI->pPage->GetObjId());
|
||||
if (pXrefPage)
|
||||
{
|
||||
pXrefPage->Add(pSI->pPage->Copy(), pSI->pPage->GetGenNo());
|
||||
pXrefPage->SetPrev(pXrefCatalog);
|
||||
}
|
||||
|
||||
CXref* pXref = new CXref(this, 0, 65535);
|
||||
if (pXref)
|
||||
{
|
||||
pXref->SetPrev(pXrefPage);
|
||||
CDictObject* pTrailer = pXref->GetTrailer();
|
||||
m_pTrailer->Copy(pTrailer);
|
||||
|
||||
CEncrypt* pEncrypt = NULL;
|
||||
if (m_pEncryptDict)
|
||||
pEncrypt = m_pEncryptDict->GetEncrypt();
|
||||
|
||||
pXref->WriteToStream(pStream, pEncrypt, bNeedStreamXRef);
|
||||
pSI->pXref = pXref;
|
||||
}
|
||||
|
||||
pField->GetSignatureDict()->WriteToStream(pStream, pStream->Size(), pDataToSign, dwDataLength);
|
||||
|
||||
// Восстанавливаем XRef
|
||||
m_pXref = pXrefBefore;
|
||||
|
||||
delete pStream;
|
||||
|
||||
return true;
|
||||
}
|
||||
bool CDocument::FinalizeSignature(BYTE* pSignedData, DWORD dwDataLength)
|
||||
{
|
||||
if (m_vSignatures.empty())
|
||||
return false;
|
||||
|
||||
TSignatureInfo* pSI = m_vSignatures[0];
|
||||
bool bNeedStreamXRef = pSI->bNeedStreamXRef;
|
||||
std::wstring wsPath = pSI->wsPath;
|
||||
if (wsPath.empty() || !pSI->pField)
|
||||
return false;
|
||||
|
||||
CFileStream* pStream = new CFileStream();
|
||||
if (!pStream || !pStream->OpenFile(wsPath, false))
|
||||
{
|
||||
delete pStream;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pSI->pField->GetSignatureDict() || !pSI->pField->GetSignatureDict()->FinalizeSignature(pStream, pSignedData, dwDataLength))
|
||||
{
|
||||
delete pStream;
|
||||
return false;
|
||||
}
|
||||
|
||||
CXref* pXref = pSI->pXref;
|
||||
delete pStream;
|
||||
delete pSI;
|
||||
|
||||
m_vSignatures.pop_front();
|
||||
Sign(wsPath, pXref->GetSizeXRef() + (bNeedStreamXRef ? 1 : 0), bNeedStreamXRef);
|
||||
delete pXref;
|
||||
|
||||
return true;
|
||||
}
|
||||
void CDocument::Sign(const std::wstring& wsPath, unsigned int nSizeXRef, bool bNeedStreamXRef)
|
||||
{
|
||||
unsigned int nPrevAddr = m_pXref->GetPrevAddr();
|
||||
std::vector<CXref*> vXRefForWrite;
|
||||
for (unsigned int i = 0; i < m_vSignatures.size(); i++)
|
||||
if (!m_vSignatures.empty())
|
||||
{
|
||||
CXref* pXrefBefore = m_pXref;
|
||||
m_pXref = new CXref(this, nSizeXRef);
|
||||
if (!m_pXref)
|
||||
{
|
||||
m_pXref = pXrefBefore;
|
||||
continue;
|
||||
}
|
||||
m_pXref->SetPrevAddr(nPrevAddr);
|
||||
|
||||
CSignatureField* pField = CreateSignatureField();
|
||||
if (!pField)
|
||||
{
|
||||
RELEASEOBJECT(m_pXref);
|
||||
m_pXref = pXrefBefore;
|
||||
continue;
|
||||
}
|
||||
|
||||
m_pAcroForm->Add("SigFlags", 3);
|
||||
pField->GetSignatureDict()->SetCert(m_vSignatures[i].pCertificate);
|
||||
pField->GetSignatureDict()->SetDate();
|
||||
pField->AddPageRect(m_vSignatures[i].pPage, m_vSignatures[i].oRect);
|
||||
pField->Add("F", 132);
|
||||
pField->SetFieldName("Sig" + std::to_string(i + m_unFormFields + 1));
|
||||
if (m_vSignatures[i].pImage)
|
||||
pField->SetAppearance(m_vSignatures[i].pImage);
|
||||
|
||||
CFileStream* pStream = new CFileStream();
|
||||
if (!pStream || !pStream->OpenFile(wsPath, false))
|
||||
{
|
||||
RELEASEOBJECT(m_pXref);
|
||||
m_pXref = pXrefBefore;
|
||||
continue;
|
||||
}
|
||||
|
||||
CXref* pXrefCatalog = new CXref(this, m_pCatalog->GetObjId());
|
||||
if (pXrefCatalog)
|
||||
{
|
||||
pXrefCatalog->Add(m_pCatalog->Copy(), m_pCatalog->GetGenNo());
|
||||
pXrefCatalog->SetPrev(m_pXref);
|
||||
}
|
||||
|
||||
CXref* pXrefPage = new CXref(this, m_vSignatures[i].pPage->GetObjId());
|
||||
if (pXrefPage)
|
||||
{
|
||||
pXrefPage->Add(m_vSignatures[i].pPage->Copy(), m_vSignatures[i].pPage->GetGenNo());
|
||||
pXrefPage->SetPrev(pXrefCatalog);
|
||||
}
|
||||
|
||||
CXref* pXref = new CXref(this, 0, 65535);
|
||||
if (pXref)
|
||||
{
|
||||
pXref->SetPrev(pXrefPage);
|
||||
CDictObject* pTrailer = pXref->GetTrailer();
|
||||
m_pTrailer->Copy(pTrailer);
|
||||
|
||||
CEncrypt* pEncrypt = NULL;
|
||||
if (m_pEncryptDict)
|
||||
pEncrypt = m_pEncryptDict->GetEncrypt();
|
||||
|
||||
pXref->WriteToStream(pStream, pEncrypt, bNeedStreamXRef);
|
||||
nPrevAddr = pXref->GetPrevAddr();
|
||||
nSizeXRef = m_pXref->GetSizeXRef();
|
||||
vXRefForWrite.push_back(pXref);
|
||||
}
|
||||
|
||||
RELEASEOBJECT(pStream);
|
||||
pStream = new CFileStream();
|
||||
if (pStream && pStream->OpenFile(wsPath, false))
|
||||
pField->GetSignatureDict()->WriteToStream(pStream, pStream->Size());
|
||||
|
||||
m_pXref = pXrefBefore;
|
||||
RELEASEOBJECT(pStream);
|
||||
m_vSignatures[0]->wsPath = wsPath;
|
||||
m_vSignatures[0]->nSizeXRef = nSizeXRef;
|
||||
m_vSignatures[0]->bNeedStreamXRef = bNeedStreamXRef;
|
||||
}
|
||||
for (CXref* XRef : vXRefForWrite)
|
||||
RELEASEOBJECT(XRef);
|
||||
vXRefForWrite.clear();
|
||||
}
|
||||
void CDocument::AddShapeXML(const std::string& sXML)
|
||||
{
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#define _PDF_WRITER_SRC_DOCUMENT_H
|
||||
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include "Types.h"
|
||||
|
||||
@ -195,7 +196,9 @@ namespace PdfWriter
|
||||
bool AddToFile(const std::wstring& wsPath, CXref* pXref, CDictObject* pTrailer, CXref* pInfoXref, CInfoDict* pInfo);
|
||||
void AddObject(CObjectBase* pObj);
|
||||
bool MovePage(int nPageIndex, int nPos);
|
||||
void Sign(const TRect& oRect, CImageDict* pImage, ICertificate* pCert);
|
||||
void Sign(const TRect& oRect, CImageDict* pImage);
|
||||
bool PrepareSignature(BYTE** pDataToSign, DWORD& dwDataLength);
|
||||
bool FinalizeSignature(BYTE* pSignedData, DWORD dwDataLength);
|
||||
bool EditAnnot (CXref* pXref, CAnnotation* pAnnot, int nID);
|
||||
void AddParent(int nID, CDictObject* pParent);
|
||||
CDictObject* CreateParent(int nID);
|
||||
@ -255,18 +258,27 @@ namespace PdfWriter
|
||||
};
|
||||
struct TSignatureInfo
|
||||
{
|
||||
TSignatureInfo(const TRect& _oRect, CPage* _pPage, CImageDict* _pImage, ICertificate* _pCertificate)
|
||||
TSignatureInfo(const TRect& _oRect, CPage* _pPage, CImageDict* _pImage)
|
||||
{
|
||||
oRect = _oRect;
|
||||
pPage = _pPage;
|
||||
pImage = _pImage;
|
||||
pCertificate = _pCertificate;
|
||||
|
||||
nSizeXRef = 0;
|
||||
bNeedStreamXRef = false;
|
||||
pField = NULL;
|
||||
pXref = NULL;
|
||||
}
|
||||
|
||||
TRect oRect;
|
||||
CPage* pPage;
|
||||
CImageDict* pImage;
|
||||
ICertificate* pCertificate;
|
||||
|
||||
std::wstring wsPath;
|
||||
unsigned int nSizeXRef;
|
||||
bool bNeedStreamXRef;
|
||||
CSignatureField* pField;
|
||||
CXref* pXref;
|
||||
};
|
||||
struct TImageInfo
|
||||
{
|
||||
@ -296,7 +308,7 @@ namespace PdfWriter
|
||||
CStreamData* m_pMetaData;
|
||||
bool m_bEncrypt;
|
||||
CEncryptDict* m_pEncryptDict;
|
||||
std::vector<TSignatureInfo> m_vSignatures;
|
||||
std::deque<TSignatureInfo*> m_vSignatures;
|
||||
std::vector<TImageInfo> m_vImages;
|
||||
unsigned int m_unFormFields;
|
||||
unsigned int m_unCompressMode;
|
||||
|
||||
@ -223,32 +223,6 @@ namespace PdfWriter
|
||||
Add("Filter", "Adobe.PPKLite");
|
||||
Add("SubFilter", "adbe.pkcs7.detached");
|
||||
|
||||
unsigned int unDigestLength = 15000;
|
||||
BYTE* pDigest = new BYTE[unDigestLength];
|
||||
memset(pDigest, 0, unDigestLength);
|
||||
Add("Contents", new CBinaryObject(pDigest, unDigestLength));
|
||||
RELEASEARRAYOBJECTS(pDigest);
|
||||
|
||||
CArrayObject* pByteRange = new CArrayObject();
|
||||
if (!pByteRange)
|
||||
return;
|
||||
Add("ByteRange", pByteRange);
|
||||
pByteRange->Add(0);
|
||||
pByteRange->Add(1234567890);
|
||||
pByteRange->Add(1234567890);
|
||||
pByteRange->Add(1234567890);
|
||||
|
||||
// Reference - Массив справочных словарей сигнатур
|
||||
|
||||
// Changes - Массив из трех чисел, который указывает изменения в документе в порядке: количество измененных страниц,
|
||||
// количество измененных полей и количество заполненных полей
|
||||
// Порядок подписей определяется значением ByteRange. Поскольку каждая подпись приводит к добавочному сохранению,
|
||||
// более поздние подписи имеют большее значение длины
|
||||
|
||||
// Prop_Build - Словарь, который может использоваться обработчиком подписи для записи информации о состоянии компьютерной среды,
|
||||
// используемой для подписи, такой как имя обработчика, используемого для создания подписи, дата сборки программного обеспечения,
|
||||
// версия, и операционная система. Спецификация словаря PDF Signature Build содержит рекомендации по использованию этого словаря
|
||||
|
||||
m_nLen1 = 0;
|
||||
m_nOffset2 = 0;
|
||||
m_nByteRangeBegin = 0;
|
||||
@ -259,40 +233,33 @@ namespace PdfWriter
|
||||
}
|
||||
void CSignatureDict::WriteToStream(CStream* pStream, CEncrypt* pEncrypt)
|
||||
{
|
||||
for (auto const &oIter : m_mList)
|
||||
for (std::map<std::string, CObjectBase*>::const_iterator oIter = m_mList.begin(); oIter != m_mList.end(); ++oIter)
|
||||
{
|
||||
CObjectBase* pObject = oIter.second;
|
||||
if (!pObject)
|
||||
CObjectBase* pObject = oIter->second;
|
||||
if (!pObject || pObject->IsHidden())
|
||||
continue;
|
||||
|
||||
if (pObject->IsHidden())
|
||||
int nBegin, nEnd;
|
||||
pStream->WriteEscapeName(oIter->first.c_str());
|
||||
pStream->WriteChar(' ');
|
||||
nBegin = pStream->Tell();
|
||||
// Цифровая подпись не шифруется
|
||||
pStream->Write(pObject, oIter->first == "Contents" ? NULL : pEncrypt);
|
||||
nEnd = pStream->Tell();
|
||||
pStream->WriteStr("\012");
|
||||
if (oIter->first == "Contents")
|
||||
{
|
||||
// ничего не делаем
|
||||
m_nLen1 = nBegin;
|
||||
m_nOffset2 = nEnd;
|
||||
}
|
||||
else
|
||||
if (oIter->first == "ByteRange")
|
||||
{
|
||||
int nBegin, nEnd;
|
||||
pStream->WriteEscapeName(oIter.first.c_str());
|
||||
pStream->WriteChar(' ');
|
||||
nBegin = pStream->Tell();
|
||||
// Цифровая подпись не шифруется
|
||||
pStream->Write(pObject, oIter.first == "Contents" ? NULL : pEncrypt);
|
||||
nEnd = pStream->Tell();
|
||||
pStream->WriteStr("\012");
|
||||
if (oIter.first == "Contents")
|
||||
{
|
||||
m_nLen1 = nBegin;
|
||||
m_nOffset2 = nEnd;
|
||||
}
|
||||
if (oIter.first == "ByteRange")
|
||||
{
|
||||
m_nByteRangeBegin = nBegin;
|
||||
m_nByteRangeEnd = nEnd;
|
||||
}
|
||||
m_nByteRangeBegin = nBegin;
|
||||
m_nByteRangeEnd = nEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
void CSignatureDict::WriteToStream(CStream* pStream, int nFileEnd)
|
||||
void CSignatureDict::WriteToStream(CStream* pStream, int nFileEnd, BYTE** pDataForSignature, DWORD& dwLenDataForSignature)
|
||||
{
|
||||
// Запись ByteRange
|
||||
if (m_nByteRangeBegin > 0 && m_nByteRangeEnd > 0 && m_nByteRangeBegin < m_nByteRangeEnd && m_nByteRangeEnd < nFileEnd)
|
||||
@ -325,16 +292,16 @@ namespace PdfWriter
|
||||
RELEASEOBJECT(pByteRange);
|
||||
}
|
||||
// Запись Contents
|
||||
if (m_pCertificate && m_nLen1 > 0 && m_nOffset2 > 0 && m_nLen1 < m_nOffset2 && m_nOffset2 < nFileEnd)
|
||||
if (m_nLen1 > 0 && m_nOffset2 > 0 && m_nLen1 < m_nOffset2 && m_nOffset2 < nFileEnd)
|
||||
{
|
||||
DWORD dwLenDataForSignature = m_nLen1 + nFileEnd - m_nOffset2;
|
||||
BYTE* pDataForSignature = new BYTE[dwLenDataForSignature];
|
||||
if (!pDataForSignature)
|
||||
dwLenDataForSignature = m_nLen1 + nFileEnd - m_nOffset2;
|
||||
*pDataForSignature = new BYTE[dwLenDataForSignature];
|
||||
if (!*pDataForSignature)
|
||||
return;
|
||||
|
||||
pStream->Seek(0, EWhenceMode::SeekSet);
|
||||
unsigned int dwLenReadData = m_nLen1;
|
||||
pStream->Read(pDataForSignature, &dwLenReadData);
|
||||
pStream->Read(*pDataForSignature, &dwLenReadData);
|
||||
if ((int)dwLenReadData != m_nLen1)
|
||||
{
|
||||
RELEASEARRAYOBJECTS(pDataForSignature);
|
||||
@ -343,40 +310,69 @@ namespace PdfWriter
|
||||
|
||||
pStream->Seek(m_nOffset2, EWhenceMode::SeekSet);
|
||||
dwLenReadData = nFileEnd - m_nOffset2;
|
||||
pStream->Read(pDataForSignature + m_nLen1, &dwLenReadData);
|
||||
pStream->Read(*pDataForSignature + m_nLen1, &dwLenReadData);
|
||||
if ((int)dwLenReadData != nFileEnd - m_nOffset2)
|
||||
{
|
||||
RELEASEARRAYOBJECTS(pDataForSignature);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
BYTE* pDatatoWrite = NULL;
|
||||
unsigned int dwLenDatatoWrite;
|
||||
m_pCertificate->SignPKCS7(pDataForSignature, dwLenDataForSignature, pDatatoWrite, dwLenDatatoWrite);
|
||||
RELEASEARRAYOBJECTS(pDataForSignature);
|
||||
if (!pDatatoWrite)
|
||||
return;
|
||||
|
||||
pStream->Seek(m_nLen1, EWhenceMode::SeekSet);
|
||||
CBinaryObject* pContents = new CBinaryObject(pDatatoWrite, dwLenDatatoWrite);
|
||||
RELEASEARRAYOBJECTS(pDatatoWrite);
|
||||
if (!pContents)
|
||||
return;
|
||||
// Цифровая подпись не шифруется
|
||||
pStream->Write(pContents, NULL);
|
||||
RELEASEOBJECT(pContents);
|
||||
|
||||
// Стереть лишний >
|
||||
BYTE cChar = '0';
|
||||
pStream->Seek(pStream->Tell() - 1, EWhenceMode::SeekSet);
|
||||
pStream->Write(&cChar, 1);
|
||||
*/
|
||||
}
|
||||
}
|
||||
void CSignatureDict::SetCert(ICertificate* pCert)
|
||||
{
|
||||
m_pCertificate = pCert;
|
||||
}
|
||||
void CSignatureDict::SetName(const std::string& sName)
|
||||
bool CSignatureDict::FinalizeSignature(CStream* pStream, BYTE* pSignedData, DWORD dwDataLength)
|
||||
{
|
||||
if (!pSignedData)
|
||||
return false;
|
||||
|
||||
// Записываем подписанные данные в Contents
|
||||
if (dwDataLength > m_nContentsSize)
|
||||
{
|
||||
// Подпись не влезает! Ошибка расчета размера
|
||||
return false;
|
||||
}
|
||||
|
||||
pStream->Seek(m_nLen1, EWhenceMode::SeekSet);
|
||||
CBinaryObject* pContents = new CBinaryObject(pSignedData, dwDataLength);
|
||||
if (!pContents)
|
||||
return false;
|
||||
|
||||
// Цифровая подпись не шифруется
|
||||
pStream->Write(pContents, NULL);
|
||||
delete pContents;
|
||||
|
||||
// Стираем лишний '>' если нужно
|
||||
BYTE cChar = '0';
|
||||
pStream->Seek(pStream->Tell() - 1, EWhenceMode::SeekSet);
|
||||
pStream->Write(&cChar, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
void CSignatureDict::SetContentsSize(unsigned int nSize)
|
||||
{
|
||||
m_nContentsSize = nSize;
|
||||
|
||||
BYTE* pDigest = new BYTE[m_nContentsSize];
|
||||
memset(pDigest, 0, m_nContentsSize);
|
||||
Add("Contents", new CBinaryObject(pDigest, m_nContentsSize, false));
|
||||
|
||||
CArrayObject* pByteRange = new CArrayObject();
|
||||
if (!pByteRange)
|
||||
return;
|
||||
Add("ByteRange", pByteRange);
|
||||
pByteRange->Add(0);
|
||||
pByteRange->Add(1234567890);
|
||||
pByteRange->Add(1234567890);
|
||||
pByteRange->Add(1234567890);
|
||||
}
|
||||
void CSignatureDict::SetName(const std::string& sName)
|
||||
{
|
||||
// Name - Cтрока, Имя лица или органа, подписавшего документ.
|
||||
// Значение следует использовать когда невозможно извлечь имя из подписи или сертификата подписавшего.
|
||||
|
||||
@ -34,8 +34,6 @@
|
||||
|
||||
#include "Objects.h"
|
||||
|
||||
#include "../../DesktopEditor/xmlsec/src/include/Certificate.h"
|
||||
|
||||
namespace PdfWriter
|
||||
{
|
||||
class CEncrypt;
|
||||
@ -78,18 +76,19 @@ namespace PdfWriter
|
||||
}
|
||||
|
||||
void WriteToStream(CStream* pStream, CEncrypt* pEncrypt) override;
|
||||
void WriteToStream(CStream* pStream, int nFileEnd);
|
||||
void SetCert(ICertificate* pCert);
|
||||
void WriteToStream(CStream* pStream, int nFileEnd, BYTE** pDataToSign, DWORD& dwDataLength);
|
||||
bool FinalizeSignature(CStream* pStream, BYTE* pSignedData, DWORD dwDataLength);
|
||||
|
||||
void SetContentsSize(unsigned int nSize);
|
||||
void SetName(const std::string& sName);
|
||||
void SetReason(const std::string& sReason);
|
||||
void SetContact(const std::string& sContacts);
|
||||
void SetDate();
|
||||
private:
|
||||
ICertificate* m_pCertificate;
|
||||
unsigned int m_nContentsSize; // Размер Contents
|
||||
|
||||
int m_nLen1; // Длина первого интервала сигнатуры
|
||||
int m_nOffset2; // Начало второго интервала сигнатуры
|
||||
int m_nLen1; // Длина первого интервала
|
||||
int m_nOffset2; // Начало второго интервала
|
||||
|
||||
int m_nByteRangeBegin; // Смещение начала массива ByteRange
|
||||
int m_nByteRangeEnd; // Смещение конца массива ByteRange
|
||||
|
||||
@ -524,7 +524,7 @@ TEST_F(CPdfFileTest, EditPdf)
|
||||
|
||||
TEST_F(CPdfFileTest, EditPdfFromBase64)
|
||||
{
|
||||
//GTEST_SKIP();
|
||||
GTEST_SKIP();
|
||||
|
||||
NSFonts::NSApplicationFontStream::SetGlobalMemoryStorage(NSFonts::NSApplicationFontStream::CreateDefaultGlobalMemoryStorage());
|
||||
|
||||
@ -602,22 +602,93 @@ TEST_F(CPdfFileTest, EditPdfFromBin)
|
||||
|
||||
TEST_F(CPdfFileTest, EditPdfSign)
|
||||
{
|
||||
GTEST_SKIP();
|
||||
//GTEST_SKIP();
|
||||
|
||||
LoadFromFile();
|
||||
ASSERT_TRUE(pdfFile->EditPdf(wsDstFile));
|
||||
|
||||
ICertificate* pCertificate = GetCertificate();
|
||||
ASSERT_TRUE(pCertificate);
|
||||
|
||||
EXPECT_TRUE(pdfFile->EditPage(0));
|
||||
{
|
||||
pdfFile->Sign(10, 10, 100, 100, NSFile::GetProcessDirectory() + L"/test.jpeg", pCertificate);
|
||||
pdfFile->Sign(10, 10, 100, 100, NSFile::GetProcessDirectory() + L"/test.jpeg");
|
||||
pdfFile->Sign(10, 150, 100, 100, NSFile::GetProcessDirectory() + L"/test.jpeg");
|
||||
pdfFile->Sign(10, 300, 100, 100, NSFile::GetProcessDirectory() + L"/test.jpeg");
|
||||
}
|
||||
|
||||
// Для цифровой подписи важно предварительно pdfFile->EditClose, в остальных случаях pdfFile->Close() сделает тоже самое
|
||||
pdfFile->EditClose();
|
||||
|
||||
// EditPdf & EditClose || CreatePdf & SaveToFile
|
||||
// И только после подготовка данных для подписания, подписываем, запись подписи
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
BYTE* pDataToSign = NULL;
|
||||
DWORD dwDataLength = 0;
|
||||
|
||||
// Получили данные для подписания
|
||||
pdfFile->PrepareSignature(&pDataToSign, dwDataLength);
|
||||
|
||||
ICertificate* pCertificate = GetCertificate();
|
||||
ASSERT_TRUE(pCertificate);
|
||||
|
||||
BYTE* pDatatoWrite = NULL;
|
||||
unsigned int dwLenDatatoWrite = 0;
|
||||
// Предположим, что для подписи 1 произошло не успешное подписание, и данные остались пустыми
|
||||
pCertificate->SignPKCS7(pDataToSign, dwDataLength, pDatatoWrite, dwLenDatatoWrite);
|
||||
|
||||
// Обязательно FinalizeSignature - он либо заполнит данные, либо сделает подпись пустой
|
||||
pdfFile->FinalizeSignature(pDatatoWrite, dwLenDatatoWrite);
|
||||
|
||||
RELEASEOBJECT(pCertificate);
|
||||
}
|
||||
|
||||
pdfFile->Close();
|
||||
}
|
||||
|
||||
RELEASEOBJECT(pCertificate);
|
||||
TEST_F(CPdfFileTest, PdfToPdfSign)
|
||||
{
|
||||
GTEST_SKIP();
|
||||
|
||||
LoadFromFile();
|
||||
pdfFile->CreatePdf();
|
||||
|
||||
double dPageDpiX, dPageDpiY, dW, dH;
|
||||
int nPages = pdfFile->GetPagesCount();
|
||||
for (int i = 0; i < nPages; i++)
|
||||
{
|
||||
pdfFile->NewPage();
|
||||
|
||||
pdfFile->GetPageInfo(i, &dW, &dH, &dPageDpiX, &dPageDpiY);
|
||||
pdfFile->put_Width( dW / dPageDpiX * 25.4);
|
||||
pdfFile->put_Height(dH / dPageDpiY * 25.4);
|
||||
|
||||
pdfFile->DrawPageOnRenderer(pdfFile, i, NULL);
|
||||
|
||||
pdfFile->Sign(10, 10, 100, 100, NSFile::GetProcessDirectory() + L"/test.jpeg");
|
||||
}
|
||||
|
||||
pdfFile->SaveToFile(wsDstFile);
|
||||
|
||||
for (int i = 0; i < nPages; ++i)
|
||||
{
|
||||
BYTE* pDataToSign = NULL;
|
||||
DWORD dwDataLength = 0;
|
||||
|
||||
pdfFile->PrepareSignature(&pDataToSign, dwDataLength);
|
||||
|
||||
ICertificate* pCertificate = GetCertificate();
|
||||
ASSERT_TRUE(pCertificate);
|
||||
|
||||
BYTE* pDatatoWrite = NULL;
|
||||
unsigned int dwLenDatatoWrite = 0;
|
||||
if (i % 2 == 0)
|
||||
pCertificate->SignPKCS7(pDataToSign, dwDataLength, pDatatoWrite, dwLenDatatoWrite);
|
||||
|
||||
pdfFile->FinalizeSignature(pDatatoWrite, dwLenDatatoWrite);
|
||||
|
||||
RELEASEOBJECT(pCertificate);
|
||||
}
|
||||
|
||||
pdfFile->Close();
|
||||
}
|
||||
|
||||
TEST_F(CPdfFileTest, PrintPdf)
|
||||
|
||||
Reference in New Issue
Block a user