Home | History | Annotate | Download | only in fpdf_edit
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "../../../include/fpdfapi/fpdf_serial.h"
      8 #include "editint.h"
      9 #define PDF_OBJECTSTREAM_MAXLENGTH	(256 * 1024)
     10 #define PDF_XREFSTREAM_MAXSIZE		10000
     11 extern void FlateEncode(const FX_BYTE* src_buf, FX_DWORD src_data, FX_LPBYTE& dest_buf, FX_DWORD& dest_size);
     12 extern void FlateEncode(FX_LPCBYTE src_buf, FX_DWORD src_size, int predictor, int Colors, int BitsPerComponent, int Columns,
     13                         FX_LPBYTE& dest_buf, FX_DWORD& dest_size);
     14 extern FX_BOOL IsSignatureDict(const CPDF_Dictionary* pDict);
     15 FX_INT32 PDF_CreatorAppendObject(const CPDF_Object* pObj, CFX_FileBufferArchive *pFile, FX_FILESIZE& offset)
     16 {
     17     FX_INT32 len = 0;
     18     if (pObj == NULL) {
     19         if (pFile->AppendString(FX_BSTRC(" null")) < 0) {
     20             return -1;
     21         }
     22         offset += 5;
     23         return 1;
     24     }
     25     switch (pObj->GetType()) {
     26         case PDFOBJ_NULL:
     27             if (pFile->AppendString(FX_BSTRC(" null")) < 0) {
     28                 return -1;
     29             }
     30             offset += 5;
     31             break;
     32         case PDFOBJ_BOOLEAN:
     33         case PDFOBJ_NUMBER:
     34             if (pFile->AppendString(FX_BSTRC(" ")) < 0) {
     35                 return -1;
     36             }
     37             if ((len = pFile->AppendString(pObj->GetString())) < 0) {
     38                 return -1;
     39             }
     40             offset += len + 1;
     41             break;
     42         case PDFOBJ_STRING: {
     43                 CFX_ByteString str = pObj->GetString();
     44                 FX_BOOL bHex = ((CPDF_String*)pObj)->IsHex();
     45                 if ((len = pFile->AppendString(PDF_EncodeString(str, bHex))) < 0) {
     46                     return -1;
     47                 }
     48                 offset += len;
     49                 break;
     50             }
     51         case PDFOBJ_NAME: {
     52                 if (pFile->AppendString(FX_BSTRC("/")) < 0) {
     53                     return -1;
     54                 }
     55                 CFX_ByteString str = pObj->GetString();
     56                 if ((len = pFile->AppendString(PDF_NameEncode(str))) < 0) {
     57                     return -1;
     58                 }
     59                 offset += len + 1;
     60                 break;
     61             }
     62         case PDFOBJ_REFERENCE: {
     63                 if (pFile->AppendString(FX_BSTRC(" ")) < 0) {
     64                     return -1;
     65                 }
     66                 CPDF_Reference* p = (CPDF_Reference*)pObj;
     67                 if ((len = pFile->AppendDWord(p->GetRefObjNum())) < 0) {
     68                     return -1;
     69                 }
     70                 if (pFile->AppendString(FX_BSTRC(" 0 R ")) < 0) {
     71                     return -1;
     72                 }
     73                 offset += len + 6;
     74                 break;
     75             }
     76         case PDFOBJ_ARRAY: {
     77                 if (pFile->AppendString(FX_BSTRC("[")) < 0) {
     78                     return -1;
     79                 }
     80                 offset += 1;
     81                 CPDF_Array* p = (CPDF_Array*)pObj;
     82                 for (FX_DWORD i = 0; i < p->GetCount(); i ++) {
     83                     CPDF_Object* pElement = p->GetElement(i);
     84                     if (pElement->GetObjNum()) {
     85                         if (pFile->AppendString(FX_BSTRC(" ")) < 0) {
     86                             return -1;
     87                         }
     88                         if ((len = pFile->AppendDWord(pElement->GetObjNum())) < 0) {
     89                             return -1;
     90                         }
     91                         if (pFile->AppendString(FX_BSTRC(" 0 R")) < 0) {
     92                             return -1;
     93                         }
     94                         offset += len + 5;
     95                     } else {
     96                         if (PDF_CreatorAppendObject(pElement, pFile, offset) < 0) {
     97                             return -1;
     98                         }
     99                     }
    100                 }
    101                 if (pFile->AppendString(FX_BSTRC("]")) < 0) {
    102                     return -1;
    103                 }
    104                 offset += 1;
    105                 break;
    106             }
    107         case PDFOBJ_DICTIONARY: {
    108                 if (pFile->AppendString(FX_BSTRC("<<")) < 0) {
    109                     return -1;
    110                 }
    111                 offset += 2;
    112                 CPDF_Dictionary* p = (CPDF_Dictionary*)pObj;
    113                 FX_POSITION pos = p->GetStartPos();
    114                 while (pos) {
    115                     CFX_ByteString key;
    116                     CPDF_Object* pValue = p->GetNextElement(pos, key);
    117                     if (pFile->AppendString(FX_BSTRC("/")) < 0) {
    118                         return -1;
    119                     }
    120                     if ((len = pFile->AppendString(PDF_NameEncode(key))) < 0) {
    121                         return -1;
    122                     }
    123                     offset += len + 1;
    124                     if (pValue->GetObjNum()) {
    125                         if (pFile->AppendString(FX_BSTRC(" ")) < 0) {
    126                             return -1;
    127                         }
    128                         if ((len = pFile->AppendDWord(pValue->GetObjNum())) < 0) {
    129                             return -1;
    130                         }
    131                         if (pFile->AppendString(FX_BSTRC(" 0 R")) < 0) {
    132                             return -1;
    133                         }
    134                         offset += len + 5;
    135                     } else {
    136                         if (PDF_CreatorAppendObject(pValue, pFile, offset) < 0) {
    137                             return -1;
    138                         }
    139                     }
    140                 }
    141                 if (pFile->AppendString(FX_BSTRC(">>")) < 0) {
    142                     return -1;
    143                 }
    144                 offset += 2;
    145                 break;
    146             }
    147         case PDFOBJ_STREAM: {
    148                 CPDF_Stream* p = (CPDF_Stream*)pObj;
    149                 if (PDF_CreatorAppendObject(p->GetDict(), pFile, offset) < 0) {
    150                     return -1;
    151                 }
    152                 if (pFile->AppendString(FX_BSTRC("stream\r\n")) < 0) {
    153                     return -1;
    154                 }
    155                 offset += 8;
    156                 CPDF_StreamAcc acc;
    157                 acc.LoadAllData(p, TRUE);
    158                 if (pFile->AppendBlock(acc.GetData(), acc.GetSize()) < 0) {
    159                     return -1;
    160                 }
    161                 offset += acc.GetSize();
    162                 if ((len = pFile->AppendString(FX_BSTRC("\r\nendstream"))) < 0) {
    163                     return -1;
    164                 }
    165                 offset += len;
    166                 break;
    167             }
    168         default:
    169             ASSERT(FALSE);
    170             break;
    171     }
    172     return 1;
    173 }
    174 FX_INT32 PDF_CreatorWriteTrailer(CPDF_Document* pDocument, CFX_FileBufferArchive* pFile, CPDF_Array* pIDArray, FX_BOOL bCompress)
    175 {
    176     FX_FILESIZE offset = 0;
    177     FX_INT32 len = 0;
    178     FXSYS_assert(pDocument && pFile);
    179     CPDF_Parser *pParser = (CPDF_Parser*)pDocument->GetParser();
    180     if (pParser) {
    181         CPDF_Dictionary* p = pParser->GetTrailer();
    182         FX_POSITION pos = p->GetStartPos();
    183         while (pos) {
    184             CFX_ByteString key;
    185             CPDF_Object* pValue = p->GetNextElement(pos, key);
    186             if (key == FX_BSTRC("Encrypt") || key == FX_BSTRC("Size") || key == FX_BSTRC("Filter") ||
    187                     key == FX_BSTRC("Index") || key == FX_BSTRC("Length") || key == FX_BSTRC("Prev") ||
    188                     key == FX_BSTRC("W") || key == FX_BSTRC("XRefStm") || key == FX_BSTRC("Type") || key == FX_BSTRC("ID")) {
    189                 continue;
    190             }
    191             if (bCompress && key == FX_BSTRC("DecodeParms")) {
    192                 continue;
    193             }
    194             if (pFile->AppendString((FX_BSTRC("/"))) < 0) {
    195                 return -1;
    196             }
    197             if ((len = pFile->AppendString(PDF_NameEncode(key))) < 0) {
    198                 return -1;
    199             }
    200             offset += len + 1;
    201             if (pValue->GetObjNum()) {
    202                 if (pFile->AppendString(FX_BSTRC(" ")) < 0) {
    203                     return -1;
    204                 }
    205                 if ((len = pFile->AppendDWord(pValue->GetObjNum())) < 0) {
    206                     return -1;
    207                 }
    208                 if (pFile->AppendString(FX_BSTRC(" 0 R ")) < 0) {
    209                     return -1;
    210                 }
    211                 offset += len + 6;
    212             } else {
    213                 if (PDF_CreatorAppendObject(pValue, pFile, offset) < 0) {
    214                     return -1;
    215                 }
    216             }
    217         }
    218         if (pIDArray) {
    219             if (pFile->AppendString((FX_BSTRC("/ID"))) < 0) {
    220                 return -1;
    221             }
    222             offset += 3;
    223             if (PDF_CreatorAppendObject(pIDArray, pFile, offset) < 0) {
    224                 return -1;
    225             }
    226         }
    227         return offset;
    228     }
    229     if (pFile->AppendString(FX_BSTRC("\r\n/Root ")) < 0) {
    230         return -1;
    231     }
    232     if ((len = pFile->AppendDWord(pDocument->GetRoot()->GetObjNum())) < 0) {
    233         return -1;
    234     }
    235     if (pFile->AppendString(FX_BSTRC(" 0 R\r\n")) < 0) {
    236         return -1;
    237     }
    238     offset += len + 14;
    239     if (pDocument->GetInfo()) {
    240         if (pFile->AppendString(FX_BSTRC("/Info ")) < 0) {
    241             return -1;
    242         }
    243         if ((len = pFile->AppendDWord(pDocument->GetInfo()->GetObjNum())) < 0) {
    244             return -1;
    245         }
    246         if (pFile->AppendString(FX_BSTRC(" 0 R\r\n")) < 0) {
    247             return -1;
    248         }
    249         offset += len + 12;
    250     }
    251     if (pIDArray) {
    252         if (pFile->AppendString((FX_BSTRC("/ID"))) < 0) {
    253             return -1;
    254         }
    255         offset += 3;
    256         if (PDF_CreatorAppendObject(pIDArray, pFile, offset) < 0) {
    257             return -1;
    258         }
    259     }
    260     return offset;
    261 }
    262 FX_INT32 PDF_CreatorWriteEncrypt(const CPDF_Dictionary* pEncryptDict, FX_DWORD dwObjNum, CFX_FileBufferArchive *pFile)
    263 {
    264     if (!pEncryptDict) {
    265         return 0;
    266     }
    267     FXSYS_assert(pFile);
    268     FX_FILESIZE offset = 0;
    269     FX_INT32 len = 0;
    270     if (pFile->AppendString(FX_BSTRC("/Encrypt")) < 0) {
    271         return -1;
    272     }
    273     offset += 8;
    274     if (pFile->AppendString(FX_BSTRC(" ")) < 0) {
    275         return -1;
    276     }
    277     if ((len = pFile->AppendDWord(dwObjNum)) < 0) {
    278         return -1;
    279     }
    280     if (pFile->AppendString(FX_BSTRC(" 0 R ")) < 0) {
    281         return -1;
    282     }
    283     offset += len + 6;
    284     return offset;
    285 }
    286 FX_BOOL PDF_GenerateFileID(FX_DWORD dwSeed1, FX_DWORD dwSeed2, FX_LPDWORD pBuffer)
    287 {
    288     if (!pBuffer) {
    289         return FALSE;
    290     }
    291     FX_LPVOID pContext = FX_Random_MT_Start(dwSeed1);
    292     FX_INT32 i = 0;
    293     for (i = 0; i < 2; i++) {
    294         *pBuffer++ = FX_Random_MT_Generate(pContext);
    295     }
    296     FX_Random_MT_Close(pContext);
    297     pContext = FX_Random_MT_Start(dwSeed2);
    298     for (i = 0; i < 2; i++) {
    299         *pBuffer++ = FX_Random_MT_Generate(pContext);
    300     }
    301     FX_Random_MT_Close(pContext);
    302     return TRUE;
    303 }
    304 class CPDF_FlateEncoder
    305 {
    306 public:
    307     CPDF_FlateEncoder();
    308     ~CPDF_FlateEncoder();
    309     FX_BOOL		Initialize(CPDF_Stream* pStream, FX_BOOL bFlateEncode);
    310     FX_BOOL		Initialize(FX_LPCBYTE pBuffer, FX_DWORD size, FX_BOOL bFlateEncode, FX_BOOL bXRefStream = FALSE);
    311     void		CloneDict();
    312     FX_LPBYTE			m_pData;
    313     FX_DWORD			m_dwSize;
    314     CPDF_Dictionary*	m_pDict;
    315     FX_BOOL				m_bCloned;
    316     FX_BOOL				m_bNewData;
    317     CPDF_StreamAcc		m_Acc;
    318 };
    319 CPDF_FlateEncoder::CPDF_FlateEncoder()
    320 {
    321     m_pData = NULL;
    322     m_dwSize = 0;
    323     m_pDict = NULL;
    324     m_bCloned = FALSE;
    325     m_bNewData = FALSE;
    326 }
    327 void CPDF_FlateEncoder::CloneDict()
    328 {
    329     if (!m_bCloned) {
    330         m_pDict = (CPDF_Dictionary*)m_pDict->Clone();
    331         m_bCloned = TRUE;
    332     }
    333 }
    334 FX_BOOL CPDF_FlateEncoder::Initialize(CPDF_Stream* pStream, FX_BOOL bFlateEncode)
    335 {
    336     m_Acc.LoadAllData(pStream, TRUE);
    337     if (pStream->GetDict()->KeyExist("Filter") || !bFlateEncode) {
    338         if (pStream->GetDict()->KeyExist("Filter") && !bFlateEncode) {
    339             CPDF_StreamAcc destAcc;
    340             destAcc.LoadAllData(pStream);
    341             m_dwSize = destAcc.GetSize();
    342             m_pData = (FX_LPBYTE)destAcc.DetachData();
    343             m_pDict = (CPDF_Dictionary*)pStream->GetDict()->Clone();
    344             m_pDict->RemoveAt(FX_BSTRC("Filter"));
    345             m_bNewData = TRUE;
    346             m_bCloned = TRUE;
    347         } else {
    348             m_pData = (FX_LPBYTE)m_Acc.GetData();
    349             m_dwSize = m_Acc.GetSize();
    350             m_pDict = pStream->GetDict();
    351         }
    352         return TRUE;
    353     }
    354     m_pData = NULL;
    355     m_dwSize = 0;
    356     m_bNewData = TRUE;
    357     m_bCloned = TRUE;
    358     ::FlateEncode(m_Acc.GetData(), m_Acc.GetSize(), m_pData, m_dwSize);
    359     m_pDict = (CPDF_Dictionary*)pStream->GetDict()->Clone();
    360     m_pDict->SetAtInteger("Length", m_dwSize);
    361     m_pDict->SetAtName("Filter", "FlateDecode");
    362     m_pDict->RemoveAt("DecodeParms");
    363     return TRUE;
    364 }
    365 FX_BOOL CPDF_FlateEncoder::Initialize(FX_LPCBYTE pBuffer, FX_DWORD size, FX_BOOL bFlateEncode, FX_BOOL bXRefStream)
    366 {
    367     if (!bFlateEncode) {
    368         m_pData = (FX_LPBYTE)pBuffer;
    369         m_dwSize = size;
    370         return TRUE;
    371     }
    372     m_bNewData = TRUE;
    373     if (bXRefStream) {
    374         ::FlateEncode(pBuffer, size, 12, 1, 8, 7, m_pData, m_dwSize);
    375     } else {
    376         ::FlateEncode(pBuffer, size, m_pData, m_dwSize);
    377     }
    378     return TRUE;
    379 }
    380 CPDF_FlateEncoder::~CPDF_FlateEncoder()
    381 {
    382     if (m_bCloned && m_pDict) {
    383         m_pDict->Release();
    384     }
    385     if (m_bNewData && m_pData) {
    386         FX_Free(m_pData);
    387     }
    388 }
    389 class CPDF_Encryptor
    390 {
    391 public:
    392     CPDF_Encryptor();
    393     ~CPDF_Encryptor();
    394     FX_BOOL		Initialize(CPDF_CryptoHandler* pHandler, int objnum, FX_LPBYTE src_data, FX_DWORD src_size);
    395     FX_LPBYTE			m_pData;
    396     FX_DWORD			m_dwSize;
    397     FX_BOOL				m_bNewBuf;
    398 };
    399 CPDF_Encryptor::CPDF_Encryptor()
    400 {
    401     m_pData = NULL;
    402     m_dwSize = 0;
    403     m_bNewBuf = FALSE;
    404 }
    405 FX_BOOL CPDF_Encryptor::Initialize(CPDF_CryptoHandler* pHandler, int objnum, FX_LPBYTE src_data, FX_DWORD src_size)
    406 {
    407     if (src_size == 0) {
    408         return TRUE;
    409     }
    410     if (pHandler == NULL) {
    411         m_pData = (FX_LPBYTE)src_data;
    412         m_dwSize = src_size;
    413         m_bNewBuf = FALSE;
    414         return TRUE;
    415     }
    416     m_dwSize = pHandler->EncryptGetSize(objnum, 0, src_data, src_size);
    417     m_pData = FX_Alloc(FX_BYTE, m_dwSize);
    418     if(!m_pData) {
    419         return FALSE;
    420     }
    421     pHandler->EncryptContent(objnum, 0, src_data, src_size, m_pData, m_dwSize);
    422     m_bNewBuf = TRUE;
    423     return TRUE;
    424 }
    425 CPDF_Encryptor::~CPDF_Encryptor()
    426 {
    427     if (m_bNewBuf) {
    428         FX_Free(m_pData);
    429     }
    430 }
    431 CPDF_ObjectStream::CPDF_ObjectStream()
    432     : m_dwObjNum(0)
    433     , m_index(0)
    434 {
    435 }
    436 FX_BOOL CPDF_ObjectStream::Start()
    437 {
    438     m_ObjNumArray.RemoveAll();
    439     m_OffsetArray.RemoveAll();
    440     m_Buffer.Clear();
    441     m_dwObjNum = 0;
    442     m_index = 0;
    443     return TRUE;
    444 }
    445 FX_INT32 CPDF_ObjectStream::CompressIndirectObject(FX_DWORD dwObjNum, const CPDF_Object *pObj)
    446 {
    447     m_ObjNumArray.Add(dwObjNum);
    448     m_OffsetArray.Add(m_Buffer.GetLength());
    449     m_Buffer << pObj;
    450     return 1;
    451 }
    452 FX_INT32 CPDF_ObjectStream::CompressIndirectObject(FX_DWORD dwObjNum, FX_LPCBYTE pBuffer, FX_DWORD dwSize)
    453 {
    454     m_ObjNumArray.Add(dwObjNum);
    455     m_OffsetArray.Add(m_Buffer.GetLength());
    456     m_Buffer.AppendBlock(pBuffer, dwSize);
    457     return 1;
    458 }
    459 FX_FILESIZE CPDF_ObjectStream::End(CPDF_Creator* pCreator)
    460 {
    461     FXSYS_assert(pCreator);
    462     if (m_ObjNumArray.GetSize() == 0) {
    463         return 0;
    464     }
    465     CFX_FileBufferArchive *pFile = &pCreator->m_File;
    466     CPDF_CryptoHandler *pHandler = pCreator->m_pCryptoHandler;
    467     FX_FILESIZE ObjOffset = pCreator->m_Offset;
    468     if (!m_dwObjNum) {
    469         m_dwObjNum = ++pCreator->m_dwLastObjNum;
    470     }
    471     CFX_ByteTextBuf tempBuffer;
    472     FX_INT32 iCount = m_ObjNumArray.GetSize();
    473     for (FX_INT32 i = 0; i < iCount; i++) {
    474         tempBuffer << m_ObjNumArray.ElementAt(i) << FX_BSTRC(" ") << m_OffsetArray.ElementAt(i) << FX_BSTRC(" ");
    475     }
    476     FX_FILESIZE &offset = pCreator->m_Offset;
    477     FX_INT32 len = pFile->AppendDWord(m_dwObjNum);
    478     if (len < 0) {
    479         return -1;
    480     }
    481     offset += len;
    482     if ((len = pFile->AppendString(FX_BSTRC(" 0 obj\r\n<</Type /ObjStm /N "))) < 0) {
    483         return -1;
    484     }
    485     offset += len;
    486     if ((len = pFile->AppendDWord((FX_DWORD)iCount)) < 0) {
    487         return -1;
    488     }
    489     offset += len;
    490     if (pFile->AppendString(FX_BSTRC("/First ")) < 0) {
    491         return -1;
    492     }
    493     if ((len = pFile->AppendDWord((FX_DWORD)tempBuffer.GetLength())) < 0) {
    494         return -1;
    495     }
    496     if (pFile->AppendString(FX_BSTRC("/Length ")) < 0) {
    497         return -1;
    498     }
    499     offset += len + 15;
    500     if (!pCreator->m_bCompress && !pHandler) {
    501         if ((len = pFile->AppendDWord((FX_DWORD)(tempBuffer.GetLength() + m_Buffer.GetLength()))) < 0) {
    502             return -1;
    503         }
    504         offset += len;
    505         if ((len = pFile->AppendString(FX_BSTRC(">>stream\r\n"))) < 0) {
    506             return -1;
    507         }
    508         if (pFile->AppendBlock(tempBuffer.GetBuffer(), tempBuffer.GetLength()) < 0) {
    509             return -1;
    510         }
    511         if (pFile->AppendBlock(m_Buffer.GetBuffer(), m_Buffer.GetLength()) < 0) {
    512             return -1;
    513         }
    514         offset += len + tempBuffer.GetLength() + m_Buffer.GetLength();
    515     } else {
    516         tempBuffer << m_Buffer;
    517         CPDF_FlateEncoder encoder;
    518         encoder.Initialize(tempBuffer.GetBuffer(), tempBuffer.GetLength(), pCreator->m_bCompress);
    519         CPDF_Encryptor encryptor;
    520         encryptor.Initialize(pHandler, m_dwObjNum, encoder.m_pData, encoder.m_dwSize);
    521         if ((len = pFile->AppendDWord(encryptor.m_dwSize)) < 0) {
    522             return -1;
    523         }
    524         offset += len;
    525         if (pCreator->m_bCompress) {
    526             if (pFile->AppendString(FX_BSTRC("/Filter /FlateDecode")) < 0) {
    527                 return -1;
    528             }
    529             offset += 20;
    530         }
    531         if ((len = pFile->AppendString(FX_BSTRC(">>stream\r\n"))) < 0) {
    532             return -1;
    533         }
    534         if (pFile->AppendBlock(encryptor.m_pData, encryptor.m_dwSize) < 0) {
    535             return -1;
    536         }
    537         offset += len + encryptor.m_dwSize;
    538     }
    539     if ((len = pFile->AppendString(FX_BSTRC("\r\nendstream\r\nendobj\r\n"))) < 0) {
    540         return -1;
    541     }
    542     offset += len;
    543     return ObjOffset;
    544 }
    545 CPDF_XRefStream::CPDF_XRefStream()
    546     : m_PrevOffset(0)
    547     , m_iSeg(0)
    548     , m_dwTempObjNum(0)
    549 {
    550 }
    551 FX_BOOL CPDF_XRefStream::Start()
    552 {
    553     m_IndexArray.RemoveAll();
    554     m_Buffer.Clear();
    555     m_iSeg = 0;
    556     return TRUE;
    557 }
    558 FX_INT32 CPDF_XRefStream::CompressIndirectObject(FX_DWORD dwObjNum, const CPDF_Object *pObj, CPDF_Creator *pCreator)
    559 {
    560     if (!pCreator) {
    561         return 0;
    562     }
    563     m_ObjStream.CompressIndirectObject(dwObjNum, pObj);
    564     if (m_ObjStream.m_ObjNumArray.GetSize() < pCreator->m_ObjectStreamSize &&
    565             m_ObjStream.m_Buffer.GetLength() < PDF_OBJECTSTREAM_MAXLENGTH) {
    566         return 1;
    567     }
    568     return EndObjectStream(pCreator);
    569 }
    570 FX_INT32 CPDF_XRefStream::CompressIndirectObject(FX_DWORD dwObjNum, FX_LPCBYTE pBuffer, FX_DWORD dwSize, CPDF_Creator *pCreator)
    571 {
    572     if (!pCreator) {
    573         return 0;
    574     }
    575     m_ObjStream.CompressIndirectObject(dwObjNum, pBuffer, dwSize);
    576     if (m_ObjStream.m_ObjNumArray.GetSize() < pCreator->m_ObjectStreamSize &&
    577             m_ObjStream.m_Buffer.GetLength() < PDF_OBJECTSTREAM_MAXLENGTH) {
    578         return 1;
    579     }
    580     return EndObjectStream(pCreator);
    581 }
    582 static void _AppendIndex0(CFX_ByteTextBuf& buffer, FX_BOOL bFirstObject =  TRUE)
    583 {
    584     buffer.AppendByte(0);
    585     buffer.AppendByte(0);
    586     buffer.AppendByte(0);
    587     buffer.AppendByte(0);
    588     buffer.AppendByte(0);
    589     if (bFirstObject) {
    590         buffer.AppendByte(0xFF);
    591         buffer.AppendByte(0xFF);
    592     } else {
    593         buffer.AppendByte(0);
    594         buffer.AppendByte(0);
    595     }
    596 }
    597 static void _AppendIndex1(CFX_ByteTextBuf& buffer, FX_FILESIZE offset)
    598 {
    599     buffer.AppendByte(1);
    600     buffer.AppendByte(FX_GETBYTEOFFSET24(offset));
    601     buffer.AppendByte(FX_GETBYTEOFFSET16(offset));
    602     buffer.AppendByte(FX_GETBYTEOFFSET8(offset));
    603     buffer.AppendByte(FX_GETBYTEOFFSET0(offset));
    604     buffer.AppendByte(0);
    605     buffer.AppendByte(0);
    606 }
    607 static void _AppendIndex2(CFX_ByteTextBuf& buffer, FX_DWORD objnum, FX_INT32 index)
    608 {
    609     buffer.AppendByte(2);
    610     buffer.AppendByte(FX_GETBYTEOFFSET24(objnum));
    611     buffer.AppendByte(FX_GETBYTEOFFSET16(objnum));
    612     buffer.AppendByte(FX_GETBYTEOFFSET8(objnum));
    613     buffer.AppendByte(FX_GETBYTEOFFSET0(objnum));
    614     buffer.AppendByte(FX_GETBYTEOFFSET8(index));
    615     buffer.AppendByte(FX_GETBYTEOFFSET0(index));
    616 }
    617 FX_INT32 CPDF_XRefStream::EndObjectStream(CPDF_Creator *pCreator, FX_BOOL bEOF)
    618 {
    619     FX_FILESIZE objOffset = 0;
    620     if (bEOF) {
    621         objOffset = m_ObjStream.End(pCreator);
    622         if (objOffset < 0) {
    623             return -1;
    624         }
    625     }
    626     FX_DWORD &dwObjStmNum = m_ObjStream.m_dwObjNum;
    627     if (!dwObjStmNum) {
    628         dwObjStmNum = ++pCreator->m_dwLastObjNum;
    629     }
    630     FX_INT32 iSize = m_ObjStream.m_ObjNumArray.GetSize();
    631     FX_INT32 iSeg = m_IndexArray.GetSize() / 2;
    632     if (!(pCreator->m_dwFlags & FPDFCREATE_INCREMENTAL)) {
    633         if (m_dwTempObjNum == 0) {
    634             _AppendIndex0(m_Buffer);
    635             m_dwTempObjNum++;
    636         }
    637         FX_DWORD end_num = m_IndexArray.GetAt((iSeg - 1) * 2) + m_IndexArray.GetAt((iSeg - 1) * 2 + 1);
    638         int index = 0;
    639         for (; m_dwTempObjNum < end_num; m_dwTempObjNum++) {
    640             FX_FILESIZE* offset = pCreator->m_ObjectOffset.GetPtrAt(m_dwTempObjNum);
    641             if (offset) {
    642                 if (index >= iSize || m_dwTempObjNum != m_ObjStream.m_ObjNumArray[index]) {
    643                     _AppendIndex1(m_Buffer, *offset);
    644                 } else {
    645                     _AppendIndex2(m_Buffer, dwObjStmNum, index++);
    646                 }
    647             } else {
    648                 _AppendIndex0(m_Buffer, FALSE);
    649             }
    650         }
    651         if (iSize > 0 && bEOF) {
    652             pCreator->m_ObjectOffset.Add(dwObjStmNum, 1);
    653             pCreator->m_ObjectSize.Add(dwObjStmNum, 1);
    654             pCreator->m_ObjectOffset[dwObjStmNum] = objOffset;
    655         }
    656         m_iSeg = iSeg;
    657         if (bEOF) {
    658             m_ObjStream.Start();
    659         }
    660         return 1;
    661     }
    662     FX_INT32 &j = m_ObjStream.m_index;
    663     for (int i = m_iSeg; i < iSeg; i++) {
    664         FX_DWORD start = m_IndexArray.ElementAt(i * 2);
    665         FX_DWORD end = m_IndexArray.ElementAt(i * 2 + 1) + start;
    666         for (FX_DWORD m = start; m < end; m++) {
    667             if (j >= iSize || m != m_ObjStream.m_ObjNumArray.ElementAt(j)) {
    668                 _AppendIndex1(m_Buffer, pCreator->m_ObjectOffset[m]);
    669             } else {
    670                 _AppendIndex2(m_Buffer, dwObjStmNum, j++);
    671             }
    672         }
    673     }
    674     if (iSize > 0 && bEOF) {
    675         _AppendIndex1(m_Buffer, objOffset);
    676         m_IndexArray.Add(dwObjStmNum);
    677         m_IndexArray.Add(1);
    678         iSeg += 1;
    679     }
    680     m_iSeg = iSeg;
    681     if (bEOF) {
    682         m_ObjStream.Start();
    683     }
    684     return 1;
    685 }
    686 FX_BOOL CPDF_XRefStream::GenerateXRefStream(CPDF_Creator* pCreator, FX_BOOL bEOF)
    687 {
    688     FX_FILESIZE offset_tmp = pCreator->m_Offset;
    689     FX_DWORD objnum = ++pCreator->m_dwLastObjNum;
    690     CFX_FileBufferArchive *pFile = &pCreator->m_File;
    691     FX_BOOL bIncremental = (pCreator->m_dwFlags & FPDFCREATE_INCREMENTAL) != 0;
    692     if (bIncremental) {
    693         AddObjectNumberToIndexArray(objnum);
    694     } else {
    695         for (; m_dwTempObjNum < pCreator->m_dwLastObjNum; m_dwTempObjNum++) {
    696             FX_FILESIZE* offset = pCreator->m_ObjectOffset.GetPtrAt(m_dwTempObjNum);
    697             if (offset) {
    698                 _AppendIndex1(m_Buffer, *offset);
    699             } else {
    700                 _AppendIndex0(m_Buffer, FALSE);
    701             }
    702         }
    703     }
    704     _AppendIndex1(m_Buffer, offset_tmp);
    705     FX_FILESIZE &offset = pCreator->m_Offset;
    706     FX_INT32 len = pFile->AppendDWord(objnum);
    707     if (len < 0) {
    708         return FALSE;
    709     }
    710     offset += len;
    711     if ((len = pFile->AppendString(FX_BSTRC(" 0 obj\r\n<</Type /XRef/W[1 4 2]/Index["))) < 0) {
    712         return FALSE;
    713     }
    714     offset += len;
    715     if (!bIncremental) {
    716         if ((len = pFile->AppendDWord(0)) < 0) {
    717             return FALSE;
    718         }
    719         if ((len = pFile->AppendString(FX_BSTRC(" "))) < 0) {
    720             return FALSE;
    721         }
    722         offset += len + 1;
    723         if ((len = pFile->AppendDWord(objnum + 1)) < 0) {
    724             return FALSE;
    725         }
    726         offset += len;
    727     } else {
    728         FX_INT32 iSeg = m_IndexArray.GetSize() / 2;
    729         for (FX_INT32 i = 0; i < iSeg; i++) {
    730             if ((len = pFile->AppendDWord(m_IndexArray.ElementAt(i * 2))) < 0) {
    731                 return FALSE;
    732             }
    733             if (pFile->AppendString(FX_BSTRC(" ")) < 0) {
    734                 return FALSE;
    735             }
    736             offset += len + 1;
    737             if ((len = pFile->AppendDWord(m_IndexArray.ElementAt(i * 2 + 1))) < 0) {
    738                 return FALSE;
    739             }
    740             if (pFile->AppendString(FX_BSTRC(" ")) < 0) {
    741                 return FALSE;
    742             }
    743             offset += len + 1;
    744         }
    745     }
    746     if (pFile->AppendString(FX_BSTRC("]/Size ")) < 0) {
    747         return FALSE;
    748     }
    749     if ((len = pFile->AppendDWord(objnum + 1)) < 0) {
    750         return FALSE;
    751     }
    752     offset += len + 7;
    753     if (m_PrevOffset > 0) {
    754         if (pFile->AppendString(FX_BSTRC("/Prev ")) < 0) {
    755             return -1;
    756         }
    757         FX_CHAR offset_buf[20];
    758         FXSYS_memset32(offset_buf, 0, sizeof(offset_buf));
    759         FXSYS_i64toa(m_PrevOffset, offset_buf, 10);
    760         FX_INT32 len = (FX_INT32)FXSYS_strlen(offset_buf);
    761         if (pFile->AppendBlock(offset_buf, len) < 0) {
    762             return -1;
    763         }
    764         offset += len + 6;
    765     }
    766     FX_BOOL bPredictor = TRUE;
    767     CPDF_FlateEncoder encoder;
    768     encoder.Initialize(m_Buffer.GetBuffer(), m_Buffer.GetLength(), pCreator->m_bCompress, bPredictor);
    769     if (pCreator->m_bCompress) {
    770         if (pFile->AppendString(FX_BSTRC("/Filter /FlateDecode")) < 0) {
    771             return FALSE;
    772         }
    773         offset += 20;
    774         if (bPredictor) {
    775             if ((len = pFile->AppendString(FX_BSTRC("/DecodeParms<</Columns 7/Predictor 12>>"))) < 0) {
    776                 return FALSE;
    777             }
    778             offset += len;
    779         }
    780     }
    781     if (pFile->AppendString(FX_BSTRC("/Length ")) < 0) {
    782         return FALSE;
    783     }
    784     if ((len = pFile->AppendDWord(encoder.m_dwSize)) < 0) {
    785         return FALSE;
    786     }
    787     offset += len + 8;
    788     if (bEOF) {
    789         if ((len = PDF_CreatorWriteTrailer(pCreator->m_pDocument, pFile, pCreator->m_pIDArray, pCreator->m_bCompress)) < 0) {
    790             return -1;
    791         }
    792         offset += len;
    793         if (pCreator->m_pEncryptDict) {
    794             FX_DWORD dwEncryptObjNum = pCreator->m_pEncryptDict->GetObjNum();
    795             if (dwEncryptObjNum == 0) {
    796                 dwEncryptObjNum = pCreator->m_dwEnryptObjNum;
    797             }
    798             if ((len = PDF_CreatorWriteEncrypt(pCreator->m_pEncryptDict, dwEncryptObjNum, pFile)) < 0) {
    799                 return -1;
    800             }
    801             offset += len;
    802         }
    803     }
    804     if ((len = pFile->AppendString(FX_BSTRC(">>stream\r\n"))) < 0) {
    805         return FALSE;
    806     }
    807     offset += len;
    808     if (pFile->AppendBlock(encoder.m_pData, encoder.m_dwSize) < 0) {
    809         return FALSE;
    810     }
    811     if ((len = pFile->AppendString(FX_BSTRC("\r\nendstream\r\nendobj\r\n"))) < 0) {
    812         return FALSE;
    813     }
    814     offset += encoder.m_dwSize + len;
    815     m_PrevOffset = offset_tmp;
    816     return TRUE;
    817 }
    818 FX_BOOL CPDF_XRefStream::End(CPDF_Creator *pCreator, FX_BOOL bEOF )
    819 {
    820     if (EndObjectStream(pCreator, bEOF) < 0) {
    821         return FALSE;
    822     }
    823     return GenerateXRefStream(pCreator, bEOF);
    824 }
    825 FX_BOOL CPDF_XRefStream::EndXRefStream(CPDF_Creator* pCreator)
    826 {
    827     if (!(pCreator->m_dwFlags & FPDFCREATE_INCREMENTAL)) {
    828         _AppendIndex0(m_Buffer);
    829         for (FX_DWORD i = 1; i < pCreator->m_dwLastObjNum + 1; i++) {
    830             FX_FILESIZE* offset = pCreator->m_ObjectOffset.GetPtrAt(i);
    831             if (offset) {
    832                 _AppendIndex1(m_Buffer, *offset);
    833             } else {
    834                 _AppendIndex0(m_Buffer, FALSE);
    835             }
    836         }
    837     } else {
    838         FX_INT32 iSeg = m_IndexArray.GetSize() / 2;
    839         for (int i = 0; i < iSeg; i++) {
    840             FX_DWORD start = m_IndexArray.ElementAt(i * 2);
    841             FX_DWORD end = m_IndexArray.ElementAt(i * 2 + 1) + start;
    842             for (FX_DWORD j = start; j < end; j++) {
    843                 _AppendIndex1(m_Buffer, pCreator->m_ObjectOffset[j]);
    844             }
    845         }
    846     }
    847     return GenerateXRefStream(pCreator, FALSE);
    848 }
    849 FX_BOOL CPDF_XRefStream::AddObjectNumberToIndexArray(FX_DWORD objnum)
    850 {
    851     FX_INT32 iSize = m_IndexArray.GetSize();
    852     if (iSize == 0) {
    853         m_IndexArray.Add(objnum);
    854         m_IndexArray.Add(1);
    855     } else {
    856         FXSYS_assert(iSize > 1);
    857         FX_DWORD startobjnum = m_IndexArray.ElementAt(iSize - 2);
    858         FX_INT32 iCount = m_IndexArray.ElementAt(iSize - 1);
    859         if (objnum == startobjnum + iCount) {
    860             m_IndexArray[iSize - 1] = iCount + 1;
    861         } else {
    862             m_IndexArray.Add(objnum);
    863             m_IndexArray.Add(1);
    864         }
    865     }
    866     return TRUE;
    867 }
    868 CPDF_Creator::CPDF_Creator(CPDF_Document* pDoc)
    869 {
    870     m_pDocument = pDoc;
    871     m_pParser = (CPDF_Parser*)pDoc->m_pParser;
    872     m_bCompress = TRUE;
    873     if (m_pParser) {
    874         m_pEncryptDict = m_pParser->GetEncryptDict();
    875         m_pCryptoHandler = m_pParser->GetCryptoHandler();
    876     } else {
    877         m_pEncryptDict = NULL;
    878         m_pCryptoHandler = NULL;
    879     }
    880     m_bSecurityChanged = FALSE;
    881     m_bStandardSecurity = FALSE;
    882     m_pMetadata = NULL;
    883     m_bEncryptCloned = FALSE;
    884     m_bEncryptMetadata = FALSE;
    885     m_Offset = 0;
    886     m_iStage = -1;
    887     m_dwFlags = 0;
    888     m_Pos = NULL;
    889     m_XrefStart = 0;
    890     m_pXRefStream = NULL;
    891     m_ObjectStreamSize = 200;
    892     m_dwLastObjNum = m_pDocument->GetLastObjNum();
    893     m_pIDArray = NULL;
    894     m_FileVersion = 0;
    895     m_dwEnryptObjNum = 0;
    896     m_bNewCrypto = FALSE;
    897 }
    898 CPDF_Creator::~CPDF_Creator()
    899 {
    900     ResetStandardSecurity();
    901     if (m_bEncryptCloned && m_pEncryptDict) {
    902         m_pEncryptDict->Release();
    903         m_pEncryptDict = NULL;
    904     }
    905     Clear();
    906 }
    907 static FX_BOOL _IsXRefNeedEnd(CPDF_XRefStream* pXRef, FX_DWORD flag)
    908 {
    909     if (!(flag & FPDFCREATE_INCREMENTAL)) {
    910         return FALSE;
    911     }
    912     FX_INT32 iSize = pXRef->m_IndexArray.GetSize() / 2;
    913     FX_INT32 iCount = 0;
    914     for (FX_INT32 i = 0; i < iSize; i++) {
    915         iCount += pXRef->m_IndexArray.ElementAt(i * 2 + 1);
    916     }
    917     return (iCount >= PDF_XREFSTREAM_MAXSIZE);
    918 }
    919 FX_INT32 CPDF_Creator::WriteIndirectObjectToStream(const CPDF_Object* pObj)
    920 {
    921     if (!m_pXRefStream) {
    922         return 1;
    923     }
    924     FX_DWORD objnum = pObj->GetObjNum();
    925     if (m_pParser && m_pParser->m_ObjVersion.GetSize() > (FX_INT32)objnum && m_pParser->m_ObjVersion[objnum] > 0) {
    926         return 1;
    927     }
    928     if (pObj->GetType() == PDFOBJ_NUMBER) {
    929         return 1;
    930     }
    931     CPDF_Dictionary *pDict = pObj->GetDict();
    932     if (pObj->GetType() == PDFOBJ_STREAM) {
    933         if (pDict && pDict->GetString(FX_BSTRC("Type")) == FX_BSTRC("XRef")) {
    934             return 0;
    935         }
    936         return 1;
    937     }
    938     if (pDict) {
    939         if (pDict == m_pDocument->m_pRootDict || pDict == m_pEncryptDict) {
    940             return 1;
    941         }
    942         if (IsSignatureDict(pDict)) {
    943             return 1;
    944         }
    945         if (pDict->GetString(FX_BSTRC("Type")) == FX_BSTRC("Page")) {
    946             return 1;
    947         }
    948     }
    949     m_pXRefStream->AddObjectNumberToIndexArray(objnum);
    950     if (m_pXRefStream->CompressIndirectObject(objnum, pObj, this) < 0) {
    951         return -1;
    952     }
    953     if (!_IsXRefNeedEnd(m_pXRefStream, m_dwFlags)) {
    954         return 0;
    955     }
    956     if (!m_pXRefStream->End(this)) {
    957         return -1;
    958     }
    959     if (!m_pXRefStream->Start()) {
    960         return -1;
    961     }
    962     return 0;
    963 }
    964 FX_INT32 CPDF_Creator::WriteIndirectObjectToStream(FX_DWORD objnum, FX_LPCBYTE pBuffer, FX_DWORD dwSize)
    965 {
    966     if (!m_pXRefStream) {
    967         return 1;
    968     }
    969     m_pXRefStream->AddObjectNumberToIndexArray(objnum);
    970     FX_INT32 iRet = m_pXRefStream->CompressIndirectObject(objnum, pBuffer, dwSize, this);
    971     if (iRet < 1) {
    972         return iRet;
    973     }
    974     if (!_IsXRefNeedEnd(m_pXRefStream, m_dwFlags)) {
    975         return 0;
    976     }
    977     if (!m_pXRefStream->End(this)) {
    978         return -1;
    979     }
    980     if (!m_pXRefStream->Start()) {
    981         return -1;
    982     }
    983     return 0;
    984 }
    985 FX_INT32 CPDF_Creator::AppendObjectNumberToXRef(FX_DWORD objnum)
    986 {
    987     if (!m_pXRefStream) {
    988         return 1;
    989     }
    990     m_pXRefStream->AddObjectNumberToIndexArray(objnum);
    991     if (!_IsXRefNeedEnd(m_pXRefStream, m_dwFlags)) {
    992         return 0;
    993     }
    994     if (!m_pXRefStream->End(this)) {
    995         return -1;
    996     }
    997     if (!m_pXRefStream->Start()) {
    998         return -1;
    999     }
   1000     return 0;
   1001 }
   1002 FX_INT32 CPDF_Creator::WriteStream(const CPDF_Object* pStream, FX_DWORD objnum, CPDF_CryptoHandler* pCrypto)
   1003 {
   1004     CPDF_FlateEncoder encoder;
   1005     encoder.Initialize((CPDF_Stream*)pStream, pStream == m_pMetadata ? FALSE : m_bCompress);
   1006     CPDF_Encryptor encryptor;
   1007     if(!encryptor.Initialize(pCrypto, objnum, encoder.m_pData, encoder.m_dwSize)) {
   1008         return -1;
   1009     }
   1010     if ((FX_DWORD)encoder.m_pDict->GetInteger(FX_BSTRC("Length")) != encryptor.m_dwSize) {
   1011         encoder.CloneDict();
   1012         encoder.m_pDict->SetAtInteger(FX_BSTRC("Length"), encryptor.m_dwSize);
   1013     }
   1014     if (WriteDirectObj(objnum, encoder.m_pDict) < 0) {
   1015         return -1;
   1016     }
   1017     int len = m_File.AppendString(FX_BSTRC("stream\r\n"));
   1018     if (len < 0) {
   1019         return -1;
   1020     }
   1021     m_Offset += len;
   1022     if (m_File.AppendBlock(encryptor.m_pData, encryptor.m_dwSize) < 0) {
   1023         return -1;
   1024     }
   1025     m_Offset += encryptor.m_dwSize;
   1026     if ((len = m_File.AppendString(FX_BSTRC("\r\nendstream"))) < 0) {
   1027         return -1;
   1028     }
   1029     m_Offset += len;
   1030     return 1;
   1031 }
   1032 FX_INT32 CPDF_Creator::WriteIndirectObj(FX_DWORD objnum, const CPDF_Object* pObj)
   1033 {
   1034     FX_INT32 len = m_File.AppendDWord(objnum);
   1035     if (len < 0) {
   1036         return -1;
   1037     }
   1038     m_Offset += len;
   1039     if ((len = m_File.AppendString(FX_BSTRC(" 0 obj\r\n"))) < 0) {
   1040         return -1;
   1041     }
   1042     m_Offset += len;
   1043     if (pObj->GetType() == PDFOBJ_STREAM) {
   1044         CPDF_CryptoHandler *pHandler = NULL;
   1045         pHandler = (pObj == m_pMetadata && !m_bEncryptMetadata) ? NULL : m_pCryptoHandler;
   1046         if (WriteStream(pObj, objnum, pHandler) < 0) {
   1047             return -1;
   1048         }
   1049     } else {
   1050         if (WriteDirectObj(objnum, pObj) < 0) {
   1051             return -1;
   1052         }
   1053     }
   1054     if ((len = m_File.AppendString(FX_BSTRC("\r\nendobj\r\n"))) < 0) {
   1055         return -1;
   1056     }
   1057     m_Offset += len;
   1058     if (AppendObjectNumberToXRef(objnum) < 0) {
   1059         return -1;
   1060     }
   1061     return 0;
   1062 }
   1063 FX_INT32 CPDF_Creator::WriteIndirectObj(const CPDF_Object* pObj)
   1064 {
   1065     FX_INT32 iRet = WriteIndirectObjectToStream(pObj);
   1066     if (iRet < 1) {
   1067         return iRet;
   1068     }
   1069     return WriteIndirectObj(pObj->GetObjNum(), pObj);
   1070 }
   1071 FX_INT32 CPDF_Creator::WriteDirectObj(FX_DWORD objnum, const CPDF_Object* pObj, FX_BOOL bEncrypt)
   1072 {
   1073     FX_INT32 len = 0;
   1074     if (pObj == NULL) {
   1075         if (m_File.AppendString(FX_BSTRC(" null")) < 0) {
   1076             return -1;
   1077         }
   1078         m_Offset += 5;
   1079         return 1;
   1080     }
   1081     switch (pObj->GetType()) {
   1082         case PDFOBJ_NULL:
   1083             if (m_File.AppendString(FX_BSTRC(" null")) < 0) {
   1084                 return -1;
   1085             }
   1086             m_Offset += 5;
   1087             break;
   1088         case PDFOBJ_BOOLEAN:
   1089         case PDFOBJ_NUMBER:
   1090             if (m_File.AppendString(FX_BSTRC(" ")) < 0) {
   1091                 return -1;
   1092             }
   1093             if ((len = m_File.AppendString(pObj->GetString())) < 0) {
   1094                 return -1;
   1095             }
   1096             m_Offset += len + 1;
   1097             break;
   1098         case PDFOBJ_STRING: {
   1099                 CFX_ByteString str = pObj->GetString();
   1100                 FX_BOOL bHex = ((CPDF_String*)pObj)->IsHex();
   1101                 if (m_pCryptoHandler == NULL || !bEncrypt) {
   1102                     CFX_ByteString content = PDF_EncodeString(str, bHex);
   1103                     if ((len = m_File.AppendString(content)) < 0) {
   1104                         return -1;
   1105                     }
   1106                     m_Offset += len;
   1107                     break;
   1108                 }
   1109                 CPDF_Encryptor encryptor;
   1110                 encryptor.Initialize(m_pCryptoHandler, objnum, (FX_LPBYTE)(FX_LPCSTR)str, str.GetLength());
   1111                 CFX_ByteString content = PDF_EncodeString(CFX_ByteString((FX_LPCSTR)encryptor.m_pData, encryptor.m_dwSize), bHex);
   1112                 if ((len = m_File.AppendString(content)) < 0) {
   1113                     return -1;
   1114                 }
   1115                 m_Offset += len;
   1116                 break;
   1117             }
   1118         case PDFOBJ_STREAM: {
   1119                 CPDF_FlateEncoder encoder;
   1120                 encoder.Initialize((CPDF_Stream*)pObj, m_bCompress);
   1121                 CPDF_Encryptor encryptor;
   1122                 CPDF_CryptoHandler* pHandler = m_pCryptoHandler;
   1123                 encryptor.Initialize(pHandler, objnum, encoder.m_pData, encoder.m_dwSize);
   1124                 if ((FX_DWORD)encoder.m_pDict->GetInteger(FX_BSTRC("Length")) != encryptor.m_dwSize) {
   1125                     encoder.CloneDict();
   1126                     encoder.m_pDict->SetAtInteger(FX_BSTRC("Length"), encryptor.m_dwSize);
   1127                 }
   1128                 if (WriteDirectObj(objnum, encoder.m_pDict) < 0) {
   1129                     return -1;
   1130                 }
   1131                 if ((len = m_File.AppendString(FX_BSTRC("stream\r\n"))) < 0) {
   1132                     return -1;
   1133                 }
   1134                 m_Offset += len;
   1135                 if (m_File.AppendBlock(encryptor.m_pData, encryptor.m_dwSize) < 0) {
   1136                     return -1;
   1137                 }
   1138                 m_Offset += encryptor.m_dwSize;
   1139                 if ((len = m_File.AppendString(FX_BSTRC("\r\nendstream"))) < 0) {
   1140                     return -1;
   1141                 }
   1142                 m_Offset += len;
   1143                 break;
   1144             }
   1145         case PDFOBJ_NAME: {
   1146                 if (m_File.AppendString(FX_BSTRC("/")) < 0) {
   1147                     return -1;
   1148                 }
   1149                 CFX_ByteString str = pObj->GetString();
   1150                 if ((len = m_File.AppendString(PDF_NameEncode(str))) < 0) {
   1151                     return -1;
   1152                 }
   1153                 m_Offset += len + 1;
   1154                 break;
   1155             }
   1156         case PDFOBJ_REFERENCE: {
   1157                 if (m_File.AppendString(FX_BSTRC(" ")) < 0) {
   1158                     return -1;
   1159                 }
   1160                 CPDF_Reference* p = (CPDF_Reference*)pObj;
   1161                 if ((len = m_File.AppendDWord(p->GetRefObjNum())) < 0) {
   1162                     return -1;
   1163                 }
   1164                 if (m_File.AppendString(FX_BSTRC(" 0 R")) < 0) {
   1165                     return -1;
   1166                 }
   1167                 m_Offset += len + 5;
   1168                 break;
   1169             }
   1170         case PDFOBJ_ARRAY: {
   1171                 if (m_File.AppendString(FX_BSTRC("[")) < 0) {
   1172                     return -1;
   1173                 }
   1174                 m_Offset += 1;
   1175                 CPDF_Array* p = (CPDF_Array*)pObj;
   1176                 for (FX_DWORD i = 0; i < p->GetCount(); i ++) {
   1177                     CPDF_Object* pElement = p->GetElement(i);
   1178                     if (pElement->GetObjNum()) {
   1179                         if (m_File.AppendString(FX_BSTRC(" ")) < 0) {
   1180                             return -1;
   1181                         }
   1182                         if ((len = m_File.AppendDWord(pElement->GetObjNum())) < 0) {
   1183                             return -1;
   1184                         }
   1185                         if (m_File.AppendString(FX_BSTRC(" 0 R")) < 0) {
   1186                             return -1;
   1187                         }
   1188                         m_Offset += len + 5;
   1189                     } else {
   1190                         if (WriteDirectObj(objnum, pElement) < 0) {
   1191                             return -1;
   1192                         }
   1193                     }
   1194                 }
   1195                 if (m_File.AppendString(FX_BSTRC("]")) < 0) {
   1196                     return -1;
   1197                 }
   1198                 m_Offset += 1;
   1199                 break;
   1200             }
   1201         case PDFOBJ_DICTIONARY: {
   1202                 if (m_pCryptoHandler == NULL || pObj == m_pEncryptDict) {
   1203                     return PDF_CreatorAppendObject(pObj, &m_File, m_Offset);
   1204                 }
   1205                 if (m_File.AppendString(FX_BSTRC("<<")) < 0) {
   1206                     return -1;
   1207                 }
   1208                 m_Offset += 2;
   1209                 CPDF_Dictionary* p = (CPDF_Dictionary*)pObj;
   1210                 FX_BOOL bSignDict = IsSignatureDict(p);
   1211                 FX_POSITION pos = p->GetStartPos();
   1212                 while (pos) {
   1213                     FX_BOOL bSignValue = FALSE;
   1214                     CFX_ByteString key;
   1215                     CPDF_Object* pValue = p->GetNextElement(pos, key);
   1216                     if (m_File.AppendString(FX_BSTRC("/")) < 0) {
   1217                         return -1;
   1218                     }
   1219                     if ((len = m_File.AppendString(PDF_NameEncode(key))) < 0) {
   1220                         return -1;
   1221                     }
   1222                     m_Offset += len + 1;
   1223                     if (bSignDict && key == FX_BSTRC("Contents")) {
   1224                         bSignValue = TRUE;
   1225                     }
   1226                     if (pValue->GetObjNum()) {
   1227                         if (m_File.AppendString(FX_BSTRC(" ")) < 0) {
   1228                             return -1;
   1229                         }
   1230                         if ((len = m_File.AppendDWord(pValue->GetObjNum())) < 0) {
   1231                             return -1;
   1232                         }
   1233                         if (m_File.AppendString(FX_BSTRC(" 0 R ")) < 0) {
   1234                             return -1;
   1235                         }
   1236                         m_Offset += len + 6;
   1237                     } else {
   1238                         if (WriteDirectObj(objnum, pValue, !bSignValue) < 0) {
   1239                             return -1;
   1240                         }
   1241                     }
   1242                 }
   1243                 if (m_File.AppendString(FX_BSTRC(">>")) < 0) {
   1244                     return -1;
   1245                 }
   1246                 m_Offset += 2;
   1247                 break;
   1248             }
   1249     }
   1250     return 1;
   1251 }
   1252 FX_INT32 CPDF_Creator::WriteOldIndirectObject(FX_DWORD objnum)
   1253 {
   1254     if(m_pParser->m_V5Type[objnum] == 0 || m_pParser->m_V5Type[objnum] == 255) {
   1255         return 0;
   1256     }
   1257     m_ObjectOffset[objnum] = m_Offset;
   1258     FX_LPVOID valuetemp = NULL;
   1259     FX_BOOL bExistInMap = m_pDocument->m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, valuetemp);
   1260     FX_BOOL bObjStm = (m_pParser->m_V5Type[objnum] == 2) && m_pEncryptDict && !m_pXRefStream;
   1261     if(m_pParser->m_bVersionUpdated || m_bSecurityChanged || bExistInMap || bObjStm) {
   1262         CPDF_Object* pObj = m_pDocument->GetIndirectObject(objnum);
   1263         if (pObj == NULL) {
   1264             m_ObjectOffset[objnum] = 0;
   1265             m_ObjectSize[objnum] = 0;
   1266             return 0;
   1267         }
   1268         if (WriteIndirectObj(pObj)) {
   1269             return -1;
   1270         }
   1271         if (!bExistInMap) {
   1272             m_pDocument->ReleaseIndirectObject(objnum);
   1273         }
   1274     } else {
   1275         FX_BYTE* pBuffer;
   1276         FX_DWORD size;
   1277         m_pParser->GetIndirectBinary(objnum, pBuffer, size);
   1278         if (pBuffer == NULL) {
   1279             return 0;
   1280         }
   1281         if (m_pParser->m_V5Type[objnum] == 2) {
   1282             if (m_pXRefStream) {
   1283                 if (WriteIndirectObjectToStream(objnum, pBuffer, size) < 0) {
   1284                     FX_Free(pBuffer);
   1285                     return -1;
   1286                 }
   1287             } else {
   1288                 FX_INT32 len = m_File.AppendDWord(objnum);
   1289                 if (len < 0) {
   1290                     return -1;
   1291                 }
   1292                 if (m_File.AppendString(FX_BSTRC(" 0 obj ")) < 0) {
   1293                     return -1;
   1294                 }
   1295                 m_Offset += len + 7;
   1296                 if (m_File.AppendBlock(pBuffer, size) < 0) {
   1297                     return -1;
   1298                 }
   1299                 m_Offset += size;
   1300                 if (m_File.AppendString(FX_BSTRC("\r\nendobj\r\n")) < 0) {
   1301                     return -1;
   1302                 }
   1303                 m_Offset += 10;
   1304             }
   1305         } else {
   1306             if (m_File.AppendBlock(pBuffer, size) < 0) {
   1307                 return -1;
   1308             }
   1309             m_Offset += size;
   1310             if(AppendObjectNumberToXRef(objnum) < 0) {
   1311                 return -1;
   1312             }
   1313         }
   1314         FX_Free(pBuffer);
   1315     }
   1316     return 1;
   1317 }
   1318 FX_INT32 CPDF_Creator::WriteOldObjs(IFX_Pause *pPause)
   1319 {
   1320     FX_DWORD nOldSize = m_pParser->m_CrossRef.GetSize();
   1321     FX_DWORD objnum = (FX_DWORD)(FX_UINTPTR)m_Pos;
   1322     for(; objnum < nOldSize; objnum ++) {
   1323         FX_INT32 iRet = WriteOldIndirectObject(objnum);
   1324         if (!iRet) {
   1325             continue;
   1326         }
   1327         if (iRet < 0) {
   1328             return iRet;
   1329         }
   1330         m_ObjectSize[objnum] = (FX_DWORD)(m_Offset - m_ObjectOffset[objnum]);
   1331         if (pPause && pPause->NeedToPauseNow()) {
   1332             m_Pos = (FX_LPVOID)(FX_UINTPTR)(objnum + 1);
   1333             return 1;
   1334         }
   1335     }
   1336     return 0;
   1337 }
   1338 FX_INT32 CPDF_Creator::WriteNewObjs(FX_BOOL bIncremental, IFX_Pause *pPause)
   1339 {
   1340     FX_INT32 iCount = m_NewObjNumArray.GetSize();
   1341     FX_INT32 index = (FX_INT32)(FX_UINTPTR)m_Pos;
   1342     while (index < iCount) {
   1343         FX_DWORD objnum = m_NewObjNumArray.ElementAt(index);
   1344         CPDF_Object *pObj = NULL;
   1345         m_pDocument->m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, (FX_LPVOID&)pObj);
   1346         if (NULL == pObj) {
   1347             ++index;
   1348             continue;
   1349         }
   1350         m_ObjectOffset[objnum] = m_Offset;
   1351         if (WriteIndirectObj(pObj)) {
   1352             return -1;
   1353         }
   1354         m_ObjectSize[objnum] = (FX_DWORD)(m_Offset - m_ObjectOffset[objnum]);
   1355         index++;
   1356         if (pPause && pPause->NeedToPauseNow()) {
   1357             m_Pos = (FX_POSITION)(FX_UINTPTR)index;
   1358             return 1;
   1359         }
   1360     }
   1361     return 0;
   1362 }
   1363 void CPDF_Creator::InitOldObjNumOffsets()
   1364 {
   1365     if (!m_pParser) {
   1366         return;
   1367     }
   1368     FX_DWORD j = 0;
   1369     FX_DWORD dwStart = 0;
   1370     FX_DWORD dwEnd = m_pParser->GetLastObjNum();
   1371     while (dwStart <= dwEnd) {
   1372         while (dwStart <= dwEnd && (m_pParser->m_V5Type[dwStart] == 0 || m_pParser->m_V5Type[dwStart] == 255)) {
   1373             dwStart++;
   1374         }
   1375         if (dwStart > dwEnd) {
   1376             break;
   1377         }
   1378         j = dwStart;
   1379         while (j <= dwEnd && m_pParser->m_V5Type[j] != 0 && m_pParser->m_V5Type[j] != 255) {
   1380             j++;
   1381         }
   1382         m_ObjectOffset.Add(dwStart, j - dwStart);
   1383         m_ObjectSize.Add(dwStart, j - dwStart);
   1384         dwStart = j;
   1385     }
   1386 }
   1387 void CPDF_Creator::InitNewObjNumOffsets()
   1388 {
   1389     FX_BOOL bIncremental = (m_dwFlags & FPDFCREATE_INCREMENTAL) != 0;
   1390     FX_BOOL bNoOriginal = (m_dwFlags & FPDFCREATE_NO_ORIGINAL) != 0;
   1391     FX_DWORD nOldSize = m_pParser ? m_pParser->m_CrossRef.GetSize() : 0;
   1392     FX_POSITION pos = m_pDocument->m_IndirectObjs.GetStartPosition();
   1393     while (pos) {
   1394         size_t key = 0;
   1395         CPDF_Object* pObj;
   1396         m_pDocument->m_IndirectObjs.GetNextAssoc(pos, (FX_LPVOID&)key, (FX_LPVOID&)pObj);
   1397         FX_DWORD objnum = (FX_DWORD)key;
   1398         if (pObj->GetObjNum() == -1) {
   1399             continue;
   1400         }
   1401         if (bIncremental) {
   1402             if (!pObj->IsModified()) {
   1403                 continue;
   1404             }
   1405         } else {
   1406             if (objnum < nOldSize && m_pParser->m_V5Type[objnum] != 0) {
   1407                 continue;
   1408             }
   1409         }
   1410         AppendNewObjNum(objnum);
   1411     }
   1412     FX_INT32 iCount = m_NewObjNumArray.GetSize();
   1413     if (iCount == 0) {
   1414         return;
   1415     }
   1416     FX_INT32 i = 0;
   1417     FX_DWORD dwStartObjNum = 0;
   1418     FX_BOOL bCrossRefValid = m_pParser && m_pParser->GetLastXRefOffset() > 0;
   1419     while (i < iCount) {
   1420         dwStartObjNum = m_NewObjNumArray.ElementAt(i);
   1421         if ((bIncremental && (bNoOriginal || bCrossRefValid)) || !m_ObjectOffset.GetPtrAt(dwStartObjNum)) {
   1422             break;
   1423         }
   1424         i++;
   1425     }
   1426     if (i >= iCount) {
   1427         return;
   1428     }
   1429     FX_DWORD dwLastObjNum = dwStartObjNum;
   1430     i++;
   1431     FX_BOOL bNewStart = FALSE;
   1432     for (; i < iCount; i++) {
   1433         FX_DWORD dwCurObjNum = m_NewObjNumArray.ElementAt(i);
   1434         FX_BOOL bExist = (dwCurObjNum < nOldSize && m_ObjectOffset.GetPtrAt(dwCurObjNum) != NULL);
   1435         if (bExist || dwCurObjNum - dwLastObjNum > 1) {
   1436             if (!bNewStart) {
   1437                 m_ObjectOffset.Add(dwStartObjNum, dwLastObjNum - dwStartObjNum + 1);
   1438                 m_ObjectSize.Add(dwStartObjNum, dwLastObjNum - dwStartObjNum + 1);
   1439             }
   1440             dwStartObjNum = dwCurObjNum;
   1441         }
   1442         if (bNewStart) {
   1443             dwStartObjNum = dwCurObjNum;
   1444         }
   1445         bNewStart = bExist;
   1446         dwLastObjNum = dwCurObjNum;
   1447     }
   1448     m_ObjectOffset.Add(dwStartObjNum, dwLastObjNum - dwStartObjNum + 1);
   1449     m_ObjectSize.Add(dwStartObjNum, dwLastObjNum - dwStartObjNum + 1);
   1450 }
   1451 void CPDF_Creator::AppendNewObjNum(FX_DWORD objbum)
   1452 {
   1453     FX_INT32 iStart = 0, iFind = 0;
   1454     FX_INT32 iEnd = m_NewObjNumArray.GetUpperBound();
   1455     while (iStart <= iEnd) {
   1456         FX_INT32 iMid = (iStart + iEnd) / 2;
   1457         FX_DWORD dwMid = m_NewObjNumArray.ElementAt(iMid);
   1458         if (objbum < dwMid) {
   1459             iEnd = iMid - 1;
   1460         } else {
   1461             if (iMid == iEnd) {
   1462                 iFind = iMid + 1;
   1463                 break;
   1464             }
   1465             FX_DWORD dwNext = m_NewObjNumArray.ElementAt(iMid + 1);
   1466             if (objbum < dwNext) {
   1467                 iFind = iMid + 1;
   1468                 break;
   1469             }
   1470             iStart = iMid + 1;
   1471         }
   1472     }
   1473     m_NewObjNumArray.InsertAt(iFind, objbum);
   1474 }
   1475 FX_INT32 CPDF_Creator::WriteDoc_Stage1(IFX_Pause *pPause)
   1476 {
   1477     FXSYS_assert(m_iStage > -1 || m_iStage < 20);
   1478     if (m_iStage == 0) {
   1479         if (m_pParser == NULL) {
   1480             m_dwFlags &= ~FPDFCREATE_INCREMENTAL;
   1481         }
   1482         if (m_bSecurityChanged && (m_dwFlags & FPDFCREATE_NO_ORIGINAL) == 0) {
   1483             m_dwFlags &= ~FPDFCREATE_INCREMENTAL;
   1484         }
   1485         m_pMetadata = m_pDocument->GetRoot()->GetElementValue(FX_BSTRC("Metadata"));
   1486         if (m_dwFlags & FPDFCREATE_OBJECTSTREAM) {
   1487             m_pXRefStream = FX_NEW CPDF_XRefStream;
   1488             m_pXRefStream->Start();
   1489             if ((m_dwFlags & FPDFCREATE_INCREMENTAL) != 0 && m_pParser) {
   1490                 FX_FILESIZE prev = m_pParser->GetLastXRefOffset();
   1491                 m_pXRefStream->m_PrevOffset = prev;
   1492             }
   1493         }
   1494         m_iStage = 10;
   1495     }
   1496     if (m_iStage == 10) {
   1497         if ((m_dwFlags & FPDFCREATE_INCREMENTAL) == 0) {
   1498             if (m_File.AppendString(FX_BSTRC("%PDF-1.")) < 0) {
   1499                 return -1;
   1500             }
   1501             m_Offset += 7;
   1502             FX_INT32 version = 7;
   1503             if (m_FileVersion) {
   1504                 version = m_FileVersion;
   1505             } else if (m_pParser) {
   1506                 version = m_pParser->GetFileVersion();
   1507             }
   1508             FX_INT32 len = m_File.AppendDWord(version % 10);
   1509             if (len < 0) {
   1510                 return -1;
   1511             }
   1512             m_Offset += len;
   1513             if ((len = m_File.AppendString(FX_BSTRC("\r\n%\xA1\xB3\xC5\xD7\r\n"))) < 0) {
   1514                 return -1;
   1515             }
   1516             m_Offset += len;
   1517             InitOldObjNumOffsets();
   1518             m_iStage = 20;
   1519         } else {
   1520             IFX_FileRead* pSrcFile = m_pParser->GetFileAccess();
   1521             m_Offset = pSrcFile->GetSize();
   1522             m_Pos = (FX_LPVOID)(FX_UINTPTR)m_Offset;
   1523             m_iStage = 15;
   1524         }
   1525     }
   1526     if (m_iStage == 15) {
   1527         if ((m_dwFlags & FPDFCREATE_NO_ORIGINAL) == 0 && m_Pos) {
   1528             IFX_FileRead* pSrcFile = m_pParser->GetFileAccess();
   1529             FX_BYTE buffer[4096];
   1530             FX_DWORD src_size = (FX_DWORD)(FX_UINTPTR)m_Pos;
   1531             while (src_size) {
   1532                 FX_DWORD block_size = src_size > 4096 ? 4096 : src_size;
   1533                 if (!pSrcFile->ReadBlock(buffer, m_Offset - src_size, block_size)) {
   1534                     return -1;
   1535                 }
   1536                 if (m_File.AppendBlock(buffer, block_size) < 0) {
   1537                     return -1;
   1538                 }
   1539                 src_size -= block_size;
   1540                 if (pPause && pPause->NeedToPauseNow()) {
   1541                     m_Pos = (FX_LPVOID)(FX_UINTPTR)src_size;
   1542                     return 1;
   1543                 }
   1544             }
   1545         }
   1546         if ((m_dwFlags & FPDFCREATE_NO_ORIGINAL) == 0 && m_pParser->GetLastXRefOffset() == 0) {
   1547             InitOldObjNumOffsets();
   1548             FX_DWORD dwEnd = m_pParser->GetLastObjNum();
   1549             FX_BOOL bObjStm = (m_dwFlags & FPDFCREATE_OBJECTSTREAM) != 0;
   1550             for (FX_DWORD objnum = 0; objnum <= dwEnd; objnum++) {
   1551                 if (m_pParser->m_V5Type[objnum] == 0 || m_pParser->m_V5Type[objnum] == 255) {
   1552                     continue;
   1553                 }
   1554                 m_ObjectOffset[objnum] = m_pParser->m_CrossRef[objnum];
   1555                 if (bObjStm) {
   1556                     m_pXRefStream->AddObjectNumberToIndexArray(objnum);
   1557                 }
   1558             }
   1559             if (bObjStm) {
   1560                 m_pXRefStream->EndXRefStream(this);
   1561                 m_pXRefStream->Start();
   1562             }
   1563         }
   1564         m_iStage = 20;
   1565     }
   1566     InitNewObjNumOffsets();
   1567     return m_iStage;
   1568 }
   1569 FX_INT32 CPDF_Creator::WriteDoc_Stage2(IFX_Pause *pPause)
   1570 {
   1571     FXSYS_assert(m_iStage >= 20 || m_iStage < 30);
   1572     if (m_iStage == 20) {
   1573         if ((m_dwFlags & FPDFCREATE_INCREMENTAL) == 0 && m_pParser) {
   1574             m_Pos = (FX_LPVOID)(FX_UINTPTR)0;
   1575             m_iStage = 21;
   1576         } else {
   1577             m_iStage = 25;
   1578         }
   1579     }
   1580     if (m_iStage == 21) {
   1581         FX_INT32 iRet = WriteOldObjs(pPause);
   1582         if (iRet) {
   1583             return iRet;
   1584         }
   1585         m_iStage = 25;
   1586     }
   1587     if (m_iStage == 25) {
   1588         m_Pos = (FX_LPVOID)(FX_UINTPTR)0;
   1589         m_iStage = 26;
   1590     }
   1591     if (m_iStage == 26) {
   1592         FX_INT32 iRet = WriteNewObjs((m_dwFlags & FPDFCREATE_INCREMENTAL) != 0, pPause);
   1593         if (iRet) {
   1594             return iRet;
   1595         }
   1596         m_iStage = 27;
   1597     }
   1598     if (m_iStage == 27) {
   1599         if (NULL != m_pEncryptDict && 0 == m_pEncryptDict->GetObjNum()) {
   1600             m_dwLastObjNum += 1;
   1601             FX_FILESIZE saveOffset = m_Offset;
   1602             if (WriteIndirectObj(m_dwLastObjNum, m_pEncryptDict) < 0) {
   1603                 return -1;
   1604             }
   1605             m_ObjectOffset.Add(m_dwLastObjNum, 1);
   1606             m_ObjectOffset[m_dwLastObjNum] = saveOffset;
   1607             m_ObjectSize.Add(m_dwLastObjNum, 1);
   1608             m_ObjectSize[m_dwLastObjNum] = m_Offset - saveOffset;
   1609             m_dwEnryptObjNum = m_dwLastObjNum;
   1610             if (m_dwFlags & FPDFCREATE_INCREMENTAL) {
   1611                 m_NewObjNumArray.Add(m_dwLastObjNum);
   1612             }
   1613         }
   1614         m_iStage = 80;
   1615     }
   1616     return m_iStage;
   1617 }
   1618 FX_INT32 CPDF_Creator::WriteDoc_Stage3(IFX_Pause *pPause)
   1619 {
   1620     FXSYS_assert(m_iStage >= 80 || m_iStage < 90);
   1621     FX_DWORD dwLastObjNum = m_dwLastObjNum;
   1622     if (m_iStage == 80) {
   1623         m_XrefStart = m_Offset;
   1624         if (m_dwFlags & FPDFCREATE_OBJECTSTREAM) {
   1625             m_pXRefStream->End(this, TRUE);
   1626             m_XrefStart = m_pXRefStream->m_PrevOffset;
   1627             m_iStage = 90;
   1628         } else if ((m_dwFlags & FPDFCREATE_INCREMENTAL) == 0 || !m_pParser->IsXRefStream()) {
   1629             if ((m_dwFlags & FPDFCREATE_INCREMENTAL) == 0 || m_pParser->GetLastXRefOffset() == 0) {
   1630                 CFX_ByteString str;
   1631                 str = m_ObjectOffset.GetPtrAt(1) ? FX_BSTRC("xref\r\n") : FX_BSTRC("xref\r\n0 1\r\n0000000000 65536 f\r\n");
   1632                 if (m_File.AppendString(str) < 0) {
   1633                     return -1;
   1634                 }
   1635                 m_Pos = (FX_LPVOID)(FX_UINTPTR)1;
   1636                 m_iStage = 81;
   1637             } else {
   1638                 if (m_File.AppendString(FX_BSTRC("xref\r\n")) < 0) {
   1639                     return -1;
   1640                 }
   1641                 m_Pos = (FX_LPVOID)(FX_UINTPTR)0;
   1642                 m_iStage = 82;
   1643             }
   1644         } else {
   1645             m_iStage = 90;
   1646         }
   1647     }
   1648     if (m_iStage == 81) {
   1649         CFX_ByteString str;
   1650         FX_DWORD i = (FX_DWORD)(FX_UINTPTR)m_Pos, j;
   1651         while (i <= dwLastObjNum) {
   1652             while (i <= dwLastObjNum && !m_ObjectOffset.GetPtrAt(i)) {
   1653                 i++;
   1654             }
   1655             if (i > dwLastObjNum) {
   1656                 break;
   1657             }
   1658             j = i;
   1659             while (j <= dwLastObjNum && m_ObjectOffset.GetPtrAt(j)) {
   1660                 j++;
   1661             }
   1662             if (i == 1) {
   1663                 str.Format("0 %d\r\n0000000000 65536 f\r\n", j);
   1664             } else {
   1665                 str.Format("%d %d\r\n", i, j - i);
   1666             }
   1667             if (m_File.AppendBlock((FX_LPCSTR)str, str.GetLength()) < 0) {
   1668                 return -1;
   1669             }
   1670             while (i < j) {
   1671                 str.Format("%010d 00000 n\r\n", m_ObjectOffset[i ++]);
   1672                 if (m_File.AppendBlock((FX_LPCSTR)str, str.GetLength()) < 0) {
   1673                     return -1;
   1674                 }
   1675             }
   1676             if (i > dwLastObjNum) {
   1677                 break;
   1678             }
   1679             if (pPause && pPause->NeedToPauseNow()) {
   1680                 m_Pos = (FX_LPVOID)(FX_UINTPTR)i;
   1681                 return 1;
   1682             }
   1683         }
   1684         m_iStage = 90;
   1685     }
   1686     if (m_iStage == 82) {
   1687         CFX_ByteString str;
   1688         FX_INT32 iCount = m_NewObjNumArray.GetSize();
   1689         FX_INT32 i = (FX_INT32)(FX_UINTPTR)m_Pos;
   1690         while (i < iCount) {
   1691             FX_INT32 j = i;
   1692             FX_DWORD objnum = m_NewObjNumArray.ElementAt(i);
   1693             while (j < iCount) {
   1694                 if (++j == iCount) {
   1695                     break;
   1696                 }
   1697                 FX_DWORD dwCurrent = m_NewObjNumArray.ElementAt(j);
   1698                 if (dwCurrent - objnum > 1) {
   1699                     break;
   1700                 }
   1701                 objnum = dwCurrent;
   1702             }
   1703             objnum = m_NewObjNumArray.ElementAt(i);
   1704             if (objnum == 1) {
   1705                 str.Format("0 %d\r\n0000000000 65536 f\r\n", j - i + 1);
   1706             } else {
   1707                 str.Format("%d %d\r\n", objnum, j - i);
   1708             }
   1709             if (m_File.AppendBlock((FX_LPCSTR)str, str.GetLength()) < 0) {
   1710                 return -1;
   1711             }
   1712             while (i < j) {
   1713                 objnum = m_NewObjNumArray.ElementAt(i++);
   1714                 str.Format("%010d 00000 n\r\n", m_ObjectOffset[objnum]);
   1715                 if (m_File.AppendBlock((FX_LPCSTR)str, str.GetLength()) < 0) {
   1716                     return -1;
   1717                 }
   1718             }
   1719             if (pPause && (i % 100) == 0 && pPause->NeedToPauseNow()) {
   1720                 m_Pos = (FX_LPVOID)(FX_UINTPTR)i;
   1721                 return 1;
   1722             }
   1723         }
   1724         m_iStage = 90;
   1725     }
   1726     return m_iStage;
   1727 }
   1728 static FX_INT32 _OutPutIndex(CFX_FileBufferArchive* pFile, FX_FILESIZE offset)
   1729 {
   1730     FXSYS_assert(pFile);
   1731     if (sizeof(offset) > 4) {
   1732         if (FX_GETBYTEOFFSET32(offset)) {
   1733             if (pFile->AppendByte(FX_GETBYTEOFFSET56(offset)) < 0) {
   1734                 return -1;
   1735             }
   1736             if (pFile->AppendByte(FX_GETBYTEOFFSET48(offset)) < 0) {
   1737                 return -1;
   1738             }
   1739             if (pFile->AppendByte(FX_GETBYTEOFFSET40(offset)) < 0) {
   1740                 return -1;
   1741             }
   1742             if (pFile->AppendByte(FX_GETBYTEOFFSET32(offset)) < 0) {
   1743                 return -1;
   1744             }
   1745         }
   1746     }
   1747     if (pFile->AppendByte(FX_GETBYTEOFFSET24(offset)) < 0) {
   1748         return -1;
   1749     }
   1750     if (pFile->AppendByte(FX_GETBYTEOFFSET16(offset)) < 0) {
   1751         return -1;
   1752     }
   1753     if (pFile->AppendByte(FX_GETBYTEOFFSET8(offset)) < 0) {
   1754         return -1;
   1755     }
   1756     if (pFile->AppendByte(FX_GETBYTEOFFSET0(offset)) < 0) {
   1757         return -1;
   1758     }
   1759     if (pFile->AppendByte(0) < 0) {
   1760         return -1;
   1761     }
   1762     return 0;
   1763 }
   1764 FX_INT32 CPDF_Creator::WriteDoc_Stage4(IFX_Pause *pPause)
   1765 {
   1766     FXSYS_assert(m_iStage >= 90);
   1767     if ((m_dwFlags & FPDFCREATE_OBJECTSTREAM) == 0) {
   1768         FX_BOOL bXRefStream = (m_dwFlags & FPDFCREATE_INCREMENTAL) != 0 && m_pParser->IsXRefStream();
   1769         if (!bXRefStream) {
   1770             if (m_File.AppendString(FX_BSTRC("trailer\r\n<<")) < 0) {
   1771                 return -1;
   1772             }
   1773         } else {
   1774             if (m_File.AppendDWord(m_pDocument->m_LastObjNum + 1) < 0) {
   1775                 return -1;
   1776             }
   1777             if (m_File.AppendString(FX_BSTRC(" 0 obj <<")) < 0) {
   1778                 return -1;
   1779             }
   1780         }
   1781         if (m_pParser) {
   1782             CPDF_Dictionary* p = m_pParser->m_pTrailer;
   1783             FX_POSITION pos = p->GetStartPos();
   1784             while (pos) {
   1785                 CFX_ByteString key;
   1786                 CPDF_Object* pValue = p->GetNextElement(pos, key);
   1787                 if (key == FX_BSTRC("Encrypt") || key == FX_BSTRC("Size") || key == FX_BSTRC("Filter") ||
   1788                         key == FX_BSTRC("Index") || key == FX_BSTRC("Length") || key == FX_BSTRC("Prev") ||
   1789                         key == FX_BSTRC("W") || key == FX_BSTRC("XRefStm") || key == FX_BSTRC("ID")) {
   1790                     continue;
   1791                 }
   1792                 if (m_File.AppendString((FX_BSTRC("/"))) < 0) {
   1793                     return -1;
   1794                 }
   1795                 if (m_File.AppendString(PDF_NameEncode(key)) < 0) {
   1796                     return -1;
   1797                 }
   1798                 if (pValue->GetObjNum()) {
   1799                     if (m_File.AppendString(FX_BSTRC(" ")) < 0) {
   1800                         return -1;
   1801                     }
   1802                     if (m_File.AppendDWord(pValue->GetObjNum()) < 0) {
   1803                         return -1;
   1804                     }
   1805                     if (m_File.AppendString(FX_BSTRC(" 0 R ")) < 0) {
   1806                         return -1;
   1807                     }
   1808                 } else {
   1809                     FX_FILESIZE offset = 0;
   1810                     if (PDF_CreatorAppendObject(pValue, &m_File, offset) < 0) {
   1811                         return -1;
   1812                     }
   1813                 }
   1814             }
   1815         } else {
   1816             if (m_File.AppendString(FX_BSTRC("\r\n/Root ")) < 0) {
   1817                 return -1;
   1818             }
   1819             if (m_File.AppendDWord(m_pDocument->m_pRootDict->GetObjNum()) < 0) {
   1820                 return -1;
   1821             }
   1822             if (m_File.AppendString(FX_BSTRC(" 0 R\r\n")) < 0) {
   1823                 return -1;
   1824             }
   1825             if (m_pDocument->m_pInfoDict) {
   1826                 if (m_File.AppendString(FX_BSTRC("/Info ")) < 0) {
   1827                     return -1;
   1828                 }
   1829                 if (m_File.AppendDWord(m_pDocument->m_pInfoDict->GetObjNum()) < 0) {
   1830                     return -1;
   1831                 }
   1832                 if (m_File.AppendString(FX_BSTRC(" 0 R\r\n")) < 0) {
   1833                     return -1;
   1834                 }
   1835             }
   1836         }
   1837         if (m_pEncryptDict) {
   1838             if (m_File.AppendString(FX_BSTRC("/Encrypt")) < 0) {
   1839                 return -1;
   1840             }
   1841             FX_DWORD dwObjNum = m_pEncryptDict->GetObjNum();
   1842             if (dwObjNum == 0) {
   1843                 dwObjNum = m_pDocument->GetLastObjNum() + 1;
   1844             }
   1845             if (m_File.AppendString(FX_BSTRC(" ")) < 0) {
   1846                 return -1;
   1847             }
   1848             if (m_File.AppendDWord(dwObjNum) < 0) {
   1849                 return -1;
   1850             }
   1851             if (m_File.AppendString(FX_BSTRC(" 0 R ")) < 0) {
   1852                 return -1;
   1853             }
   1854         }
   1855         if (m_File.AppendString(FX_BSTRC("/Size ")) < 0) {
   1856             return -1;
   1857         }
   1858         if (m_File.AppendDWord(m_dwLastObjNum + (bXRefStream ? 2 : 1)) < 0) {
   1859             return -1;
   1860         }
   1861         if ((m_dwFlags & FPDFCREATE_INCREMENTAL) != 0) {
   1862             FX_FILESIZE prev = m_pParser->GetLastXRefOffset();
   1863             if (prev) {
   1864                 if (m_File.AppendString(FX_BSTRC("/Prev ")) < 0) {
   1865                     return -1;
   1866                 }
   1867                 FX_CHAR offset_buf[20];
   1868                 FXSYS_memset32(offset_buf, 0, sizeof(offset_buf));
   1869                 FXSYS_i64toa(prev, offset_buf, 10);
   1870                 if (m_File.AppendBlock(offset_buf, FXSYS_strlen(offset_buf)) < 0) {
   1871                     return -1;
   1872                 }
   1873             }
   1874         }
   1875         if (m_pIDArray) {
   1876             if (m_File.AppendString((FX_BSTRC("/ID"))) < 0) {
   1877                 return -1;
   1878             }
   1879             FX_FILESIZE offset = 0;
   1880             if (PDF_CreatorAppendObject(m_pIDArray, &m_File, offset) < 0) {
   1881                 return -1;
   1882             }
   1883         }
   1884         if (!bXRefStream) {
   1885             if (m_File.AppendString(FX_BSTRC(">>")) < 0) {
   1886                 return -1;
   1887             }
   1888         } else {
   1889             if (m_File.AppendString(FX_BSTRC("/W[0 4 1]/Index[")) < 0) {
   1890                 return -1;
   1891             }
   1892             if ((m_dwFlags & FPDFCREATE_INCREMENTAL) != 0 && m_pParser && m_pParser->GetLastXRefOffset() == 0) {
   1893                 FX_DWORD i = 0;
   1894                 for (i = 0; i < m_dwLastObjNum; i++) {
   1895                     if (!m_ObjectOffset.GetPtrAt(i)) {
   1896                         continue;
   1897                     }
   1898                     if (m_File.AppendDWord(i) < 0) {
   1899                         return -1;
   1900                     }
   1901                     if (m_File.AppendString(FX_BSTRC(" 1 ")) < 0) {
   1902                         return -1;
   1903                     }
   1904                 }
   1905                 if (m_File.AppendString(FX_BSTRC("]/Length ")) < 0) {
   1906                     return -1;
   1907                 }
   1908                 if (m_File.AppendDWord(m_dwLastObjNum * 5) < 0) {
   1909                     return -1;
   1910                 }
   1911                 if (m_File.AppendString(FX_BSTRC(">>stream\r\n")) < 0) {
   1912                     return -1;
   1913                 }
   1914                 for (i = 0; i < m_dwLastObjNum; i++) {
   1915                     FX_FILESIZE* offset = m_ObjectOffset.GetPtrAt(i);
   1916                     if (!offset) {
   1917                         continue;
   1918                     }
   1919                     _OutPutIndex(&m_File, *offset);
   1920                 }
   1921             } else {
   1922                 int count = m_NewObjNumArray.GetSize();
   1923                 FX_INT32 i = 0;
   1924                 for (i = 0; i < count; i++) {
   1925                     FX_DWORD objnum = m_NewObjNumArray.ElementAt(i);
   1926                     if (m_File.AppendDWord(objnum) < 0) {
   1927                         return -1;
   1928                     }
   1929                     if (m_File.AppendString(FX_BSTRC(" 1 ")) < 0) {
   1930                         return -1;
   1931                     }
   1932                 }
   1933                 if (m_File.AppendString(FX_BSTRC("]/Length ")) < 0) {
   1934                     return -1;
   1935                 }
   1936                 if (m_File.AppendDWord(count * 5) < 0) {
   1937                     return -1;
   1938                 }
   1939                 if (m_File.AppendString(FX_BSTRC(">>stream\r\n")) < 0) {
   1940                     return -1;
   1941                 }
   1942                 for (i = 0; i < count; i++) {
   1943                     FX_DWORD objnum = m_NewObjNumArray.ElementAt(i);
   1944                     FX_FILESIZE offset = m_ObjectOffset[objnum];
   1945                     _OutPutIndex(&m_File, offset);
   1946                 }
   1947             }
   1948             if (m_File.AppendString(FX_BSTRC("\r\nendstream")) < 0) {
   1949                 return -1;
   1950             }
   1951         }
   1952     }
   1953     if (m_File.AppendString(FX_BSTRC("\r\nstartxref\r\n")) < 0) {
   1954         return -1;
   1955     }
   1956     FX_CHAR offset_buf[20];
   1957     FXSYS_memset32(offset_buf, 0, sizeof(offset_buf));
   1958     FXSYS_i64toa(m_XrefStart, offset_buf, 10);
   1959     if (m_File.AppendBlock(offset_buf, FXSYS_strlen(offset_buf)) < 0) {
   1960         return -1;
   1961     }
   1962     if (m_File.AppendString(FX_BSTRC("\r\n%%EOF\r\n")) < 0) {
   1963         return -1;
   1964     }
   1965     m_File.Flush();
   1966     return m_iStage = 100;
   1967 }
   1968 void CPDF_Creator::Clear()
   1969 {
   1970     if (m_pXRefStream) {
   1971         delete m_pXRefStream;
   1972         m_pXRefStream = NULL;
   1973     }
   1974     m_File.Clear();
   1975     m_NewObjNumArray.RemoveAll();
   1976     if (m_pIDArray) {
   1977         m_pIDArray->Release();
   1978         m_pIDArray = NULL;
   1979     }
   1980 }
   1981 FX_BOOL CPDF_Creator::Create(FX_LPCSTR filename, FX_DWORD flags)
   1982 {
   1983     if (!m_File.AttachFile(filename)) {
   1984         return FALSE;
   1985     }
   1986     FX_BOOL bRet = Create(flags);
   1987     if (!bRet || !(flags & FPDFCREATE_PROGRESSIVE)) {
   1988         Clear();
   1989     }
   1990     return bRet;
   1991 }
   1992 FX_BOOL CPDF_Creator::Create(FX_LPCWSTR filename, FX_DWORD flags)
   1993 {
   1994     if (!m_File.AttachFile(filename)) {
   1995         return FALSE;
   1996     }
   1997     FX_BOOL bRet = Create(flags);
   1998     if (!bRet || !(flags & FPDFCREATE_PROGRESSIVE)) {
   1999         Clear();
   2000     }
   2001     return bRet;
   2002 }
   2003 FX_BOOL CPDF_Creator::Create(IFX_StreamWrite* pFile, FX_DWORD flags)
   2004 {
   2005     if (!pFile) {
   2006         return FALSE;
   2007     }
   2008     if (!m_File.AttachFile(pFile, FALSE)) {
   2009         return FALSE;
   2010     }
   2011     return Create(flags);
   2012 }
   2013 FX_BOOL CPDF_Creator::Create(FX_DWORD flags)
   2014 {
   2015     m_dwFlags = flags;
   2016     m_iStage = 0;
   2017     m_Offset = 0;
   2018     m_dwLastObjNum = m_pDocument->GetLastObjNum();
   2019     m_ObjectOffset.Clear();
   2020     m_ObjectSize.Clear();
   2021     m_NewObjNumArray.RemoveAll();
   2022     InitID();
   2023     if (flags & FPDFCREATE_PROGRESSIVE) {
   2024         return TRUE;
   2025     }
   2026     return Continue(NULL) > -1;
   2027 }
   2028 void CPDF_Creator::InitID(FX_BOOL bDefault )
   2029 {
   2030     CPDF_Array* pOldIDArray = m_pParser ? m_pParser->GetIDArray() : NULL;
   2031     FX_BOOL bNewId = !m_pIDArray;
   2032     if (!m_pIDArray) {
   2033         FX_LPDWORD pBuffer = NULL;
   2034         m_pIDArray = CPDF_Array::Create();
   2035         CPDF_Object* pID1 = pOldIDArray->GetElement(0);
   2036         if (pID1) {
   2037             m_pIDArray->Add(pID1->Clone());
   2038         } else {
   2039             pBuffer = FX_Alloc(FX_DWORD, 4);
   2040             PDF_GenerateFileID((FX_DWORD)(FX_UINTPTR)this, m_dwLastObjNum, pBuffer);
   2041             CFX_ByteStringC bsBuffer((FX_LPCBYTE)pBuffer, 4 * sizeof(FX_DWORD));
   2042             m_pIDArray->Add(CPDF_String::Create(bsBuffer, TRUE), m_pDocument);
   2043         }
   2044         if (pBuffer) {
   2045             FX_Free(pBuffer);
   2046         }
   2047     }
   2048     if (!bDefault) {
   2049         return;
   2050     }
   2051     if (pOldIDArray) {
   2052         CPDF_Object* pID2 = pOldIDArray->GetElement(1);
   2053         if ((m_dwFlags & FPDFCREATE_INCREMENTAL) && m_pEncryptDict && pID2) {
   2054             m_pIDArray->Add(pID2->Clone());
   2055             return;
   2056         }
   2057         FX_LPDWORD pBuffer = FX_Alloc(FX_DWORD, 4);
   2058         PDF_GenerateFileID((FX_DWORD)(FX_UINTPTR)this, m_dwLastObjNum, pBuffer);
   2059         CFX_ByteStringC bsBuffer((FX_LPCBYTE)pBuffer, 4 * sizeof(FX_DWORD));
   2060         m_pIDArray->Add(CPDF_String::Create(bsBuffer, TRUE), m_pDocument);
   2061         FX_Free(pBuffer);
   2062         return;
   2063     }
   2064     m_pIDArray->Add(m_pIDArray->GetElement(0)->Clone());
   2065     if (m_pEncryptDict && !pOldIDArray && m_pParser && bNewId) {
   2066         if (m_pEncryptDict->GetString(FX_BSTRC("Filter")) == FX_BSTRC("Standard")) {
   2067             CPDF_StandardSecurityHandler handler;
   2068             CFX_ByteString user_pass = m_pParser->GetPassword();
   2069             FX_DWORD flag = PDF_ENCRYPT_CONTENT;
   2070             handler.OnCreate(m_pEncryptDict, m_pIDArray, (FX_LPCBYTE)user_pass, user_pass.GetLength(), flag);
   2071             if (m_pCryptoHandler && m_bNewCrypto) {
   2072                 delete m_pCryptoHandler;
   2073             }
   2074             m_pCryptoHandler = FX_NEW CPDF_StandardCryptoHandler;
   2075             m_pCryptoHandler->Init(m_pEncryptDict, &handler);
   2076             m_bNewCrypto = TRUE;
   2077             m_bSecurityChanged = TRUE;
   2078         }
   2079     }
   2080 }
   2081 FX_INT32 CPDF_Creator::Continue(IFX_Pause *pPause)
   2082 {
   2083     if (m_iStage < 0) {
   2084         return m_iStage;
   2085     }
   2086     FX_INT32 iRet;
   2087     while (m_iStage < 100) {
   2088         if (m_iStage < 20) {
   2089             iRet = WriteDoc_Stage1(pPause);
   2090         } else if (m_iStage < 30) {
   2091             iRet = WriteDoc_Stage2(pPause);
   2092         } else if (m_iStage < 90) {
   2093             iRet = WriteDoc_Stage3(pPause);
   2094         } else {
   2095             iRet = WriteDoc_Stage4(pPause);
   2096         }
   2097         if (iRet < m_iStage) {
   2098             break;
   2099         }
   2100     }
   2101     if (iRet < 1 || m_iStage == 100) {
   2102         m_iStage = -1;
   2103         Clear();
   2104         return iRet > 99 ? 0 : (iRet < 1 ? -1 : iRet);
   2105     }
   2106     return m_iStage;
   2107 }
   2108 FX_BOOL CPDF_Creator::SetFileVersion(FX_INT32 fileVersion )
   2109 {
   2110     if (fileVersion < 10 || fileVersion > 17) {
   2111         return FALSE;
   2112     }
   2113     m_FileVersion = fileVersion;
   2114     return TRUE;
   2115 }
   2116 void CPDF_Creator::ResetStandardSecurity()
   2117 {
   2118     if ((m_bStandardSecurity || m_bNewCrypto) && m_pCryptoHandler) {
   2119         delete m_pCryptoHandler;
   2120         m_pCryptoHandler = NULL;
   2121     }
   2122     m_bNewCrypto = FALSE;
   2123     if (!m_bStandardSecurity) {
   2124         return;
   2125     }
   2126     if (m_pEncryptDict) {
   2127         m_pEncryptDict->Release();
   2128         m_pEncryptDict = NULL;
   2129     }
   2130     m_bStandardSecurity = FALSE;
   2131 }
   2132