/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"
#include <com/sun/star/embed/XTransactedObject.hpp>
#ifndef _COM_SUN_STAR_EMBED_ElementModes_HPP_
#include <com/sun/star/embed/ElementModes.hpp>
#endif
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <cppuhelper/compbase4.hxx>

#include <unotools/ucbstreamhelper.hxx>
#include <unotools/streamwrap.hxx>
#include <unotools/tempfile.hxx>
#include <tools/debug.hxx>
#include <vcl/cvtgrf.hxx>
#include <vcl/gfxlink.hxx>
#include <vcl/metaact.hxx>
#include <tools/zcodec.hxx>

#include "svtools/filter.hxx"
#include "svx/xmlgrhlp.hxx"

#include <algorithm>

// -----------
// - Defines -
// -----------

using namespace com::sun::star;
using namespace com::sun::star::uno;
using namespace com::sun::star::io;

using ::com::sun::star::lang::XMultiServiceFactory;

#define XML_GRAPHICSTORAGE_NAME		"Pictures"
#define XML_PACKAGE_URL_BASE		"vnd.sun.star.Package:"
#define XML_GRAPHICOBJECT_URL_BASE	"vnd.sun.star.GraphicObject:"

// ---------------------------
// - SvXMLGraphicInputStream -
// ---------------------------

const MetaCommentAction* ImplCheckForEPS( GDIMetaFile& rMtf )
{
	static ByteString aComment( (const sal_Char*)"EPSReplacementGraphic" );
	const MetaCommentAction* pComment = NULL;

	if ( ( rMtf.GetActionCount() >= 2 )
			&& ( rMtf.FirstAction()->GetType() == META_EPS_ACTION )
			&& ( ((const MetaAction*)rMtf.GetAction( 1 ))->GetType() == META_COMMENT_ACTION )
			&& ( ((const MetaCommentAction*)rMtf.GetAction( 1 ))->GetComment() == aComment ) )
		pComment = (const MetaCommentAction*)rMtf.GetAction( 1 );

	return pComment;
}

class SvXMLGraphicInputStream : public::cppu::WeakImplHelper1< XInputStream >
{
private:

    virtual sal_Int32	SAL_CALL	readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) throw(NotConnectedException, BufferSizeExceededException, RuntimeException);
	virtual sal_Int32	SAL_CALL	readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) throw(NotConnectedException, BufferSizeExceededException, RuntimeException);
	virtual void		SAL_CALL	skipBytes(sal_Int32 nBytesToSkip) throw(NotConnectedException, BufferSizeExceededException, RuntimeException);
	virtual sal_Int32	SAL_CALL	available() throw(NotConnectedException, RuntimeException);
	virtual void		SAL_CALL	closeInput() throw(NotConnectedException, RuntimeException);

private:

    ::utl::TempFile                 maTmp;
    Reference< XInputStream >       mxStmWrapper;

                                    // not available
                                    SvXMLGraphicInputStream();
                                    SvXMLGraphicInputStream( const SvXMLGraphicInputStream& );
    SvXMLGraphicInputStream&        operator==( SvXMLGraphicInputStream& );

public:

                                    SvXMLGraphicInputStream( const ::rtl::OUString& rGraphicId );
    virtual                         ~SvXMLGraphicInputStream();

    sal_Bool                        Exists() const { return mxStmWrapper.is(); }
};

// -----------------------------------------------------------------------------

SvXMLGraphicInputStream::SvXMLGraphicInputStream( const ::rtl::OUString& rGraphicId )
{
	String			aGraphicId( rGraphicId );
	GraphicObject	aGrfObject( ByteString( aGraphicId, RTL_TEXTENCODING_ASCII_US ) );

    maTmp.EnableKillingFile();

	if( aGrfObject.GetType() != GRAPHIC_NONE )
	{
        SvStream* pStm = ::utl::UcbStreamHelper::CreateStream( maTmp.GetURL(), STREAM_WRITE | STREAM_TRUNC );

        if( pStm )
        {
			Graphic			aGraphic( (Graphic&) aGrfObject.GetGraphic() );
			const GfxLink	aGfxLink( aGraphic.GetLink() );
            sal_Bool        bRet = sal_False;

			if( aGfxLink.GetDataSize() && aGfxLink.GetData() )
            {
				pStm->Write( aGfxLink.GetData(), aGfxLink.GetDataSize() );
			    bRet = ( pStm->GetError() == 0 );
            }
			else
			{
				if( aGraphic.GetType() == GRAPHIC_BITMAP )
				{
					GraphicFilter*  pFilter = GraphicFilter::GetGraphicFilter();
                    String          aFormat;

					if( aGraphic.IsAnimated() )
						aFormat = String( RTL_CONSTASCII_USTRINGPARAM( "gif" ) );
					else
						aFormat = String( RTL_CONSTASCII_USTRINGPARAM( "png" ) );

					bRet = ( pFilter->ExportGraphic( aGraphic, String(), *pStm, pFilter->GetExportFormatNumberForShortName( aFormat ) ) == 0 );
				}
				else if( aGraphic.GetType() == GRAPHIC_GDIMETAFILE )
				{
					pStm->SetVersion( SOFFICE_FILEFORMAT_8 );
					pStm->SetCompressMode( COMPRESSMODE_ZBITMAP );
					( (GDIMetaFile&) aGraphic.GetGDIMetaFile() ).Write( *pStm );
    			    bRet = ( pStm->GetError() == 0 );
				}
			}

            if( bRet )
            {
                pStm->Seek( 0 );
                mxStmWrapper = new ::utl::OInputStreamWrapper( pStm, sal_True );
            }
            else
                delete pStm;
        }
    }
}

