PdfDestination::PdfDestination( const PdfPage* pPage, const PdfRect & rRect ) { PdfVariant var; rRect.ToVariant( var ); m_array.push_back( pPage->GetObject()->Reference() ); m_array.push_back( PdfName("FitR") ); m_array.insert( m_array.end(), var.GetArray().begin(), var.GetArray().end() ); m_pObject = pPage->GetObject()->GetOwner()->CreateObject( m_array ); }
PdfObject* PdfPagesTree::GetPageNodeFromArray( int nPageNum, const PdfArray & rKidsArray, PdfObjectList & rLstParents ) { if( static_cast<size_t>(nPageNum) >= rKidsArray.GetSize() ) { PdfError::LogMessage( eLogSeverity_Critical, "Requesting page index %i from array of size %i\n", nPageNum, rKidsArray.size() ); return NULL; } // TODO: Fill cache immediately with all pages // in this kids array PdfVariant rVar = rKidsArray[nPageNum]; while( true ) { if( rVar.IsArray() ) { // Fixes some broken PDFs who have trees with 1 element kids arrays return GetPageNodeFromArray( 0, rVar.GetArray(), rLstParents ); } else if( !rVar.IsReference() ) { PODOFO_RAISE_ERROR_INFO( ePdfError_NotImplemented, "Cannot handle inline pages." ); } PdfObject* pgObject = GetRoot()->GetOwner()->GetObject( rVar.GetReference() ); if(pgObject==NULL) { PODOFO_RAISE_ERROR_INFO( ePdfError_PageNotFound, "Invalid reference." ); } //printf("Reading %s\n", pgObject->Reference().ToString().c_str()); // make sure the object is a /Page and not a /Pages with a single kid if( this->IsTypePage(pgObject) ) { return pgObject; } // it's a /Pages with a single kid, so dereference and try again... if (this->IsTypePages(pgObject) ) { if( !pgObject->GetDictionary().HasKey( "Kids" ) ) return NULL; rLstParents.push_back( pgObject ); rVar = *(pgObject->GetDictionary().GetKey( "Kids" )); } else { // Reference to unexpected object PODOFO_RAISE_ERROR_INFO( ePdfError_PageNotFound, "Reference to unexpected object." ); } } return NULL; }
void PdfSigIncWriter::Write( PdfOutputDevice* pDevice, pdf_int64 prevOffset) { //CreateFileIdentifier( m_identifier, m_pTrailer ); if( m_pTrailer->GetDictionary().HasKey( "ID" ) ) { PdfObject *idObj = m_pTrailer->GetDictionary().GetKey("ID"); TCIVariantList it = idObj->GetArray().begin(); while( it != idObj->GetArray().end() ) { if( (*it).GetDataType() == ePdfDataType_HexString ) { PdfVariant var = (*it); m_identifier = var.GetString(); } ++it; } } else { PdfDate date; PdfString dateString; PdfObject* pInfo; PdfOutputDevice length; date.ToString( dateString ); pInfo = new PdfObject(); pInfo->GetDictionary().AddKey( "CreationDate", dateString ); pInfo->GetDictionary().AddKey( "Creator", PdfString("PoDoFo") ); pInfo->GetDictionary().AddKey( "Producer", PdfString("PoDoFo") ); pInfo->GetDictionary().AddKey( "Location", PdfString("SOMEFILENAME") ); pInfo->WriteObject( &length, ePdfWriteMode_Clean, NULL ); char *pBuffer = static_cast<char*>(podofo_calloc( length.GetLength(), sizeof(char) )); if( !pBuffer ) { delete pInfo; PODOFO_RAISE_ERROR( ePdfError_OutOfMemory ); } PdfOutputDevice device( pBuffer, length.GetLength() ); pInfo->WriteObject( &device, ePdfWriteMode_Clean, NULL ); // calculate the MD5 Sum m_identifier = PdfEncryptMD5Base::GetMD5String( reinterpret_cast<unsigned char*>(pBuffer), static_cast<unsigned int>(length.GetLength()) ); podofo_free( pBuffer ); delete pInfo; } if( !pDevice ) { PODOFO_RAISE_ERROR( ePdfError_InvalidHandle ); } // setup encrypt dictionary if( m_pEncrypt ) { m_pEncrypt->GenerateEncryptionKey( m_identifier ); // Add our own Encryption dictionary m_pEncryptObj = m_vecObjects->CreateObject(); m_pEncrypt->CreateEncryptionDictionary( m_pEncryptObj->GetDictionary() ); } if( GetLinearized() ) { this->WriteLinearized( pDevice ); } else { PdfXRef* pXRef = m_bXRefStream ? new PdfXRefStream( m_vecObjects, this ) : new PdfXRef(); try { // WritePdfHeader ( pDevice ); WritePdfObjects ( pDevice, *m_vecObjects, pXRef ); pXRef->SetFirstEmptyBlock(); pXRef->Write( pDevice ); // XRef streams contain the trailer in the XRef if( !m_bXRefStream ) { PdfObject trailer; // if we have a dummy offset we write also a prev entry to the trailer FillTrailerObject( &trailer, pXRef->GetSize(), false, false ); PdfObject prevOffsetObj(prevOffset); trailer.GetDictionary().AddKey( "Prev", prevOffsetObj); pDevice->Print("trailer\n"); trailer.WriteObject( pDevice, ePdfWriteMode_Clean, NULL ); // Do not encrypt the trailer dicionary!!! } pDevice->Print( "startxref\n%li\n%%%%EOF\n", pXRef->GetOffset()); delete pXRef; } catch( PdfError & e ) { // Make sure pXRef is always deleted delete pXRef; e.AddToCallstack( __FILE__, __LINE__ ); throw e; } } }
void PdfParser::ReadXRefStreamContents( pdf_long lOffset, bool bReadOnlyTrailer ) { char* pBuffer; char* pStart; pdf_long lBufferLen; long long lSize = 0; PdfVariant vWArray; PdfObject* pObj; long nW[W_ARRAY_SIZE] = { 0, 0, 0 }; int i; m_device.Device()->Seek( lOffset ); PdfParserObject xrefObject( m_vecObjects, m_device, m_buffer ); // Ignore the encryption in the XREF as the XREF stream must no be encrypted (see PDF Reference 3.4.7) xrefObject.ParseFile( NULL ); if( !xrefObject.GetDictionary().HasKey( PdfName::KeyType ) ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } pObj = xrefObject.GetDictionary().GetKey( PdfName::KeyType ); if( !pObj->IsName() || ( pObj->GetName() != "XRef" ) ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } if( !m_pTrailer ) m_pTrailer = new PdfParserObject( m_vecObjects, m_device, m_buffer ); MergeTrailer( &xrefObject ); if( bReadOnlyTrailer ) return; if( !xrefObject.GetDictionary().HasKey( PdfName::KeySize ) || !xrefObject.GetDictionary().HasKey( "W" ) ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } lSize = xrefObject.GetDictionary().GetKeyAsLong( PdfName::KeySize, 0 ); vWArray = *(xrefObject.GetDictionary().GetKey( "W" )); // The pdf reference states that W is always an array with 3 entries // all of them have to be integeres if( !vWArray.IsArray() || vWArray.GetArray().size() != 3 ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } for( i=0;i<W_ARRAY_SIZE;i++ ) { if( !vWArray.GetArray()[i].IsNumber() ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } nW[i] = static_cast<long>(vWArray.GetArray()[i].GetNumber()); } std::vector<long long> vecIndeces; // get the first object number in this crossref stream. // it is not required to have an index key though. if( xrefObject.GetDictionary().HasKey( "Index" ) ) { // reuse vWArray!! vWArray = *(xrefObject.GetDictionary().GetKey( "Index" )); if( !vWArray.IsArray() ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } TCIVariantList it = vWArray.GetArray().begin(); while ( it != vWArray.GetArray().end() ) { vecIndeces.push_back( (*it).GetNumber() ); ++it; } } else { vecIndeces.push_back( 0 ); vecIndeces.push_back( lSize ); } if( vecIndeces.size() % 2 ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } if( !xrefObject.HasStreamToParse() ) { PODOFO_RAISE_ERROR( ePdfError_NoXRef ); } xrefObject.GetStream()->GetFilteredCopy( &pBuffer, &lBufferLen ); pStart = pBuffer; int nCurIndex = 0; while( nCurIndex < static_cast<pdf_long>(vecIndeces.size()) && pBuffer - pStart < lBufferLen ) { int nFirstObj = static_cast<int>(vecIndeces[nCurIndex]); long long nCount = vecIndeces[nCurIndex+1]; while( nCount-- && pBuffer - pStart < lBufferLen ) { ReadXRefStreamEntry( pBuffer, lBufferLen, nW, nFirstObj++ ); pBuffer += (nW[0] + nW[1] + nW[2]); } nCurIndex += 2; } free( pStart ); if( xrefObject.GetDictionary().HasKey("Prev") ) { lOffset = static_cast<pdf_long>(xrefObject.GetDictionary().GetKeyAsLong( "Prev", 0 )); ReadXRefStreamContents( lOffset, bReadOnlyTrailer ); } }