예제 #1
0
	void parsePPT(OLEStreamReader& reader, std::string& text)
	{
		std::vector<unsigned char> rec(8);
		bool read_status = true;
		std::stack<long> container_ends;
		while (read_status)
		{
			int pos = reader.tell();
			read_status = reader.read(&*rec.begin(), 8);
			if (oleEof(reader))
			{
				parseRecord(RT_END_DOCUMENT_ATOM, 0, reader, text);
				return;
			}
			if (rec.size() < 8)
				break;
			int rec_type = getU16LittleEndian(rec.begin() + 2);
			U32 rec_len = getU32LittleEndian(rec.begin() + 4);
			if (m_verbose_logging)
			{
				while (!container_ends.empty() && pos+rec_len-1 > container_ends.top())
					container_ends.pop();
				std::string indend;
				for (int i = 0; i < container_ends.size(); i++)
					indend += "\t";
				*m_log_stream << indend << "record=0x" << std::hex << rec_type << ", begin=0x" << pos << ", end=0x" << pos + rec_len - 1 << "\n";
				container_ends.push(pos + rec_len - 1);
			}
			parseRecord(rec_type, rec_len, reader, text);
		}
	}
예제 #2
0
void Parser9x::parsePicture( const PictureData& data )
{
    wvlog << "Parser9x::parsePicture" << std::endl;
    OLEStreamReader* stream = m_fib.nFib < Word8nFib ? m_wordDocument : m_data;
    stream->push(); // saveState would be overkill

    //go to the position in the stream after the PICF, where the actual picture data/escher is
    if ( !stream->seek( data.fcPic + data.picf->cbHeader, G_SEEK_SET ) ) {
        wvlog << "Error: Parser9x::parsePicture couldn't seek properly" << std::endl;
        stream->pop();
        return;
    }

    if ( data.picf->mfp.mm == 0x64 || data.picf->mfp.mm == 0x66 ) {
        wvlog << "Linked graphic in Escher object" << std::endl;
        parsePictureEscher( data, stream, data.picf->lcb, data.fcPic );
    }
    else {
        switch ( data.picf->mfp.mm ) {
            case 94: // A .bmp or a .gif name is stored after the PICF
            case 98: // The .tiff name is stored after the PICF
                parsePictureExternalHelper( data, stream );
                break;
            case 99: // A full bmp is stored after the PICF -- not handled in OOo??
                parsePictureBitmapHelper( data, stream );
                break;
            default: // It has to be a .wmf or .emf file (right after the PICF)
                wvlog << "assuming WMF/EMF file... not sure this is correct" << std::endl;
                parsePictureWmfHelper( data, stream );
                break;
        }
    }
    stream->pop();
}
예제 #3
0
// Some basic test for the storage system. Please don't change the oletest.doc
// file as some tests depend on exacly that file (e.g. directory names)
int main( int, char** )
{
    std::cerr << "Testing the OLE storage and the streams..." << std::endl;
    std::cerr << "###############################################################################" << std::endl;
    std::cerr << "Test 1: Open the sample file: ";
    OLEStorage storage( "testole.doc" );
    test( storage.open( OLEStorage::ReadOnly ) );
    std::cerr << "###############################################################################" << std::endl;

    std::cerr << "Test2: List the contents of the root directory:" << std::endl;
    std::list<std::string> dir = storage.listDirectory();
    test( storage.isValid() );

    std::list<std::string>::const_iterator it = dir.begin();
    std::list<std::string>::const_iterator end = dir.end();
    for ( ; it != end; ++it )
        std::cerr << "   - " << *it << std::endl;
    std::cerr << "###############################################################################" << std::endl;

    std::cerr << "Test3: Stat a stream: skipped" << std::endl;
    /*
    MsOleStat s = storage.stat( "WordDocument" );
    test( storage.lastError() == MS_OLE_ERR_OK && s.type == MsOleStreamT &&
          s.size != static_cast<unsigned int>( -1 ), "### Error in Test 3: " + int2string( storage.lastError() ), "Passed." );
    */

    std::cerr << "Test4: Stat a storage (directory): skipped" << std::endl;
    /*
    s = storage.stat( "ObjectPool" );
    test( storage.lastError() == MS_OLE_ERR_OK && s.type == MsOleStorageT &&
          s.size != static_cast<unsigned int>( -1 ) , "### Error in Test 4: " + int2string( storage.lastError() ), "Passed." );
    */

    std::cerr << "Test5: Enter a directory: ";
    test( storage.enterDirectory( "ObjectPool" ) );
    std::cerr << "###############################################################################" << std::endl;

    std::cerr << "Test6: List the contents of the current directory:" << std::endl;
    dir = storage.listDirectory();
    test( storage.isValid() );
    it = dir.begin();
    end = dir.end();
    for ( ; it != end; ++it )
        std::cerr << "   - " << *it << std::endl;
    std::cerr << "###############################################################################" << std::endl;

    std::cerr << "Test7: Leave a directory." << std::endl;
    storage.leaveDirectory();
    storage.leaveDirectory();  // we can do that as often as we want to
    storage.leaveDirectory();  // as we will never leave '/'
    std::cerr << "###############################################################################" << std::endl;

    std::cerr << "Test8: List the contents of the current directory (should be the root dir):" << std::endl;
    dir = storage.listDirectory();
    test( storage.isValid() );
    it = dir.begin();
    end = dir.end();
    for ( ; it != end; ++it )
        std::cerr << "   - " << *it << std::endl;
    std::cerr << "###############################################################################" << std::endl;

    // go somewhere (for testing purpose)
    storage.enterDirectory( "ObjectPool" );
    std::cerr << "Test9: Set a few custom paths:" << std::endl;
    std::cerr << "   Trying '/ObjectPool/_1020966487': ";
    test( storage.setPath("/ObjectPool/_1020966487") );
    std::cerr << "   Trying '/ObjectPool/_1020966487': ";
    test( storage.setPath("/ObjectPool/_1020966487") );
    std::cerr << "   Trying 'ObjectPool/_1020966487': ";
    test( storage.setPath("ObjectPool/_1020966487") );
    std::cerr << "   Trying 'ObjectPool/_1020966487/': ";
    test( storage.setPath("ObjectPool/_1020966487/") );
    std::cerr << "   Trying '/ObjectPool/_1020966487/': ";
    test( storage.setPath("/ObjectPool/_1020966487/") );
    std::cerr << "   Trying '/ObjectPool_1020966487': ";
    test( !storage.setPath("/ObjectPool_1020966487") );
    std::cerr << "   Trying '/': ";
    test( storage.setPath("/") && storage.path()=="/" );
    std::cerr << "###############################################################################" << std::endl;

    std::cerr << "Test10: Open a stream for reading: ";
    OLEStreamReader* reader = storage.createStreamReader( "1Table" );
    test( reader && reader->isValid() );

    std::cerr << "Test11: Check whether we are at 0 right after opening: ";
    test( reader->tell() == 0 );

    std::cerr << "Test12: Check the size of the stream: ";
    test( reader->size() == 0x20a6 );

    std::cerr << "Test13: Seek in the stream: ";
    reader->seek( 0x100 );
    test( reader->seek( 1, G_SEEK_CUR ) && reader->tell() == 0x101 );
    reader->push(); // save the current pos (0x101)

    std::cerr << "Test14: More seeking: ";
    test( reader->seek( -2, G_SEEK_CUR ) && reader->tell() == 0xff );
    reader->push(); // save the current pos (0xff)

    std::cerr << "Test15: Even more seeking: ";
    test( reader->seek( -2, G_SEEK_END ) && reader->tell() == 0x20a4 );

    std::cerr << "Test16: Checking the stack: ";
    test( reader->pop() && reader->tell() == 0xff );

    std::cerr << "Test17: Checking the stack again: ";
    test( reader->pop() && reader->tell() == 0x101 );

    // clean up the current stream
    delete reader;
    reader = 0;

    std::cerr << "Test18: Open another stream for reading: ";
    reader = storage.createStreamReader( "WordDocument" );
    test( reader && reader->isValid() );

    std::cerr << "Test19: Read the magic 16 Bit value: ";
    test( reader->readU16() == 0xa5ec );

    std::cerr << "Test20: Check the nFib: ";
    test( reader->readU16() == 193 );

    std::cerr << "Test21: Check the byte reading: ";
    reader->seek( 2 );
    test( reader->readU8() == 0xc1 );

    std::cerr << "Test22: Check the word reading: ";
    reader->seek( 0 );
    test( reader->readU32() == 0x00c1a5ec );

    // Get rid of our test document
    // The warning we get is the intended behavior :)
    storage.close();

    // Open a new document for write tests (make sure
    // it doesn't exist)
    system( "rm test123456.doc &> /dev/null" );
    storage.setName( "test123456.doc" );
    test( storage.open( OLEStorage::WriteOnly ) );

    std::cerr << "Test23: Open a stream for writing (I): ";
    OLEStreamWriter* writer = storage.createStreamWriter( "Check1" );
    test( writer && writer->isValid() );

    writer->write( static_cast<U32>( 0x11111111 ) );
    writer->write( static_cast<U32>( 0x11111111 ) );
    writer->write( static_cast<U32>( 0x11111111 ) );
    writer->write( static_cast<U32>( 0x11111111 ) );
    writer->write( static_cast<U32>( 0x11111111 ) );
    writer->write( static_cast<U32>( 0x11111111 ) );
    writer->write( static_cast<U32>( 0x11111111 ) );
    writer->write( static_cast<U32>( 0x11111111 ) );
    writer->write( static_cast<U32>( 0x11111111 ) );

    // write it to disk...
    delete writer;
    writer = 0;

    std::cerr << "Test24: Open a stream for writing (II): ";
    writer = storage.createStreamWriter( "Check2" );
    test( writer && writer->isValid() );

    writer->write( static_cast<U8>( 200 ) );
    writer->write( static_cast<S8>( 123 ) );
    writer->write( static_cast<U16>( 42420 ) );
    writer->write( static_cast<S16>( -21420 ) );
    writer->write( static_cast<U32>( 0xdeadbeef ) );
    writer->write( static_cast<S32>( 0x7fffffff ) );

    // write it to disk...
    delete writer;
    writer = 0;

#ifndef SMALL_BLOCKS_ONLY
    std::cerr << "Test25: Open a stream for writing (III): ";
    writer = storage.createStreamWriter( "Check3" );
    test( writer && writer->isValid() );

    for ( int i = 0; i < 10000; ++i ) {
        writer->write( static_cast<S32>( 0x22222222 ) );
        writer->write( static_cast<S32>( 0x22222222 ) );
        writer->write( static_cast<S32>( 0x22222222 ) );
        writer->write( static_cast<S32>( 0x22222222 ) );
        writer->write( static_cast<S32>( 0x22222222 ) );
    }

    delete writer;
    writer = 0;
#endif

    std::cerr << "Test26: Open a stream for writing (IV): ";
    writer = storage.createStreamWriter( "Check4" );
    test( writer && writer->isValid() );

    srand( time( 0 ) );
    U8 buffer1[ 256 ];
    for ( int i = 0; i< 256; ++i )
        buffer1[ i ] = rand() % 256;

    writer->write( buffer1, 256 );

    delete writer;
    writer = 0;

    storage.close();

    std::cerr << "Test27: Read back the created file: ";
    test( storage.open( OLEStorage::ReadOnly ) && storage.isValid() );

    std::cerr << "Test28: Open the stream I for reading: ";
    reader = storage.createStreamReader( "Check1" );
    test( reader && reader->isValid() );

    std::cerr << "Test29: Check the size of the stream I: ";
    test( reader->size() == 36 );

    delete reader;
    reader = 0;

    std::cerr << "Test30: Open the stream II for reading: ";
    reader = storage.createStreamReader( "Check2" );
    test( reader && reader->isValid() );

    std::cerr << "Test31: Check the size of the stream II: ";
    test( reader->size() == 14 );

    std::cerr << "Test32: Check the contents of the stream II: ";
    test( reader->readU8() == 200 && reader->readS8() == 123 && reader->readU16() == 42420 &&
        reader->readS16() == -21420 && reader->readU32() == 0xdeadbeef && reader->readS32() == 0x7fffffff );

    delete reader;
    reader = 0;

    std::cerr << "Test33: Open the stream IV for reading: ";
    reader = storage.createStreamReader( "Check4" );
    test( reader && reader->isValid() );

    std::cerr << "Test34: Read back and compare the content with the expected values: ";
    U8 buffer2[ 256 ];
    reader->read( buffer2, 256 );
    bool success = true;
    for ( int i = 0; i < 256; ++i )
        if ( buffer1[ i ] != buffer2[ i ] ) {
            success = false;
            break;
        }
    test( success );

    storage.close(); // missing delete reader; intendet, doesn't result in memleaks

    std::cerr << "Done." << std::endl;
    return 0;
}
예제 #4
0
// A small testcase for the word97_helper stuff
int main( int, char** )
{
    std::cerr << "Testing some auxilliary classes..." << std::endl;

    OLEStorage storage( std::string( "testole.doc" ) );
    test( storage.open( OLEStorage::ReadOnly ) );

    OLEStreamReader* document = storage.createStreamReader( "WordDocument" );
    test( document && document->isValid(), "Error: Couldn't open the WordDocument stream" );
    //document->dumpStream( "document.stream" );

    Word97::FIB fib( document, true );

    OLEStreamReader* table = storage.createStreamReader( fib.fWhichTblStm ? "1Table" : "0Table" );
    test( table && table->isValid(), "Error: Couldn't open the Table stream" );

    // Test STTBFASSOC reading from memory
    std::cerr << "Test 1: Read the STTBFASSOC from memory: ";
    table->seek( fib.fcSttbfAssoc );
    //table->dumpStream( "table.stream" );
    U8* data = new U8[ fib.lcbSttbfAssoc ];
    table->read( data, fib.lcbSttbfAssoc );
    STTBF sttbf( 0x0400, data );
    delete [] data;
    test( sttbf.count() == 18 );

    for ( UString s = sttbf.firstString(); !s.isNull(); s = sttbf.nextString() )
        std::cerr << "String: '" << s.ascii() << "'" << std::endl;

    // Test STTBFASSOC reading from a stream
    std::cerr << "Test 2: Read the STTBFASSOC from a stream: ";
    table->seek( fib.fcSttbfAssoc );
    STTBF sttbf2( 0x0400, table );

    UString s1 = sttbf.firstString(), s2 = sttbf2.firstString();
    bool failed = false;
    for ( ; !s1.isNull() && !s2.isNull(); s1 = sttbf.nextString(), s2 = sttbf2.nextString() ) {
        if ( s1 != s2 ) {
            failed = true;
            break;
        }
    }
    test( !failed );

    // Testing PLF reading/iterating
    std::cerr << "Test 3a: Reading a PLF (LFO): ";
    table->seek( fib.fcPlfLfo );
    PLF<Word97::LFO> plf( table );
    test( plf.count() == 10 ); // we have some padding data at the end, so the size is screwed

    std::cerr << "Test 3b: Reading a PLF (LSTF, \"short count\" PLF): ";
    table->seek( fib.fcPlcfLst );
    PLF<Word97::LSTF, true> plf1( table );
    test( plf1.count() * Word97::LSTF::sizeOf + 2 == fib.lcbPlcfLst );

    std::cerr << "Test 3c: Trying to match the list IDs: ";
    // Check whether all list ids match, then the file is okay (and we read it correctly)
    // Yes, I know that this is O(n^2), but hey, this is a test case for 10 elements ;)
    bool success = true;
    bool found = false;
    for ( const Word97::LSTF* lstf = plf1.first(); lstf != 0; lstf = plf1.next() ) {
        found = false;
        for ( const Word97::LFO* lfo = plf.first(); lfo != 0; lfo = plf.next() )
            if ( lstf->lsid == lfo->lsid ) {
                found = true;
                break;
            }
        if ( !found ) {
            success = false;
            break;
        }
    }
    test( success );

    table->seek( fib.fcPlcfbtePapx );
    std::cerr << "Test 4: Reading a PLCF: " << std::endl;
    //std::cerr << "Size: " << fib.lcbPlcfbtePapx << std::endl;
    PLCF<Word97::BTE> plcf( fib.lcbPlcfbtePapx, table );

    std::cerr << "Test 4a: Checking the size of the PLCF: ";
    test( plcf.count() == 6 );

    PLCFIterator<Word97::BTE> it( plcf );
    for ( ; it.current(); ++it ) {
        std::cerr << "Item: " << std::endl;
        std::cerr << "   start: " << it.currentStart() << std::endl;
        std::cerr << "   lim: " << it.currentLim() << std::endl;
        std::cerr << "   value: " << it.current()->pn << std::endl;
    }

    // Test the FKP template
    it.toFirst();   // rewind the iterator ;)
    std::cerr << "Test 5: Reading a FKP: " << std::endl;
    document->seek( it.current()->pn << 9, G_SEEK_SET );
    FKP< BX<Word97::PHE> > fkp( document, false );
    std::cerr << "crun: " << fkp.crun() << std::endl;
    FKPIterator< BX<Word97::PHE> > it2( fkp );
    for ( int i = 0; !it2.atEnd(); ++it2, ++i ) {
        std::cerr << "Item(" << i << "): " << std::endl;
        std::cerr << "   start: " << it2.currentStart() << std::endl;
        std::cerr << "   lim: " << it2.currentLim() << std::endl;
        if ( it2.current() )
            std::cerr << "   plain entry" << std::endl;
        else
            std::cerr << "   null entry" << std::endl;
    }

    std::cerr << "sizeof(PRM): " << sizeof(Word97::PRM) << std::endl;
    std::cerr << "sizeof(PRM2): " << sizeof(Word97::PRM2) << std::endl;
    std::cerr << "sizeof(PCD): " << sizeof(Word97::PCD) << std::endl;
    std::cerr << "sizeof(DTTM): " << sizeof(Word97::DTTM) << std::endl;
    std::cerr << "sizeof(BTE): " << sizeof(Word97::BTE) << std::endl;
    std::cerr << "sizeof(PHE): " << sizeof(Word97::PHE) << std::endl;
    std::cerr << "sizeof(BX): " << sizeof(BX<Word97::PHE>) << std::endl;

    delete document;
    delete table;
    std::cerr << "Done." << std::endl;
    return 0;
}
예제 #5
0
	void parseRecord(int rec_type, long rec_len, OLEStreamReader& reader, std::string& text)
	{
		switch(rec_type)
		{
			case RT_CSTRING:
			case RT_TEXT_CHARS_ATOM: 
			{
				if (m_verbose_logging)
					*m_log_stream << "RT_TextCharsAtom or RT_CString\n";
				std::vector<unsigned char> buf(2);
				long text_len = rec_len / 2;
				for (int i = 0; i < text_len; i++)
				{
					reader.read((U8*)&*buf.begin(), 2);
					U16 u = getU16LittleEndian(buf.begin());
					if (u != 0x0D)
						text += unicodeCharToUTF8(u);
					else
						text += '\n';
				}
				text += '\n';
				break;
			}
			case RT_DOCUMENT:
				if (m_verbose_logging)
					*m_log_stream << "RT_Document\n";
				break;
			case RT_DRAWING:
				if (m_verbose_logging)
					*m_log_stream << "RT_Drawing\n";
				break;
			case RT_END_DOCUMENT_ATOM:
				if (m_verbose_logging)
					*m_log_stream << "RT_DocumentEnd\n";
				reader.seek(rec_len, G_SEEK_CUR);
				break;
			case RT_LIST:
				if (m_verbose_logging)
					*m_log_stream << "RT_List\n";
				break;
			case RT_MAIN_MASTER:
				if (m_verbose_logging)
					*m_log_stream << "RT_MainMaster\n";
				#warning TODO: Make extracting text from main master slide configurable
				reader.seek(rec_len, G_SEEK_CUR);
				break;
			case RT_SLIDE:
				if (m_verbose_logging)
					*m_log_stream << "RT_Slide\n";
				break;
			case RT_SLIDE_BASE:
				break;
			case RT_SLIDE_LIST_WITH_TEXT:
				if (m_verbose_logging)
					*m_log_stream << "RT_SlideListWithText\n";
				break;
			case RT_TEXT_BYTES_ATOM:
			{
				if (m_verbose_logging)
					*m_log_stream << "RT_TextBytesAtom\n";
				std::vector<unsigned char> buf(2);
				for (int i = 0; i < rec_len; i++)
				{
					reader.read((U8*)&*buf.begin(), 1);
					if (buf[0] != 0x0D)
						text += unicodeCharToUTF8(buf[0]);
					else
						text += '\n';
				}
				text += '\n';
				break;
			}
			case OFFICE_ART_CLIENT_TEXTBOX:
				if (m_verbose_logging)
					*m_log_stream << "OfficeArtClientTextbox\n";
				break;
			case OFFICE_ART_DG_CONTAINER:
				if (m_verbose_logging)
					*m_log_stream << "OfficeArtDgContainer\n";
				break;
			case OFFICE_ART_SPGR_CONTAINER:
				if (m_verbose_logging)
					*m_log_stream << "OfficeArtSpgrContainer\n";
				break;
			case OFFICE_ART_SP_CONTAINER:
				if (m_verbose_logging)
					*m_log_stream << "OfficeArtSpContainer\n";
				break;
			default:
				reader.seek(rec_len, G_SEEK_CUR);
		}
	}
예제 #6
0
	bool oleEof(OLEStreamReader& reader)
	{
		return reader.tell() == reader.size();
	}