// -----------------------------------------------------------------------------

SvXMLGraphicInputStream::~SvXMLGraphicInputStream()
{
}

// -----------------------------------------------------------------------------

sal_Int32 SAL_CALL SvXMLGraphicInputStream::readBytes( Sequence< sal_Int8 >& rData, sal_Int32 nBytesToRead )
    throw( NotConnectedException, BufferSizeExceededException, RuntimeException )
{
    if( !mxStmWrapper.is() )
        throw NotConnectedException();

    return mxStmWrapper->readBytes( rData, nBytesToRead );
}

// -----------------------------------------------------------------------------

sal_Int32 SAL_CALL SvXMLGraphicInputStream::readSomeBytes( Sequence< sal_Int8 >& rData, sal_Int32 nMaxBytesToRead )
    throw( NotConnectedException, BufferSizeExceededException, RuntimeException )
{
    if( !mxStmWrapper.is() )
        throw NotConnectedException() ;

    return mxStmWrapper->readSomeBytes( rData, nMaxBytesToRead );
}

// -----------------------------------------------------------------------------

void SAL_CALL SvXMLGraphicInputStream::skipBytes( sal_Int32 nBytesToSkip )
    throw( NotConnectedException, BufferSizeExceededException, RuntimeException )
{
    if( !mxStmWrapper.is() )
        throw NotConnectedException() ;

    mxStmWrapper->skipBytes( nBytesToSkip );
}

// -----------------------------------------------------------------------------

sal_Int32 SAL_CALL SvXMLGraphicInputStream::available() throw( NotConnectedException, RuntimeException )
{
    if( !mxStmWrapper.is() )
        throw NotConnectedException() ;

    return mxStmWrapper->available();
}

// -----------------------------------------------------------------------------

void SAL_CALL SvXMLGraphicInputStream::closeInput() throw( NotConnectedException, RuntimeException )
{
    if( !mxStmWrapper.is() )
        throw NotConnectedException() ;

    mxStmWrapper->closeInput();
}

// ----------------------------
// - SvXMLGraphicOutputStream -
// ----------------------------

class SvXMLGraphicOutputStream : public::cppu::WeakImplHelper1< XOutputStream >
{
private:

    // XOutputStream
    virtual void SAL_CALL           writeBytes( const Sequence< sal_Int8 >& rData ) throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
    virtual void SAL_CALL           flush() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );
    virtual void SAL_CALL           closeOutput() throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException );

private:

    ::utl::TempFile*                mpTmp;
    SvStream*                       mpOStm;
    Reference< XOutputStream >      mxStmWrapper;
    GraphicObject                   maGrfObj;
    sal_Bool                        mbClosed;

                                    // not available
                                    SvXMLGraphicOutputStream( const SvXMLGraphicOutputStream& );
    SvXMLGraphicOutputStream&       operator==( SvXMLGraphicOutputStream& );

public:

                                    SvXMLGraphicOutputStream();
    virtual                         ~SvXMLGraphicOutputStream();

    sal_Bool                        Exists() const { return mxStmWrapper.is(); }
    const GraphicObject&            GetGraphicObject();
};

// -----------------------------------------------------------------------------

SvXMLGraphicOutputStream::SvXMLGraphicOutputStream() :
    mpTmp( new ::utl::TempFile ),
    mbClosed( sal_False )
{
    mpTmp->EnableKillingFile();

    mpOStm = ::utl::UcbStreamHelper::CreateStream( mpTmp->GetURL(), STREAM_WRITE | STREAM_TRUNC );

    if( mpOStm )
        mxStmWrapper = new ::utl::OOutputStreamWrapper( *mpOStm );
}

// -----------------------------------------------------------------------------

SvXMLGraphicOutputStream::~SvXMLGraphicOutputStream()
{
    delete mpTmp;
    delete mpOStm;
}

// -----------------------------------------------------------------------------

void SAL_CALL SvXMLGraphicOutputStream::writeBytes( const Sequence< sal_Int8 >& rData )
    throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
{
    if( !mxStmWrapper.is() )
        throw NotConnectedException() ;

    mxStmWrapper->writeBytes( rData );
}

// -----------------------------------------------------------------------------

void SAL_CALL SvXMLGraphicOutputStream::flush()
    throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
{
    if( !mxStmWrapper.is() )
        throw NotConnectedException() ;

    mxStmWrapper->flush();
}

// -----------------------------------------------------------------------------

void SAL_CALL SvXMLGraphicOutputStream::closeOutput()
    throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException )
{
    if( !mxStmWrapper.is() )
        throw NotConnectedException() ;

    mxStmWrapper->closeOutput();
    mxStmWrapper = Reference< XOutputStream >();

    mbClosed = sal_True;
}

// ------------------------------------------------------------------------------

