Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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 );
    }
}