mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-02-10 18:05:41 +08:00
Create FileAttachment annot
This commit is contained in:
@ -686,6 +686,27 @@ void ReadAnnotAP(BYTE* pWidgetsAP, int& i)
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
void ReadFileAttachment(BYTE* pAnnots, int& i, int n)
|
||||
{
|
||||
std::cout << "EF FileAttachment" << n << ".txt, ";
|
||||
int nFileLength = READ_INT(pAnnots + i);
|
||||
i += 4;
|
||||
|
||||
unsigned long long npFile1 = READ_INT(pAnnots + i);
|
||||
i += 4;
|
||||
unsigned long long npFile2 = READ_INT(pAnnots + i);
|
||||
i += 4;
|
||||
|
||||
BYTE* res = (BYTE*)(npFile2 << 32 | npFile1);
|
||||
|
||||
NSFile::CFileBinary oFile;
|
||||
if (oFile.CreateFileW(NSFile::GetProcessDirectory() + L"/FileAttachment" + std::to_wstring(n) + L".txt"))
|
||||
oFile.WriteFile(res, nFileLength);
|
||||
oFile.CloseFile();
|
||||
|
||||
RELEASEARRAYOBJECTS(res);
|
||||
}
|
||||
|
||||
#include "../../../../../fontengine/ApplicationFontsWorker.h"
|
||||
#include "../../../../../common/Directory.h"
|
||||
|
||||
@ -1443,6 +1464,97 @@ int main(int argc, char* argv[])
|
||||
std::cout << "Sy " << arrSy[nPathLength] << ", ";
|
||||
}
|
||||
}
|
||||
else if (sType == "FileAttachment")
|
||||
{
|
||||
if (nFlags & (1 << 15))
|
||||
{
|
||||
nPathLength = READ_INT(pAnnots + i);
|
||||
i += 4;
|
||||
std::cout << "Name " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
|
||||
i += nPathLength;
|
||||
}
|
||||
if (nFlags & (1 << 16))
|
||||
{
|
||||
nPathLength = READ_INT(pAnnots + i);
|
||||
i += 4;
|
||||
std::cout << "FS " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
|
||||
i += nPathLength;
|
||||
}
|
||||
if (nFlags & (1 << 17))
|
||||
{
|
||||
nPathLength = READ_INT(pAnnots + i);
|
||||
i += 4;
|
||||
std::cout << "F " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
|
||||
i += nPathLength;
|
||||
}
|
||||
if (nFlags & (1 << 18))
|
||||
{
|
||||
nPathLength = READ_INT(pAnnots + i);
|
||||
i += 4;
|
||||
std::cout << "UF " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
|
||||
i += nPathLength;
|
||||
}
|
||||
if (nFlags & (1 << 19))
|
||||
{
|
||||
nPathLength = READ_INT(pAnnots + i);
|
||||
i += 4;
|
||||
std::cout << "DOS " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
|
||||
i += nPathLength;
|
||||
}
|
||||
if (nFlags & (1 << 20))
|
||||
{
|
||||
nPathLength = READ_INT(pAnnots + i);
|
||||
i += 4;
|
||||
std::cout << "Mac " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
|
||||
i += nPathLength;
|
||||
}
|
||||
if (nFlags & (1 << 21))
|
||||
{
|
||||
nPathLength = READ_INT(pAnnots + i);
|
||||
i += 4;
|
||||
std::cout << "Unix " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
|
||||
i += nPathLength;
|
||||
}
|
||||
if (nFlags & (1 << 22))
|
||||
{
|
||||
nPathLength = READ_INT(pAnnots + i);
|
||||
i += 4;
|
||||
std::cout << "ID " << std::string((char*)(pAnnots + i), nPathLength);
|
||||
i += nPathLength;
|
||||
|
||||
nPathLength = READ_INT(pAnnots + i);
|
||||
i += 4;
|
||||
std::cout << " " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
|
||||
i += nPathLength;
|
||||
}
|
||||
if (nFlags & (1 << 23))
|
||||
std::cout << "V true, ";
|
||||
else
|
||||
std::cout << "V false, ";
|
||||
if (nFlags & (1 << 24))
|
||||
{
|
||||
int nFlag = READ_INT(pAnnots + i);
|
||||
i += 4;
|
||||
|
||||
if (nFlag & (1 << 0))
|
||||
ReadFileAttachment(pAnnots, i, 0);
|
||||
if (nFlag & (1 << 1))
|
||||
ReadFileAttachment(pAnnots, i, 1);
|
||||
if (nFlag & (1 << 2))
|
||||
ReadFileAttachment(pAnnots, i, 2);
|
||||
if (nFlag & (1 << 3))
|
||||
ReadFileAttachment(pAnnots, i, 3);
|
||||
if (nFlag & (1 << 4))
|
||||
ReadFileAttachment(pAnnots, i, 4);
|
||||
}
|
||||
if (nFlags & (1 << 26))
|
||||
{
|
||||
nPathLength = READ_INT(pAnnots + i);
|
||||
i += 4;
|
||||
std::cout << "Desc " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
|
||||
i += nPathLength;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
@ -1635,6 +1635,10 @@ void GetPageAnnots(PDFDoc* pdfDoc, NSWasm::CData& oRes, int nPageIndex)
|
||||
{
|
||||
pAnnot = new PdfReader::CAnnotInk(pdfDoc, &oAnnotRef, nPageIndex);
|
||||
}
|
||||
else if (sType == "FileAttachment")
|
||||
{
|
||||
pAnnot = new PdfReader::CAnnotFileAttachment(pdfDoc, &oAnnotRef, nPageIndex);
|
||||
}
|
||||
// else if (sType == "Popup")
|
||||
// {
|
||||
// pAnnot = new PdfReader::CAnnotPopup(pdfDoc, &oAnnotRef, nPageIndex);
|
||||
|
||||
@ -61,6 +61,15 @@ oObj.free();\
|
||||
put = oObj2.getNum();\
|
||||
oObj2.free();\
|
||||
}
|
||||
#define WRITE_EF(EF) \
|
||||
{ \
|
||||
oRes.AddInt(EF->nLength); \
|
||||
unsigned long long npSubMatrix = (unsigned long long)EF->pFile; \
|
||||
unsigned int npSubMatrix1 = npSubMatrix & 0xFFFFFFFF; \
|
||||
oRes.AddInt(npSubMatrix1); \
|
||||
oRes.AddInt(npSubMatrix >> 32); \
|
||||
EF->bFree = false; \
|
||||
}
|
||||
|
||||
TextString* getName(Object* oField)
|
||||
{
|
||||
@ -412,6 +421,28 @@ BYTE getLE(Object* oObj)
|
||||
|
||||
return nLE;
|
||||
}
|
||||
CAnnotFileAttachment::CEmbeddedFile* getEF(Object* oObj)
|
||||
{
|
||||
CAnnotFileAttachment::CEmbeddedFile* pRes = new CAnnotFileAttachment::CEmbeddedFile();
|
||||
|
||||
Object oObj2;
|
||||
Dict* pImDict = oObj->streamGetDict();
|
||||
if (pImDict->lookup("Length", &oObj2)->isInt())
|
||||
pRes->nLength = oObj2.getInt();
|
||||
oObj2.free();
|
||||
if (pImDict->lookup("DL", &oObj2)->isInt())
|
||||
pRes->nLength = oObj2.getInt();
|
||||
oObj2.free();
|
||||
|
||||
Stream* pImage = oObj->getStream();
|
||||
pImage->reset();
|
||||
pRes->pFile = new BYTE[pRes->nLength];
|
||||
BYTE* pBufferPtr = pRes->pFile;
|
||||
for (int nI = 0; nI < pRes->nLength; ++nI)
|
||||
*pBufferPtr++ = (BYTE)pImage->getChar();
|
||||
|
||||
return pRes;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Widget
|
||||
@ -1409,7 +1440,7 @@ CAnnotCaret::CAnnotCaret(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex) : CM
|
||||
oAnnotRef->fetch(pXref, &oAnnot);
|
||||
|
||||
// 16 - Различия Rect и фактического размера - RD
|
||||
if (oAnnot.dictLookup("RD", &oObj)->isArray())
|
||||
if (oAnnot.dictLookup("RD", &oObj)->isArray() && oObj.arrayGetLength() == 4)
|
||||
{
|
||||
m_unFlags |= (1 << 15);
|
||||
ARR_GET_NUM(oObj, 0, m_pRD[0]);
|
||||
@ -1434,6 +1465,132 @@ CAnnotCaret::CAnnotCaret(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex) : CM
|
||||
oAnnot.free();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// FileAttachment
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
CAnnotFileAttachment::CAnnotFileAttachment(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex) : CMarkupAnnot(pdfDoc, oAnnotRef, nPageIndex)
|
||||
{
|
||||
m_pEF = NULL;
|
||||
|
||||
Object oAnnot, oObj, oObj2;
|
||||
XRef* pXref = pdfDoc->getXRef();
|
||||
oAnnotRef->fetch(pXref, &oAnnot);
|
||||
|
||||
// 16 - Иконка - Name
|
||||
if (oAnnot.dictLookup("Name", &oObj)->isName())
|
||||
{
|
||||
m_unFlags |= (1 << 15);
|
||||
m_sName = oObj.getName();
|
||||
}
|
||||
oObj.free();
|
||||
|
||||
Object oFS;
|
||||
if (!oAnnot.dictLookup("FS", &oFS)->isDict())
|
||||
{
|
||||
oFS.free(); oAnnot.free();
|
||||
return;
|
||||
}
|
||||
|
||||
// 17 - Файловая система - FS
|
||||
if (oFS.dictLookup("FS", &oObj)->isName())
|
||||
{
|
||||
m_unFlags |= (1 << 16);
|
||||
m_sFS = oObj.getName();
|
||||
}
|
||||
oObj.free();
|
||||
|
||||
// 18 - Спецификация файла - F
|
||||
DICT_LOOKUP_STRING(oFS.dictLookup, "F", 17, m_sF);
|
||||
|
||||
// 19 - Спецификация файла - UF
|
||||
DICT_LOOKUP_STRING(oFS.dictLookup, "UF", 18, m_sUF);
|
||||
|
||||
// 20 - Спецификация файла - DOS
|
||||
DICT_LOOKUP_STRING(oFS.dictLookup, "DOS", 19, m_sDOS);
|
||||
|
||||
// 21 - Спецификация файла - Mac
|
||||
DICT_LOOKUP_STRING(oFS.dictLookup, "Mac", 20, m_sMac);
|
||||
|
||||
// 22 - Спецификация файла - Unix
|
||||
DICT_LOOKUP_STRING(oFS.dictLookup, "Unix", 21, m_sUnix);
|
||||
|
||||
// 23 - Идентификатор файла - ID
|
||||
if (oFS.dictLookup("ID", &oObj)->isArray() && oObj.arrayGetLength() == 2)
|
||||
{
|
||||
m_unFlags |= (1 << 22);
|
||||
if (oObj.arrayGet(0, &oObj2)->isString())
|
||||
{
|
||||
TextString* s = new TextString(oObj2.getString());
|
||||
m_sID.first = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
|
||||
delete s;
|
||||
}
|
||||
oObj2.free();
|
||||
if (oObj.arrayGet(1, &oObj2)->isString())
|
||||
{
|
||||
TextString* s = new TextString(oObj2.getString());
|
||||
m_sID.second = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
|
||||
delete s;
|
||||
}
|
||||
oObj2.free();
|
||||
}
|
||||
oObj.free();
|
||||
|
||||
// 24 - Изменчивость файла - V
|
||||
if (oFS.dictLookup("V", &oObj)->isBool() && oObj.getBool())
|
||||
m_unFlags |= (1 << 23);
|
||||
oObj.free();
|
||||
|
||||
// 25 - Встроенные файловые потоки - EF
|
||||
Object oEF;
|
||||
if (oFS.dictLookup("EF", &oEF)->isDict())
|
||||
{
|
||||
m_unFlags |= (1 << 24);
|
||||
m_pEF = new CEmbeddedFiles();
|
||||
if (oEF.dictLookup("F", &oObj)->isStream())
|
||||
m_pEF->m_pF = getEF(&oObj);
|
||||
oObj.free();
|
||||
if (oEF.dictLookup("UF", &oObj)->isStream())
|
||||
m_pEF->m_pUF = getEF(&oObj);
|
||||
oObj.free();
|
||||
if (oEF.dictLookup("DOS", &oObj)->isStream())
|
||||
m_pEF->m_pDOS = getEF(&oObj);
|
||||
oObj.free();
|
||||
if (oEF.dictLookup("Mac", &oObj)->isStream())
|
||||
m_pEF->m_pMac = getEF(&oObj);
|
||||
oObj.free();
|
||||
if (oEF.dictLookup("Unix", &oObj)->isStream())
|
||||
m_pEF->m_pUnix = getEF(&oObj);
|
||||
oObj.free();
|
||||
}
|
||||
oEF.free();
|
||||
|
||||
// 26 - Встроенные файловые потоки - RF
|
||||
Object oRF;
|
||||
if (oFS.dictLookup("RF", &oRF)->isDict())
|
||||
{
|
||||
m_unFlags |= (1 << 25);
|
||||
}
|
||||
oRF.free();
|
||||
|
||||
// 27 - Описание файла - Desc
|
||||
DICT_LOOKUP_STRING(oFS.dictLookup, "Desc", 26, m_sDesc);
|
||||
|
||||
// 28 - Коллекция - Cl
|
||||
if (oFS.dictLookup("Cl", &oObj)->isDict())
|
||||
{
|
||||
m_unFlags |= (1 << 27);
|
||||
}
|
||||
oObj.free();
|
||||
|
||||
oFS.free(); oAnnot.free();
|
||||
}
|
||||
|
||||
CAnnotFileAttachment::~CAnnotFileAttachment()
|
||||
{
|
||||
RELEASEOBJECT(m_pEF);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Annots
|
||||
//------------------------------------------------------------------------
|
||||
@ -2736,4 +2893,72 @@ void CAnnotCaret::ToWASM(NSWasm::CData& oRes)
|
||||
if (m_unFlags & (1 << 16))
|
||||
oRes.WriteBYTE(m_nSy);
|
||||
}
|
||||
|
||||
void CAnnotFileAttachment::ToWASM(NSWasm::CData& oRes)
|
||||
{
|
||||
oRes.WriteBYTE(16); // FileAttachment
|
||||
|
||||
CMarkupAnnot::ToWASM(oRes);
|
||||
|
||||
if (m_unFlags & (1 << 15))
|
||||
oRes.WriteString(m_sName);
|
||||
if (m_unFlags & (1 << 16))
|
||||
oRes.WriteString(m_sFS);
|
||||
if (m_unFlags & (1 << 17))
|
||||
oRes.WriteString(m_sF);
|
||||
if (m_unFlags & (1 << 18))
|
||||
oRes.WriteString(m_sUF);
|
||||
if (m_unFlags & (1 << 19))
|
||||
oRes.WriteString(m_sDOS);
|
||||
if (m_unFlags & (1 << 20))
|
||||
oRes.WriteString(m_sMac);
|
||||
if (m_unFlags & (1 << 21))
|
||||
oRes.WriteString(m_sUnix);
|
||||
if (m_unFlags & (1 << 22))
|
||||
{
|
||||
oRes.WriteString(m_sID.first);
|
||||
oRes.WriteString(m_sID.second);
|
||||
}
|
||||
if (m_unFlags & (1 << 24))
|
||||
{
|
||||
int nFlag = 0;
|
||||
int nPos = oRes.GetSize();
|
||||
oRes.AddInt(nFlag);
|
||||
// Освобождение памяти необходимо вызвать с js стороны
|
||||
if (m_pEF->m_pF)
|
||||
{
|
||||
nFlag |= (1 << 0);
|
||||
WRITE_EF(m_pEF->m_pF);
|
||||
}
|
||||
if (m_pEF->m_pUF)
|
||||
{
|
||||
nFlag |= (1 << 1);
|
||||
WRITE_EF(m_pEF->m_pUF);
|
||||
}
|
||||
if (m_pEF->m_pDOS)
|
||||
{
|
||||
nFlag |= (1 << 2);
|
||||
WRITE_EF(m_pEF->m_pDOS);
|
||||
}
|
||||
if (m_pEF->m_pMac)
|
||||
{
|
||||
nFlag |= (1 << 3);
|
||||
WRITE_EF(m_pEF->m_pMac);
|
||||
}
|
||||
if (m_pEF->m_pUnix)
|
||||
{
|
||||
nFlag |= (1 << 4);
|
||||
WRITE_EF(m_pEF->m_pUnix);
|
||||
}
|
||||
oRes.AddInt(nFlag, nPos);
|
||||
}
|
||||
if (m_unFlags & (1 << 25))
|
||||
{
|
||||
}
|
||||
if (m_unFlags & (1 << 26))
|
||||
oRes.WriteString(m_sDesc);
|
||||
if (m_unFlags & (1 << 27))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -473,6 +473,62 @@ private:
|
||||
double m_pRD[4]{}; // Различия Rect и фактического размера
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// PdfReader::CAnnotFileAttachment
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
class CAnnotFileAttachment final : public CMarkupAnnot
|
||||
{
|
||||
public:
|
||||
CAnnotFileAttachment(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex);
|
||||
virtual ~CAnnotFileAttachment();
|
||||
|
||||
void ToWASM(NSWasm::CData& oRes) override;
|
||||
|
||||
struct CEmbeddedFile
|
||||
{
|
||||
BYTE* pFile;
|
||||
int nLength;
|
||||
bool bFree;
|
||||
|
||||
CEmbeddedFile() : pFile(NULL), nLength(0), bFree(true) {}
|
||||
~CEmbeddedFile() { if (bFree) RELEASEARRAYOBJECTS(pFile); }
|
||||
};
|
||||
|
||||
struct CEmbeddedFiles
|
||||
{
|
||||
CEmbeddedFile* m_pF;
|
||||
CEmbeddedFile* m_pUF;
|
||||
CEmbeddedFile* m_pDOS;
|
||||
CEmbeddedFile* m_pMac;
|
||||
CEmbeddedFile* m_pUnix;
|
||||
|
||||
CEmbeddedFiles() : m_pF(NULL), m_pUF(NULL), m_pDOS(NULL), m_pMac(NULL), m_pUnix(NULL) {}
|
||||
~CEmbeddedFiles()
|
||||
{
|
||||
RELEASEOBJECT(m_pF);
|
||||
RELEASEOBJECT(m_pUF);
|
||||
RELEASEOBJECT(m_pDOS);
|
||||
RELEASEOBJECT(m_pMac);
|
||||
RELEASEOBJECT(m_pUnix);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
std::string m_sName; // Иконка
|
||||
std::string m_sFS; // Файловая система
|
||||
std::string m_sDesc; // Описание файла
|
||||
std::string m_sF; // Спецификация файла (обратная совместимость)
|
||||
std::string m_sUF; // Спецификация файла (кросс-платформенная и межъязыковая совместимость)
|
||||
std::string m_sDOS; // Спецификация файла DOS
|
||||
std::string m_sMac; // Спецификация файла Mac
|
||||
std::string m_sUnix; // Спецификация файла Unix
|
||||
std::pair<std::string, std::string> m_sID; // Идентификатор файла
|
||||
CEmbeddedFiles* m_pEF; // EF содержит F/UF/DOS/Mac/Unix со ссылками на встроенные файловые потоки по соответствующим спецификациях
|
||||
// TODO RF содержит F/UF/DOS/Mac/Unix с массивами связанных файлов по соответствующим спецификациях
|
||||
// TODO Cl коллекция для создания пользовательского интерфейса
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// PdfReader::CAnnots
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user