const GraphicObject& SvXMLGraphicOutputStream::GetGraphicObject()
{
    if( mbClosed && ( maGrfObj.GetType() == GRAPHIC_NONE ) && mpOStm )
    {
    	Graphic aGraphic;

        mpOStm->Seek( 0 );
		sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW;
		sal_uInt16 pDeterminedFormat = GRFILTER_FORMAT_DONTKNOW;
        GraphicFilter::GetGraphicFilter()->ImportGraphic( aGraphic, String(), *mpOStm ,nFormat,&pDeterminedFormat );

		if (pDeterminedFormat == GRFILTER_FORMAT_DONTKNOW)
		{
			//Read the first two byte to check whether it is a gzipped stream, is so it may be in wmz or emz format
			//unzip them and try again

			sal_uInt8    sFirstBytes[ 2 ];

			mpOStm->Seek( STREAM_SEEK_TO_END );
			sal_uIntPtr nStreamLen = mpOStm->Tell();
			mpOStm->Seek( 0 );

			if ( !nStreamLen )
			{
				SvLockBytes* pLockBytes = mpOStm->GetLockBytes();
				if ( pLockBytes  )
					pLockBytes->SetSynchronMode( sal_True );

				mpOStm->Seek( STREAM_SEEK_TO_END );
				nStreamLen = mpOStm->Tell();
				mpOStm->Seek( 0 );
			}
			if( nStreamLen >= 2 )
			{
				//read two byte
				mpOStm->Read( sFirstBytes, 2 );

				if( sFirstBytes[0] == 0x1f && sFirstBytes[1] == 0x8b )
				{
					SvMemoryStream* pDest = new SvMemoryStream;
					ZCodec aZCodec( 0x8000, 0x8000 );
					aZCodec.BeginCompression(ZCODEC_GZ_LIB);
					mpOStm->Seek( 0 );
					aZCodec.Decompress( *mpOStm, *pDest );

					if (aZCodec.EndCompression() && pDest )
					{
						pDest->Seek( STREAM_SEEK_TO_END );
						sal_uIntPtr nStreamLen_ = pDest->Tell();
						if (nStreamLen_)
						{
							pDest->Seek(0L);
					        GraphicFilter::GetGraphicFilter()->ImportGraphic( aGraphic, String(), *pDest ,nFormat,&pDeterminedFormat );
						}
					}
					delete pDest;
				}
			}
		}

		maGrfObj = aGraphic;
        if( maGrfObj.GetType() != GRAPHIC_NONE )
	    {
		    delete mpOStm, mpOStm = NULL;
			delete mpTmp, mpTmp = NULL;
		}
    }

    return maGrfObj;
}

// ----------------------
// - SvXMLGraphicHelper -
// ----------------------

SvXMLGraphicHelper::SvXMLGraphicHelper( SvXMLGraphicHelperMode eCreateMode ) :
	::cppu::WeakComponentImplHelper2< ::com::sun::star::document::XGraphicObjectResolver,
                                      ::com::sun::star::document::XBinaryStreamResolver >( maMutex )
{
	Init( NULL, eCreateMode, sal_False );
}

SvXMLGraphicHelper::SvXMLGraphicHelper() :
	::cppu::WeakComponentImplHelper2< ::com::sun::star::document::XGraphicObjectResolver,
                                      ::com::sun::star::document::XBinaryStreamResolver >( maMutex )
{
}

// -----------------------------------------------------------------------------

SvXMLGraphicHelper::~SvXMLGraphicHelper()
{
}

// -----------------------------------------------------------------------------

void SAL_CALL SvXMLGraphicHelper::disposing()
{
}

// -----------------------------------------------------------------------------

sal_Bool SvXMLGraphicHelper::ImplGetStreamNames( const ::rtl::OUString& rURLStr,
												 ::rtl::OUString& rPictureStorageName,
												 ::rtl::OUString& rPictureStreamName )
{
	String		aURLStr( rURLStr );
	sal_Bool	bRet = sal_False;

	if( aURLStr.Len() )
	{
		aURLStr = aURLStr.GetToken( aURLStr.GetTokenCount( ':' ) - 1, ':' );
		const sal_uInt32 nTokenCount = aURLStr.GetTokenCount( '/' );

		if( 1 == nTokenCount )
		{
			rPictureStorageName = String( RTL_CONSTASCII_USTRINGPARAM( XML_GRAPHICSTORAGE_NAME ) );
			rPictureStreamName = aURLStr;
			bRet = sal_True;
		}
		else if( 2 == nTokenCount )
		{
			rPictureStorageName = aURLStr.GetToken( 0, '/' );

			DBG_ASSERT( rPictureStorageName.getLength() &&
					   rPictureStorageName.getStr()[ 0 ] != '#',
					   "invalid relative URL" );

			rPictureStreamName = aURLStr.GetToken( 1, '/' );
			bRet = sal_True;
		}
		else
		{
			DBG_ERROR( "SvXMLGraphicHelper::ImplInsertGraphicURL: invalid scheme" );
		}
	}

	return bRet;
}

// -----------------------------------------------------------------------------

uno::Reference < embed::XStorage > SvXMLGraphicHelper::ImplGetGraphicStorage( const ::rtl::OUString& rStorageName )
{
    uno::Reference < embed::XStorage > xRetStorage;
    if( mxRootStorage.is() )
	{
        try
        {
            xRetStorage = mxRootStorage->openStorageElement(
                maCurStorageName = rStorageName,
                ( GRAPHICHELPER_MODE_WRITE == meCreateMode )
                    ? embed::ElementModes::READWRITE
                    : embed::ElementModes::READ );
        }
        catch ( uno::Exception& )
        {
        }
        //#i43196# try again to open the storage element - this time readonly
        if(!xRetStorage.is())
        {
            try
            {
                xRetStorage = mxRootStorage->openStorageElement( maCurStorageName = rStorageName, embed::ElementModes::READ );
            }
            catch ( uno::Exception& )
            {
            }
        }
    }

	return xRetStorage;
}

// -----------------------------------------------------------------------------

SvxGraphicHelperStream_Impl SvXMLGraphicHelper::ImplGetGraphicStream( const ::rtl::OUString& rPictureStorageName,
															  const ::rtl::OUString& rPictureStreamName,
															  sal_Bool bTruncate )
{
    SvxGraphicHelperStream_Impl aRet;
    aRet.xStorage = ImplGetGraphicStorage( rPictureStorageName );

    if( aRet.xStorage.is() )
	{
        sal_Int32 nMode = embed::ElementModes::READ;
        if ( GRAPHICHELPER_MODE_WRITE == meCreateMode )
        {
            nMode = embed::ElementModes::READWRITE;
            if ( bTruncate )
                nMode |= embed::ElementModes::TRUNCATE;
        }

        aRet.xStream = aRet.xStorage->openStreamElement( rPictureStreamName, nMode );
        if( aRet.xStream.is() && ( GRAPHICHELPER_MODE_WRITE == meCreateMode ) )
		{
//REMOVE				::rtl::OUString aPropName( RTL_CONSTASCII_USTRINGPARAM("Encrypted") );
			::rtl::OUString aPropName( RTL_CONSTASCII_USTRINGPARAM("UseCommonStoragePasswordEncryption") );
            uno::Reference < beans::XPropertySet > xProps( aRet.xStream, uno::UNO_QUERY );
            xProps->setPropertyValue( aPropName, uno::makeAny( sal_True) );
		}
	}

    return aRet;
}

// -----------------------------------------------------------------------------

String SvXMLGraphicHelper::ImplGetGraphicMimeType( const String& rFileName ) const
{
    struct XMLGraphicMimeTypeMapper
    {
	    const char*	pExt;
	    const char*	pMimeType;
    };

    static XMLGraphicMimeTypeMapper aMapper[] =
    {
        { "gif", "image/gif" },
        { "png", "image/png" },
        { "jpg", "image/jpeg" },
        { "tif", "image/tiff" },
        { "svg", "image/svg+xml" }
    };

    String aMimeType;

    if( ( rFileName.Len() >= 4 ) && ( rFileName.GetChar( rFileName.Len() - 4 ) == '.' ) )
    {
        const ByteString aExt( rFileName.Copy( rFileName.Len() - 3 ), RTL_TEXTENCODING_ASCII_US );

        for( long i = 0, nCount = sizeof( aMapper ) / sizeof( aMapper[ 0 ] ); ( i < nCount ) && !aMimeType.Len(); i++ )
            if( aExt == aMapper[ i ].pExt )
                aMimeType = String( aMapper[ i ].pMimeType, RTL_TEXTENCODING_ASCII_US );
    }

    return aMimeType;
}

// -----------------------------------------------------------------------------

Graphic SvXMLGraphicHelper::ImplReadGraphic( const ::rtl::OUString& rPictureStorageName,
											 const ::rtl::OUString& rPictureStreamName )
{
	Graphic				aGraphic;
    SvxGraphicHelperStream_Impl aStream( ImplGetGraphicStream( rPictureStorageName, rPictureStreamName, sal_False ) );
    if( aStream.xStream.is() )
    {
        SvStream* pStream = utl::UcbStreamHelper::CreateStream( aStream.xStream );
        GraphicFilter::GetGraphicFilter()->ImportGraphic( aGraphic, String(), *pStream );
        delete pStream;
    }

	return aGraphic;
}

// -----------------------------------------------------------------------------

sal_Bool SvXMLGraphicHelper::ImplWriteGraphic( const ::rtl::OUString& rPictureStorageName,
											   const ::rtl::OUString& rPictureStreamName,
											   const ::rtl::OUString& rGraphicId )
{
	String			aGraphicId( rGraphicId );
	GraphicObject	aGrfObject( ByteString( aGraphicId, RTL_TEXTENCODING_ASCII_US ) );
	sal_Bool		bRet = sal_False;

	if( aGrfObject.GetType() != GRAPHIC_NONE )
	{
        SvxGraphicHelperStream_Impl aStream( ImplGetGraphicStream( rPictureStorageName, rPictureStreamName, sal_False ) );
        if( aStream.xStream.is() )
        {
			Graphic			aGraphic( (Graphic&) aGrfObject.GetGraphic() );
			const GfxLink	aGfxLink( aGraphic.GetLink() );
            const ::rtl::OUString  aMimeType( ImplGetGraphicMimeType( rPictureStreamName ) );
            uno::Any        aAny;
            uno::Reference < beans::XPropertySet > xProps( aStream.xStream, uno::UNO_QUERY );

            // set stream properties (MediaType/Compression)
            if( aMimeType.getLength() )
            {
	            aAny <<= aMimeType;
                xProps->setPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), aAny );
            }

            const sal_Bool bCompressed = ( ( 0 == aMimeType.getLength() ) || ( aMimeType == ::rtl::OUString::createFromAscii( "image/tiff" ) ) );
            aAny <<= bCompressed;
            xProps->setPropertyValue( String( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) ), aAny );

            SvStream* pStream = utl::UcbStreamHelper::CreateStream( aStream.xStream );
			if( aGfxLink.GetDataSize() && aGfxLink.GetData() )
                pStream->Write( aGfxLink.GetData(), aGfxLink.GetDataSize() );
			else
			{
				if( aGraphic.GetType() == GRAPHIC_BITMAP )
				{
					GraphicFilter*  pFilter = GraphicFilter::GetGraphicFilter();
                    String          aFormat;

					if( aGraphic.IsAnimated() )
						aFormat = String( RTL_CONSTASCII_USTRINGPARAM( "gif" ) );
					else
						aFormat = String( RTL_CONSTASCII_USTRINGPARAM( "png" ) );

                    bRet = ( pFilter->ExportGraphic( aGraphic, String(), *pStream,
													 pFilter->GetExportFormatNumberForShortName( aFormat ) ) == 0 );
				}
				else if( aGraphic.GetType() == GRAPHIC_GDIMETAFILE )
				{
					pStream->SetVersion( SOFFICE_FILEFORMAT_8 );
					pStream->SetCompressMode( COMPRESSMODE_ZBITMAP );

					// SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm
					GDIMetaFile& rMtf( (GDIMetaFile&)aGraphic.GetGDIMetaFile() );
					const MetaCommentAction* pComment = ImplCheckForEPS( rMtf );
					if ( pComment )
					{
						sal_uInt32	nSize = pComment->GetDataSize();
						const sal_uInt8* pData = pComment->GetData();
						if ( nSize && pData )
							pStream->Write( pData, nSize );

						const MetaEPSAction* pAct = ( (const MetaEPSAction*)rMtf.FirstAction() );
						const GfxLink&		 rLink = pAct->GetLink();

						pStream->Write( rLink.GetData(), rLink.GetDataSize() );
					}
					else
						rMtf.Write( *pStream );

					bRet = ( pStream->GetError() == 0 );
				}
			}
            uno::Reference < embed::XTransactedObject > xStorage(
                                    aStream.xStorage, uno::UNO_QUERY);
            delete pStream;
            aStream.xStream->getOutputStream()->closeOutput();
            if( xStorage.is() )
                xStorage->commit();
		}
	}

	return bRet;
}

// -----------------------------------------------------------------------------

void SvXMLGraphicHelper::ImplInsertGraphicURL( const ::rtl::OUString& rURLStr, sal_uInt32 nInsertPos, rtl::OUString& rRequestedFileName )
{
	rtl::OUString aURLString( rURLStr );
	::rtl::OUString	aPictureStorageName, aPictureStreamName;
	if( ( maURLSet.find( aURLString ) != maURLSet.end() ) )
	{
		URLPairVector::iterator aIter( maGrfURLs.begin() ), aEnd( maGrfURLs.end() );
		while( aIter != aEnd )
		{
			if( aURLString == (*aIter).first )
			{
				maGrfURLs[ nInsertPos ].second = (*aIter).second;
				aIter = aEnd;
			}
			else
				aIter++;
		}
	}
	else if( ImplGetStreamNames( aURLString, aPictureStorageName, aPictureStreamName ) )
	{
		URLPair& rURLPair = maGrfURLs[ nInsertPos ];

		if( GRAPHICHELPER_MODE_READ == meCreateMode )
		{
			const GraphicObject aObj( ImplReadGraphic( aPictureStorageName, aPictureStreamName ) );

			if( aObj.GetType() != GRAPHIC_NONE )
			{
				const static ::rtl::OUString aBaseURL( RTL_CONSTASCII_USTRINGPARAM( XML_GRAPHICOBJECT_URL_BASE ) );

				maGrfObjs.push_back( aObj );
				rURLPair.second = aBaseURL;
				rURLPair.second += String( aObj.GetUniqueID().GetBuffer(), RTL_TEXTENCODING_ASCII_US );
			}
			else
				rURLPair.second = String();
		}
		else
		{
			const String		aGraphicObjectId( aPictureStreamName );
            const ByteString    aAsciiObjectID( aGraphicObjectId, RTL_TEXTENCODING_ASCII_US );
			const GraphicObject	aGrfObject( aAsciiObjectID );
			if( aGrfObject.GetType() != GRAPHIC_NONE )
			{
				String			aStreamName( aGraphicObjectId );
				Graphic			aGraphic( (Graphic&) aGrfObject.GetGraphic() );
				const GfxLink	aGfxLink( aGraphic.GetLink() );
				String			aExtension;

				if( aGfxLink.GetDataSize() )
				{
					switch( aGfxLink.GetType() )
					{
						case( GFX_LINK_TYPE_EPS_BUFFER ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".eps" ) ); break;
						case( GFX_LINK_TYPE_NATIVE_GIF ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".gif" ) ); break;
						case( GFX_LINK_TYPE_NATIVE_JPG ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".jpg" ) ); break;
						case( GFX_LINK_TYPE_NATIVE_PNG ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".png" ) ); break;
						case( GFX_LINK_TYPE_NATIVE_TIF ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".tif" ) ); break;
						case( GFX_LINK_TYPE_NATIVE_WMF ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".wmf" ) ); break;
						case( GFX_LINK_TYPE_NATIVE_MET ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".met" ) ); break;
						case( GFX_LINK_TYPE_NATIVE_PCT ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".pct" ) ); break;
						case( GFX_LINK_TYPE_NATIVE_SVG ): aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".svg" ) ); break;

						default:
							aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".grf" ) );
						break;
					}
				}
				else
				{
					if( aGrfObject.GetType() == GRAPHIC_BITMAP )
					{
						if( aGrfObject.IsAnimated() )
							aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".gif" ) );
						else
							aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".png" ) );
					}
					else if( aGrfObject.GetType() == GRAPHIC_GDIMETAFILE )
					{
						// SJ: first check if this metafile is just a eps file, then we will store the eps instead of svm
						GDIMetaFile& rMtf( (GDIMetaFile&)aGraphic.GetGDIMetaFile() );
						if ( ImplCheckForEPS( rMtf ) )
							aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".eps" ) );
						else
							aExtension = String( RTL_CONSTASCII_USTRINGPARAM( ".svm" ) );
					}
				}

				rtl::OUString aURLEntry;
				const String sPictures( RTL_CONSTASCII_USTRINGPARAM( "Pictures/" ) );

				if ( rRequestedFileName.getLength() )
				{
					aURLEntry = sPictures;
					aURLEntry += rRequestedFileName;
					aURLEntry += aExtension;

					URLPairVector::iterator aIter( maGrfURLs.begin() ), aEnd( maGrfURLs.end() );
					while( aIter != aEnd )
					{
						if( aURLEntry == (*aIter).second )
							break;
						aIter++;
					}
					if ( aIter == aEnd )
						aStreamName = rRequestedFileName;
				}

				aStreamName += aExtension;

				if( mbDirect && aStreamName.Len() )
					ImplWriteGraphic( aPictureStorageName, aStreamName, aGraphicObjectId );

				rURLPair.second = sPictures;
				rURLPair.second += aStreamName;
			}
#if OSL_DEBUG_LEVEL > 0
            else
            {
                ByteString sMessage = "graphic object with ID '";
                sMessage += aAsciiObjectID;
                sMessage += "' has an unknown type";
                OSL_ENSURE( false, sMessage.GetBuffer() );
            }
#endif
		}

		maURLSet.insert( aURLString );
	}
}

// -----------------------------------------------------------------------------

void SvXMLGraphicHelper::Init( const uno::Reference < embed::XStorage >& rXMLStorage,
							   SvXMLGraphicHelperMode eCreateMode,
							   sal_Bool bDirect )
{
    mxRootStorage = rXMLStorage;
	meCreateMode = eCreateMode;
	mbDirect = ( ( GRAPHICHELPER_MODE_READ == meCreateMode ) ? bDirect : sal_True );
}

// -----------------------------------------------------------------------------

SvXMLGraphicHelper* SvXMLGraphicHelper::Create( const uno::Reference < embed::XStorage >& rXMLStorage,
												SvXMLGraphicHelperMode eCreateMode,
												sal_Bool bDirect )
{
	SvXMLGraphicHelper* pThis = new SvXMLGraphicHelper;

	pThis->acquire();
    pThis->Init( rXMLStorage, eCreateMode, bDirect );

	return pThis;
}

// -----------------------------------------------------------------------------

SvXMLGraphicHelper*	SvXMLGraphicHelper::Create( SvXMLGraphicHelperMode eCreateMode )
{
	SvXMLGraphicHelper* pThis = new SvXMLGraphicHelper;

	pThis->acquire();
	pThis->Init( NULL, eCreateMode, sal_False );

	return pThis;
}

// -----------------------------------------------------------------------------

void SvXMLGraphicHelper::Destroy( SvXMLGraphicHelper* pSvXMLGraphicHelper )
{
	if( pSvXMLGraphicHelper )
	{
		pSvXMLGraphicHelper->dispose();
		pSvXMLGraphicHelper->release();
	}
}

// -----------------------------------------------------------------------------

// XGraphicObjectResolver
::rtl::OUString SAL_CALL SvXMLGraphicHelper::resolveGraphicObjectURL( const ::rtl::OUString& rURL )
	throw(uno::RuntimeException)
{
	::osl::MutexGuard   aGuard( maMutex );
	const sal_Int32     nIndex = maGrfURLs.size();

	rtl::OUString aURL( rURL );
	rtl::OUString aUserData;
	rtl::OUString aRequestedFileName;

	sal_Int32 nUser = rURL.indexOf( '?', 0 );
	if ( nUser >= 0 )
	{
		aURL = rtl::OUString( rURL.copy( 0, nUser ) );
		nUser++;
		aUserData = rURL.copy( nUser, rURL.getLength() - nUser );
	}
	if ( aUserData.getLength() )
	{
        sal_Int32 nIndex2 = 0;
        do
        {
			rtl::OUString aToken = aUserData.getToken( 0, ';', nIndex2 );
			sal_Int32 n = aToken.indexOf( '=' );
			if ( ( n > 0 ) && ( ( n + 1 ) < aToken.getLength() ) )
			{
				rtl::OUString aParam( aToken.copy( 0, n ) );
				rtl::OUString aValue( aToken.copy( n + 1, aToken.getLength() - ( n + 1 ) ) );

				const rtl::OUString sRequestedName( RTL_CONSTASCII_USTRINGPARAM("requestedName") );
				if ( aParam.match( sRequestedName ) )
					aRequestedFileName = aValue;
			}
        }
        while ( nIndex2 >= 0 );
	}

    maGrfURLs.push_back( ::std::make_pair( aURL, ::rtl::OUString() ) );
	ImplInsertGraphicURL( aURL, nIndex, aRequestedFileName );

    return maGrfURLs[ nIndex ].second;
}

// -----------------------------------------------------------------------------

// XBinaryStreamResolver
Reference< XInputStream > SAL_CALL SvXMLGraphicHelper::getInputStream( const ::rtl::OUString& rURL )
    throw( RuntimeException )
{
    Reference< XInputStream >   xRet;
    ::rtl::OUString                    aPictureStorageName, aGraphicId;


	if( ( GRAPHICHELPER_MODE_WRITE == meCreateMode ) &&
        ImplGetStreamNames( rURL, aPictureStorageName, aGraphicId ) )
    {
        SvXMLGraphicInputStream* pInputStream = new SvXMLGraphicInputStream( aGraphicId );

        if( pInputStream->Exists() )
            xRet = pInputStream;
        else
            delete pInputStream;
    }

    return xRet;
}

// -----------------------------------------------------------------------------

Reference< XOutputStream > SAL_CALL SvXMLGraphicHelper::createOutputStream()
    throw( RuntimeException )
{
    Reference< XOutputStream > xRet;

	if( GRAPHICHELPER_MODE_READ == meCreateMode )
    {
        SvXMLGraphicOutputStream* pOutputStream = new SvXMLGraphicOutputStream;

        if( pOutputStream->Exists() )
            maGrfStms.push_back( xRet = pOutputStream );
        else
            delete pOutputStream;
    }

    return xRet;
}

// -----------------------------------------------------------------------------

::rtl::OUString SAL_CALL SvXMLGraphicHelper::resolveOutputStream( const Reference< XOutputStream >& rxBinaryStream )
    throw( RuntimeException )
{
    ::rtl::OUString aRet;

	if( ( GRAPHICHELPER_MODE_READ == meCreateMode ) && rxBinaryStream.is() )
    {
        if( ::std::find( maGrfStms.begin(), maGrfStms.end(), rxBinaryStream ) != maGrfStms.end() )
        {
            SvXMLGraphicOutputStream* pOStm = static_cast< SvXMLGraphicOutputStream* >( rxBinaryStream.get() );

            if( pOStm )
            {
                const GraphicObject&    rGrfObj = pOStm->GetGraphicObject();
                const ::rtl::OUString          aId( ::rtl::OUString::createFromAscii( rGrfObj.GetUniqueID().GetBuffer() ) );

                if( aId.getLength() )
                {
                    aRet = ::rtl::OUString::createFromAscii( XML_GRAPHICOBJECT_URL_BASE );
                    aRet += aId;
                }
            }
        }
    }

    return aRet;
}


// --------------------------------------------------------------------------------

// for instantiation via service manager
namespace svx
{

namespace impl
{
typedef ::cppu::WeakComponentImplHelper4<
        lang::XInitialization,
        document::XGraphicObjectResolver,
        document::XBinaryStreamResolver,
        lang::XServiceInfo >
    SvXMLGraphicImportExportHelper_Base;
class MutexContainer
{
public:
    virtual ~MutexContainer();

protected:
    mutable ::osl::Mutex m_aMutex;
};
MutexContainer::~MutexContainer()
{}
} // namespace impl

class SvXMLGraphicImportExportHelper :
    public impl::MutexContainer,
    public impl::SvXMLGraphicImportExportHelper_Base
{
public:
    SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode );

protected:
    // is called from WeakComponentImplHelper when XComponent::dispose() was
    // called from outside
    virtual void SAL_CALL disposing();

    // ____ XInitialization ____
    // one argument is allowed, which is the XStorage
    virtual void SAL_CALL initialize( const Sequence< Any >& aArguments )
        throw (Exception,
               RuntimeException);

    // ____ XGraphicObjectResolver ____
    virtual ::rtl::OUString SAL_CALL resolveGraphicObjectURL( const ::rtl::OUString& aURL )
        throw (RuntimeException);

    // ____ XBinaryStreamResolver ____
    virtual Reference< io::XInputStream > SAL_CALL getInputStream( const ::rtl::OUString& aURL )
        throw (RuntimeException);
    virtual Reference< io::XOutputStream > SAL_CALL createOutputStream()
        throw (RuntimeException);
    virtual ::rtl::OUString SAL_CALL resolveOutputStream( const Reference< io::XOutputStream >& aBinaryStream )
        throw (RuntimeException);

    // ____ XServiceInfo ____
    virtual ::rtl::OUString SAL_CALL getImplementationName()
        throw (RuntimeException);
    virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName )
        throw (RuntimeException);
    virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames()
        throw (RuntimeException);

private:
    SvXMLGraphicHelperMode              m_eGraphicHelperMode;
    Reference< XGraphicObjectResolver > m_xGraphicObjectResolver;
    Reference< XBinaryStreamResolver >  m_xBinaryStreamResolver;
};

SvXMLGraphicImportExportHelper::SvXMLGraphicImportExportHelper( SvXMLGraphicHelperMode eMode ) :
        impl::SvXMLGraphicImportExportHelper_Base( m_aMutex ),
        m_eGraphicHelperMode( eMode )
{}

void SAL_CALL SvXMLGraphicImportExportHelper::disposing()
{
    Reference< XComponent > xComp( m_xGraphicObjectResolver, UNO_QUERY );
    OSL_ASSERT( xComp.is());
    if( xComp.is())
        xComp->dispose();
    // m_xBinaryStreamResolver is a reference to the same object => don't call
    // dispose() again
}

// ____ XInitialization ____
void SAL_CALL SvXMLGraphicImportExportHelper::initialize(
    const Sequence< Any >& aArguments )
    throw (Exception, RuntimeException)
{
    Reference< embed::XStorage > xStorage;
    if( aArguments.getLength() > 0 )
        aArguments[0] >>= xStorage;

    SvXMLGraphicHelper * pHelper( SvXMLGraphicHelper::Create( xStorage, m_eGraphicHelperMode ));
    m_xGraphicObjectResolver.set( pHelper );
    m_xBinaryStreamResolver.set( pHelper );
    // SvXMLGraphicHelper::Create calls acquire.  Since we have two references
    // now it is safe (and necessary) to undo this acquire
    pHelper->release();
}

// ____ XGraphicObjectResolver ____
::rtl::OUString SAL_CALL SvXMLGraphicImportExportHelper::resolveGraphicObjectURL( const ::rtl::OUString& aURL )
    throw (uno::RuntimeException)
{
    return m_xGraphicObjectResolver->resolveGraphicObjectURL( aURL );
}


// ____ XBinaryStreamResolver ____
Reference< io::XInputStream > SAL_CALL SvXMLGraphicImportExportHelper::getInputStream( const ::rtl::OUString& aURL )
    throw (uno::RuntimeException)
{
    return m_xBinaryStreamResolver->getInputStream( aURL );
}
Reference< io::XOutputStream > SAL_CALL SvXMLGraphicImportExportHelper::createOutputStream()
    throw (uno::RuntimeException)
{
    return m_xBinaryStreamResolver->createOutputStream();
}
::rtl::OUString SAL_CALL SvXMLGraphicImportExportHelper::resolveOutputStream( const Reference< io::XOutputStream >& aBinaryStream )
    throw (uno::RuntimeException)
{
    return m_xBinaryStreamResolver->resolveOutputStream( aBinaryStream );
}

// ____ XServiceInfo ____
::rtl::OUString SAL_CALL SvXMLGraphicImportExportHelper::getImplementationName()
    throw (uno::RuntimeException)
{
    if( m_eGraphicHelperMode == GRAPHICHELPER_MODE_READ )
        return SvXMLGraphicImportHelper_getImplementationName();
    return SvXMLGraphicExportHelper_getImplementationName();
}
::sal_Bool SAL_CALL SvXMLGraphicImportExportHelper::supportsService( const ::rtl::OUString& ServiceName )
    throw (uno::RuntimeException)
{
    Sequence< ::rtl::OUString > aServiceNames( getSupportedServiceNames());
    const ::rtl::OUString * pBegin = aServiceNames.getConstArray();
    const ::rtl::OUString * pEnd = pBegin + aServiceNames.getLength();
    return (::std::find( pBegin, pEnd, ServiceName ) != pEnd);
}
Sequence< ::rtl::OUString > SAL_CALL SvXMLGraphicImportExportHelper::getSupportedServiceNames()
    throw (uno::RuntimeException)
{
    if( m_eGraphicHelperMode == GRAPHICHELPER_MODE_READ )
        return SvXMLGraphicImportHelper_getSupportedServiceNames();
    return SvXMLGraphicExportHelper_getSupportedServiceNames();
}

// import
Reference< XInterface > SAL_CALL SvXMLGraphicImportHelper_createInstance(const Reference< XMultiServiceFactory > & /* rSMgr */ )
    throw( Exception )
{
    return static_cast< XWeak* >( new SvXMLGraphicImportExportHelper( GRAPHICHELPER_MODE_READ ));
}
::rtl::OUString SAL_CALL SvXMLGraphicImportHelper_getImplementationName()
    throw()
{
    return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Svx.GraphicImportHelper" ));
}
Sequence< ::rtl::OUString > SAL_CALL SvXMLGraphicImportHelper_getSupportedServiceNames()
    throw()
{
    // XGraphicObjectResolver and XBinaryStreamResolver are not part of any service
    Sequence< ::rtl::OUString > aSupportedServiceNames( 2 );
    aSupportedServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.GraphicObjectResolver" ) );
    aSupportedServiceNames[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.BinaryStreamResolver" ) );
    return aSupportedServiceNames;
}

// export
Reference< XInterface > SAL_CALL SvXMLGraphicExportHelper_createInstance(const Reference< XMultiServiceFactory > & /* rSMgr */ )
    throw( Exception )
{
    return static_cast< XWeak* >( new SvXMLGraphicImportExportHelper( GRAPHICHELPER_MODE_WRITE ));
}
::rtl::OUString SAL_CALL SvXMLGraphicExportHelper_getImplementationName()
    throw()
{
    return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Svx.GraphicExportHelper" ));
}
Sequence< ::rtl::OUString > SAL_CALL SvXMLGraphicExportHelper_getSupportedServiceNames()
    throw()
{
    // XGraphicObjectResolver and XBinaryStreamResolver are not part of any service
    Sequence< ::rtl::OUString > aSupportedServiceNames( 2 );
    aSupportedServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.GraphicObjectResolver" ) );
    aSupportedServiceNames[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.BinaryStreamResolver" ) );
    return aSupportedServiceNames;
}

} // namespace svx
