/**************************************************************
 * 
 * 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_xmlhelp.hxx"

#define WORKAROUND_98119

#ifdef WORKAROUND_98119
#include "bufferedinputstream.hxx"
#endif

#include <string.h>
#ifndef _VOS_DIAGNOSE_HXX_
#include <vos/diagnose.hxx>
#endif
#include <osl/thread.h>
#include <rtl/memory.h>
#include <osl/file.hxx>
#include <cppuhelper/weak.hxx>
#include <cppuhelper/queryinterface.hxx>
#include <comphelper/processfactory.hxx>
#include <rtl/uri.hxx>
#include <rtl/ustrbuf.hxx>
#include <libxslt/xslt.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#include "db.hxx"
#include <com/sun/star/io/XActiveDataSink.hpp>
#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/io/XSeekable.hpp>
#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
#include <com/sun/star/ucb/OpenMode.hpp>
#include <com/sun/star/ucb/XCommandProcessor.hpp>
#include <com/sun/star/ucb/XCommandEnvironment.hpp>
#include <com/sun/star/ucb/XContentIdentifier.hpp>
#include <com/sun/star/ucb/XContentProvider.hpp>
#include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>

#include "urlparameter.hxx"
#include "databases.hxx"

namespace chelp {

	inline bool ascii_isDigit( sal_Unicode ch )
	{
		return ((ch >= 0x0030) && (ch <= 0x0039));
	}
	
	inline bool ascii_isLetter( sal_Unicode ch )
	{
		return ( ( (ch >= 0x0041) && (ch <= 0x005A) ) || 
				 ( (ch >= 0x0061) && (ch <= 0x007A) ) );
	}
	
	inline bool isLetterOrDigit( sal_Unicode ch )
	{
		return ascii_isLetter( ch ) || ascii_isDigit( ch );
	}

}

using namespace cppu;
using namespace com::sun::star::io;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::ucb;
using namespace com::sun::star::beans;
using namespace com::sun::star::container;
using namespace chelp;


URLParameter::URLParameter( const rtl::OUString& aURL,
							Databases* pDatabases )
	throw( com::sun::star::ucb::IllegalIdentifierException )
	: m_pDatabases( pDatabases ),
      m_aURL( aURL )
{
	init( false );
	parse();
}


bool URLParameter::isErrorDocument()
{
	bool bErrorDoc = false;

	if( isFile() )
	{
		Reference< XHierarchicalNameAccess > xNA =
			m_pDatabases->findJarFileForPath( get_jar(), get_language(), get_path() );
		bErrorDoc = !xNA.is();
	}

	return bErrorDoc;
}


rtl::OString URLParameter::getByName( const char* par )
{
	rtl::OUString val;
	
	if( strcmp( par,"Program" ) == 0 )
		val = get_program();
	else if( strcmp( par,"Database" ) == 0 )
		val = get_module();
	else if( strcmp( par,"DatabasePar" ) == 0 )
		val = get_dbpar();
	else if( strcmp( par,"Id" ) == 0 )
		val = get_id();
	else if( strcmp( par,"Path" ) == 0 )
		val = get_path();
	else if( strcmp( par,"Language" ) == 0 )
		val = get_language();
	else if( strcmp( par,"System" ) == 0 )
		val = get_system();
	else if( strcmp( par,"HelpPrefix" ) == 0 )
		val = get_prefix();
	
	return rtl::OString( val.getStr(),val.getLength(),RTL_TEXTENCODING_UTF8 );
}


rtl::OUString URLParameter::get_id()
{
	if( m_aId.compareToAscii("start") == 0 )
	{   // module is set
		StaticModuleInformation* inf =
			m_pDatabases->getStaticInformationForModule( get_module(),
														 get_language() );
		if( inf )
			m_aId = inf->get_id();
		
		m_bStart = true;
	}
	
	return m_aId;
}
		
rtl::OUString URLParameter::get_tag()
{
	if( isFile() )
		return get_the_tag();
	else
		return m_aTag;
}


rtl::OUString URLParameter::get_title()
{
	if( isFile() )
		return get_the_title();
	else if( m_aModule.compareToAscii("") != 0 )
	{
		StaticModuleInformation* inf =
			m_pDatabases->getStaticInformationForModule( get_module(),
														 get_language() );
		if( inf )
			m_aTitle = inf->get_title();
	}
	else   // This must be the root
		m_aTitle = rtl::OUString::createFromAscii("root");
	
	return m_aTitle;
}
		

rtl::OUString URLParameter::get_language()
{
	if( m_aLanguage.getLength() == 0 )
		return m_aDefaultLanguage;
	
	return m_aLanguage;
}


rtl::OUString URLParameter::get_program()
{
	if( ! m_aProgram.getLength() )
	{
		StaticModuleInformation* inf =
			m_pDatabases->getStaticInformationForModule( get_module(),
														 get_language() );
		if( inf )
			m_aProgram = inf->get_program();
	}
	return m_aProgram;
}
			

void URLParameter::init( bool bDefaultLanguageIsInitialized )
{
	(void)bDefaultLanguageIsInitialized;

	m_bHelpDataFileRead = false;
	m_bStart = false;
    m_bUseDB = true;
	m_nHitCount = 100;                // The default maximum hitcount	
}


rtl::OUString URLParameter::get_the_tag()
{
    if(m_bUseDB) {
        if( ! m_bHelpDataFileRead )
            readHelpDataFile();
		
        m_bHelpDataFileRead = true;
		
        return m_aTag;
    }
    else
        return rtl::OUString();
}



rtl::OUString URLParameter::get_the_path()
{
    if(m_bUseDB) {
        if( ! m_bHelpDataFileRead )
            readHelpDataFile();
        m_bHelpDataFileRead = true;
        
        return m_aPath;
    }
    else
        return get_id();
}

	

rtl::OUString URLParameter::get_the_title()
{
    if(m_bUseDB) {
        if( ! m_bHelpDataFileRead )
            readHelpDataFile();
        m_bHelpDataFileRead = true;
        
        return m_aTitle;
    }
    else
        return rtl::OUString();
}


rtl::OUString URLParameter::get_the_jar()
{
    if(m_bUseDB) {
        if( ! m_bHelpDataFileRead )
            readHelpDataFile();
        m_bHelpDataFileRead = true;
        
        return m_aJar;
    }
    else
        return get_module() + rtl::OUString::createFromAscii(".jar");
}




void URLParameter::readHelpDataFile()
{
	static rtl::OUString aQuestionMark( rtl::OUString::createFromAscii( "?" ) );

	if( get_id().compareToAscii("") == 0 )
		return;

	rtl::OUString aModule = get_module();
	rtl::OUString aLanguage = get_language();

	DataBaseIterator aDbIt( *m_pDatabases, aModule, aLanguage, false );
	bool bSuccess = false;

	int nSize = 0;
	const sal_Char* pData = NULL;

	helpdatafileproxy::HDFData aHDFData;
	rtl::OUString aExtensionPath;
    rtl::OUString aExtensionRegistryPath;
	while( true )
	{
		helpdatafileproxy::Hdf* pHdf = aDbIt.nextHdf( &aExtensionPath, &aExtensionRegistryPath );
		if( !pHdf )
			break;

		rtl::OString keyStr( m_aId.getStr(),m_aId.getLength(),RTL_TEXTENCODING_UTF8 );
		
		bSuccess = pHdf->getValueForKey( keyStr, aHDFData );
		if( bSuccess )
		{
			nSize = aHDFData.getSize();
			pData = aHDFData.getData();
			break;
		}
	}

	if( bSuccess )
	{
		DbtToStringConverter converter( pData, nSize );
		m_aTitle = converter.getTitle();
		m_pDatabases->replaceName( m_aTitle );
		m_aPath  = converter.getFile();
		m_aJar   = converter.getDatabase();
		if( aExtensionPath.getLength() > 0 )
		{
			rtl::OUStringBuffer aExtendedJarStrBuf;
			aExtendedJarStrBuf.append( aQuestionMark );
			aExtendedJarStrBuf.append( aExtensionPath );
			aExtendedJarStrBuf.append( aQuestionMark );
			aExtendedJarStrBuf.append( m_aJar );
			m_aJar = aExtendedJarStrBuf.makeStringAndClear();
            m_aExtensionRegistryPath = aExtensionRegistryPath;
		}
		m_aTag   = converter.getHash();
	}
}



// Class encapsulating the transformation of the XInputStream to XHTML


class InputStreamTransformer
	: public OWeakObject,
	  public XInputStream,
	  public XSeekable
{
public:
	
	InputStreamTransformer( URLParameter* urlParam,
							Databases*    pDatatabases,
							bool isRoot = false );
	
	~InputStreamTransformer();
	
	virtual Any SAL_CALL queryInterface( const Type& rType ) throw( RuntimeException );
	virtual void SAL_CALL acquire( void ) throw();
	virtual void SAL_CALL release( void ) throw();

	virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData,sal_Int32 nBytesToRead ) 
		throw( NotConnectedException,
			   BufferSizeExceededException,
			   IOException,
			   RuntimeException);
	
	virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >& aData,sal_Int32 nMaxBytesToRead )
		throw( NotConnectedException,
			   BufferSizeExceededException,
			   IOException,
			   RuntimeException);
	
	virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) throw( NotConnectedException,
																	 BufferSizeExceededException,
																	 IOException,
																	 RuntimeException );
	
	virtual sal_Int32 SAL_CALL available( void ) throw( NotConnectedException,
														IOException,
														RuntimeException );
	
	virtual void SAL_CALL closeInput( void ) throw( NotConnectedException,
													IOException,
													RuntimeException );
	
	virtual void SAL_CALL seek( sal_Int64 location ) throw( IllegalArgumentException,
															IOException,
															RuntimeException );
	
	virtual sal_Int64 SAL_CALL getPosition( void ) throw( IOException,RuntimeException );
	
	virtual sal_Int64 SAL_CALL getLength( void ) throw( IOException,RuntimeException );
	
	void addToBuffer( const char* buffer,int len );

	sal_Int8* getData() const { return (sal_Int8*) buffer; }

    sal_Int32 getLen() const { return sal_Int32( len ); }
    
private:
	
	osl::Mutex m_aMutex;
	
	int len,pos;
	char *buffer;
};



void URLParameter::open( const Reference< XMultiServiceFactory >& rxSMgr,
						 const Command& aCommand,
						 sal_Int32 CommandId,
						 const Reference< XCommandEnvironment >& Environment,
						 const Reference< XOutputStream >& xDataSink )
{
	(void)rxSMgr;
	(void)aCommand;
	(void)CommandId;
	(void)Environment;

    if( ! xDataSink.is() )
        return;
    
	if( isPicture() )
	{
		Reference< XInputStream > xStream;
		Reference< XHierarchicalNameAccess > xNA =
			m_pDatabases->jarFile( rtl::OUString::createFromAscii( "picture.jar" ),
								   get_language() );
		
		rtl::OUString path = get_path();
		if( xNA.is() )
		{
			try
			{
				Any aEntry = xNA->getByHierarchicalName( path );
				Reference< XActiveDataSink > xSink;
				if( ( aEntry >>= xSink ) && xSink.is() )
					xStream = xSink->getInputStream();
			}
			catch ( NoSuchElementException & )
			{
			}
		}
        if( xStream.is() )
        {
            sal_Int32 ret;
            Sequence< sal_Int8 > aSeq( 4096 );
            while( true )
            {
                try
                {
                    ret = xStream->readBytes( aSeq,4096 );
                    xDataSink->writeBytes( aSeq );
                    if( ret < 4096 )
                        break;
                }
                catch( const Exception& )
                {
                    break;
                }
            }
        }
	}
	else
    {
		// a standard document or else an active help text, plug in the new input stream	
		InputStreamTransformer* p = new InputStreamTransformer( this,m_pDatabases,isRoot() );
        try
        {
            xDataSink->writeBytes( Sequence< sal_Int8 >( p->getData(),p->getLen() ) );
        }
        catch( const Exception& )
        {
        }
        delete p;
    }
    xDataSink->closeOutput();
}



void URLParameter::open( const Reference< XMultiServiceFactory >& rxSMgr,
						 const Command& aCommand,
						 sal_Int32 CommandId,
						 const Reference< XCommandEnvironment >& Environment,
						 const Reference< XActiveDataSink >& xDataSink )
{
	(void)rxSMgr;
	(void)aCommand;
	(void)CommandId;
	(void)Environment;

	if( isPicture() )
	{
		Reference< XInputStream > xStream;
		Reference< XHierarchicalNameAccess > xNA =
			m_pDatabases->jarFile( rtl::OUString::createFromAscii( "picture.jar" ),
								   get_language() );
		
		rtl::OUString path = get_path();
		if( xNA.is() )
		{
			try
			{
				Any aEntry = xNA->getByHierarchicalName( path );
				Reference< XActiveDataSink > xSink;
				if( ( aEntry >>= xSink ) && xSink.is() )
					xStream = xSink->getInputStream();
			}
			catch ( NoSuchElementException & )
			{
			}
		}
#ifdef WORKAROUND_98119
		xDataSink->setInputStream( turnToSeekable(xStream) );
#else
		xDataSink->setInputStream( xStream );
#endif
	}
	else
		// a standard document or else an active help text, plug in the new input stream	
		xDataSink->setInputStream( new InputStreamTransformer( this,m_pDatabases,isRoot() ) );
}


// #include <stdio.h>

void URLParameter::parse() throw( com::sun::star::ucb::IllegalIdentifierException )
{
    // fprintf(stdout,"url send to xmlhelp: %s\n",(rtl::OUStringToOString(m_aURL,RTL_TEXTENCODING_UTF8).getStr()));
	m_aExpr = m_aURL;
	
	sal_Int32 lstIdx = m_aExpr.lastIndexOf( sal_Unicode( '#' ) );
	if( lstIdx != -1 )
		m_aExpr = m_aExpr.copy( 0,lstIdx );
	
	if( ! scheme() ||
        ! name( module() ) ||
        ! query() ||
        ! m_aLanguage.getLength() ||
        ! m_aSystem.getLength() )
		throw com::sun::star::ucb::IllegalIdentifierException();
}
		

bool URLParameter::scheme()
{
	// Correct extension help links as sometimes the
	// module is missing resulting in a misformed URL
	if( m_aExpr.compareToAscii( "vnd.sun.star.help:///", 21 ) == 0 )
	{
		sal_Int32 nLen = m_aExpr.getLength();
		rtl::OUString aLastStr = m_aExpr.copy( nLen - 6 );
		if( aLastStr.compareToAscii( "DbPAR=" ) == 0 )
		{
			rtl::OUString aNewExpr = m_aExpr.copy( 0, 20 );
			rtl::OUString aSharedStr = rtl::OUString::createFromAscii( "shared" );
			aNewExpr += aSharedStr;
			aNewExpr += m_aExpr.copy( 20 );
			aNewExpr += aSharedStr;
			m_aExpr = aNewExpr;
		}
	}

	for( sal_Int32 nPrefixLen = 20 ; nPrefixLen >= 18 ; --nPrefixLen )
	{
		if( m_aExpr.compareToAscii( "vnd.sun.star.help://", nPrefixLen ) == 0 )
		{
			m_aExpr = m_aExpr.copy( nPrefixLen );
			return true;
		}
	}
	return false;
}

		
bool URLParameter::module()
{
	sal_Int32 idx = 0,length = m_aExpr.getLength();
	
	while( idx < length && isLetterOrDigit( (m_aExpr.getStr())[idx] ) ) 
		++idx;
			
	if( idx != 0 )
	{
		m_aModule = m_aExpr.copy( 0,idx );
		m_aExpr = m_aExpr.copy( idx );
		return true;
	}
	else
		return false;
}
	
	
	
bool URLParameter::name( bool modulePresent )
{
	// if modulepresent, a name may be present, but must not

	sal_Int32 length = m_aExpr.getLength();
    
	if( length != 0 && (m_aExpr.getStr())[0] == sal_Unicode( '/' ) )
	{
		sal_Int32 idx = 1;
		while( idx < length && (m_aExpr.getStr())[idx] != '?' )
//                ( isLetterOrDigit( (m_aExpr.getStr())[idx] ) 
//                  || (m_aExpr.getStr())[idx] == '/'
//                  || (m_aExpr.getStr())[idx] == '.' ))
			++idx;
        
		if( idx != 1 && ! modulePresent )
			return false;
		else
		{
			m_aId = m_aExpr.copy( 1,idx-1 );
			m_aExpr = m_aExpr.copy( idx );
		}
	}
    
//    fprintf(stdout,"id %s\n",(rtl::OUStringToOString(m_aId,RTL_TEXTENCODING_UTF8).getStr()));
	return true;
}
		
	
bool URLParameter::query()
{
	rtl::OUString query_;
	
	if( ! m_aExpr.getLength() )
		return true;
	else if( (m_aExpr.getStr())[0] == sal_Unicode( '?' ) )
		query_ = m_aExpr.copy( 1 ).trim();
	else
		return false;
		
			
	bool ret = true;
	sal_Int32 delimIdx,equalIdx;
	rtl::OUString parameter,value;
		
	while( query_.getLength() != 0 )
	{
		delimIdx = query_.indexOf( sal_Unicode( '&' ) );
		equalIdx = query_.indexOf( sal_Unicode( '=' ) );
		parameter = query_.copy( 0,equalIdx ).trim();
		if( delimIdx == -1 )
		{
			value = query_.copy( equalIdx + 1 ).trim();
			query_ = rtl::OUString();
		}
		else
		{
			value = query_.copy( equalIdx+1,delimIdx - equalIdx - 1 ).trim();
			query_ = query_.copy( delimIdx+1 ).trim();
		}
		
		if( parameter.compareToAscii( "Language" ) == 0 )
			m_aLanguage = value;
		else if( parameter.compareToAscii( "Device" ) == 0 )
			m_aDevice = value;
		else if( parameter.compareToAscii( "Program" ) == 0 )
			m_aProgram = value;
		else if( parameter.compareToAscii( "Eid" ) == 0 )
			m_aEid = value;
		else if( parameter.compareToAscii( "UseDB" ) == 0 )
            m_bUseDB = ! ( value.compareToAscii("no") == 0 );
        else if( parameter.compareToAscii( "DbPAR" ) == 0 )
            m_aDbPar = value;
		else if( parameter.compareToAscii( "Query" ) == 0 )
		{	
			if( ! m_aQuery.getLength() )
				m_aQuery = value;
			else
				m_aQuery += ( rtl::OUString::createFromAscii( " " ) + value );
		}
		else if( parameter.compareToAscii( "Scope" ) == 0 )
			m_aScope = value;
		else if( parameter.compareToAscii( "System" ) == 0 )
			m_aSystem = value;
		else if( parameter.compareToAscii( "HelpPrefix" ) == 0 )
			m_aPrefix = rtl::Uri::decode(
                value,
                rtl_UriDecodeWithCharset,
                RTL_TEXTENCODING_UTF8 );
		else if( parameter.compareToAscii( "HitCount" ) == 0 )
			m_nHitCount = value.toInt32();
		else if( parameter.compareToAscii( "Active" ) == 0 )
			m_aActive = value;
		else
			ret = false;
	}
			
	return ret;
}

struct UserData {
	
	UserData( InputStreamTransformer* pTransformer,
			  URLParameter*           pInitial,
			  Databases*              pDatabases )
		: m_pTransformer( pTransformer ),
          m_pDatabases( pDatabases ),
		  m_pInitial( pInitial )
	{
	}
	
	InputStreamTransformer*             m_pTransformer;
	Databases*                          m_pDatabases;
	URLParameter*                       m_pInitial;
};

UserData *ugblData = 0;

extern "C" {

static int
fileMatch(const char * URI) {
	if ((URI != NULL) && !strncmp(URI, "file:/", 6))
        return 1;
    return 0;
}

static int
zipMatch(const char * URI) {
	if ((URI != NULL) && !strncmp(URI, "vnd.sun.star.zip:/", 18))
        return 1;
    return 0;
}

static int
helpMatch(const char * URI) {
	if ((URI != NULL) && !strncmp(URI, "vnd.sun.star.help:/", 19))
        return 1;
    return 0;
}

static void *
fileOpen(const char *URI) {
	osl::File *pRet = new osl::File(rtl::OUString(URI, strlen(URI), RTL_TEXTENCODING_UTF8));
	pRet->open(OpenFlag_Read);
	return pRet;
}

static void *
zipOpen(const char * /*URI*/) {
	rtl::OUString language,jar,path;

	if( ugblData->m_pInitial->get_eid().getLength() )
		return (void*)(new Reference< XHierarchicalNameAccess >);
	else
	{
		jar = ugblData->m_pInitial->get_jar();
		language = ugblData->m_pInitial->get_language();
		path = ugblData->m_pInitial->get_path();
	}

	Reference< XHierarchicalNameAccess > xNA =
		ugblData->m_pDatabases->findJarFileForPath( jar, language, path );

    Reference< XInputStream > xInputStream;

	if( xNA.is() )
	{
		try
		{
			Any aEntry = xNA->getByHierarchicalName( path );
			Reference< XActiveDataSink > xSink;
			if( ( aEntry >>= xSink ) && xSink.is() )
				xInputStream = xSink->getInputStream();
		}
		catch ( NoSuchElementException & )
		{
		}
	}
	
	if( xInputStream.is() )
	{
		return new Reference<XInputStream>(xInputStream);
	}
	return 0;
}

static void *
helpOpen(const char * URI) {
	rtl::OUString language,jar,path;

	URLParameter urlpar( rtl::OUString::createFromAscii( URI ),
						 ugblData->m_pDatabases );
		
	jar = urlpar.get_jar();
	language = urlpar.get_language();
	path = urlpar.get_path();

	Reference< XHierarchicalNameAccess > xNA =
		ugblData->m_pDatabases->findJarFileForPath( jar, language, path );

    Reference< XInputStream > xInputStream;

	if( xNA.is() )
	{
		try
		{
			Any aEntry = xNA->getByHierarchicalName( path );
			Reference< XActiveDataSink > xSink;
			if( ( aEntry >>= xSink ) && xSink.is() )
				xInputStream = xSink->getInputStream();
		}
		catch ( NoSuchElementException & )
		{
		}
	}
	
	if( xInputStream.is() )
		return new Reference<XInputStream>(xInputStream);
	return 0;
}

static int
helpRead(void * context, char * buffer, int len) {
	Reference< XInputStream > *pRef = (Reference< XInputStream >*)context;

	Sequence< sal_Int8 > aSeq;
	len = (*pRef)->readBytes( aSeq,len);
	memcpy(buffer, aSeq.getConstArray(), len);

	return len;
}

static int
zipRead(void * context, char * buffer, int len) {
	if( ugblData->m_pInitial->get_eid().getLength() )
	{
		ugblData->m_pDatabases->popupDocument( ugblData->m_pInitial,&buffer,&len);
		return len;
	}
	else
		return helpRead(context, buffer, len);
}

static int
fileRead(void * context, char * buffer, int len) {
	int nRead = 0;
	osl::File *pFile = (osl::File*)context;
	if (pFile)
	{
		sal_uInt64 uRead = 0;
		if (osl::FileBase::E_None == pFile->read(buffer, len, uRead))
			nRead = static_cast<int>(uRead);
	}
	return nRead;
}

static int
uriClose(void * context) {
	Reference< XInputStream > *pRef = (Reference< XInputStream >*)context;
	delete pRef;
    return 0;
}

static int
fileClose(void * context) {
	osl::File *pFile = (osl::File*)context;
	if (pFile)
	{
		pFile->close();
		delete pFile;
	}
	return 0;
}

} // extern "C"

/*
// For debugging only
extern "C" void StructuredXMLErrorFunction(void *userData, xmlErrorPtr error)
{
	(void)userData;
	(void)error;

	// Reset error handler
	xmlSetStructuredErrorFunc( NULL, NULL ); 
}
*/

InputStreamTransformer::InputStreamTransformer( URLParameter* urlParam,
												Databases*    pDatabases,
												bool isRoot )
	: len( 0 ),
	  pos( 0 ),
	  buffer( new char[1] ) // Initializing with one element to avoid gcc compiler warning
{
	if( isRoot )
	{
		delete[] buffer;
		pDatabases->cascadingStylesheet( urlParam->get_language(),
										 &buffer,
										 &len );
	}
	else if( urlParam->isActive() )
	{
		delete[] buffer;
		pDatabases->setActiveText( urlParam->get_module(),
								   urlParam->get_language(),
								   urlParam->get_id(),
								   &buffer,
								   &len );
	}
	else
	{
		UserData userData( this,urlParam,pDatabases );
	
		// Uses the implementation detail, that rtl::OString::getStr returns a zero terminated character-array
        
		const char* parameter[47];
		rtl::OString parString[46];
		int last = 0;
        
		parString[last++] = "Program";
		rtl::OString aPureProgramm( urlParam->getByName( "Program" ) );
		parString[last++] = rtl::OString('\'') + aPureProgramm + rtl::OString('\'');
		parString[last++] = "Database";
		parString[last++] = rtl::OString('\'') + urlParam->getByName( "DatabasePar" ) + rtl::OString('\'');
		parString[last++] = "Id";
		parString[last++] = rtl::OString('\'') + urlParam->getByName( "Id" ) + rtl::OString('\'');
		parString[last++] = "Path";
		rtl::OString aPath( urlParam->getByName( "Path" ) );
		parString[last++] = rtl::OString('\'') + aPath + rtl::OString('\'');

		rtl::OString aPureLanguage = urlParam->getByName( "Language" );
		parString[last++] = "Language";
		parString[last++] = rtl::OString('\'') + aPureLanguage + rtl::OString('\'');
		parString[last++] = "System";
		parString[last++] = rtl::OString('\'') + urlParam->getByName( "System" ) + rtl::OString('\'');
		parString[last++] = "productname";
		parString[last++] = rtl::OString('\'') + rtl::OString(
            pDatabases->getProductName().getStr(),
            pDatabases->getProductName().getLength(),
            RTL_TEXTENCODING_UTF8 ) + rtl::OString('\'');
		parString[last++] = "productversion";
		parString[last++] = rtl::OString('\'') + 
            rtl::OString(  pDatabases->getProductVersion().getStr(),
                          pDatabases->getProductVersion().getLength(),
                          RTL_TEXTENCODING_UTF8 ) + rtl::OString('\'');

        parString[last++] = "imgrepos";
        parString[last++] = rtl::OString('\'') + pDatabases->getImagesZipFileURL() + rtl::OString('\'');
        parString[last++] = "hp";
        parString[last++] = rtl::OString('\'') + urlParam->getByName( "HelpPrefix" ) + rtl::OString('\'');
        
        if( parString[last-1].getLength() )
        {
            parString[last++] = "sm";
            parString[last++] = "'vnd.sun.star.help%3A%2F%2F'";
            parString[last++] = "qm";
            parString[last++] = "'%3F'";
            parString[last++] = "es";
            parString[last++] = "'%3D'";
            parString[last++] = "am";
            parString[last++] = "'%26'";
            parString[last++] = "cl";
            parString[last++] = "'%3A'";
            parString[last++] = "sl";
            parString[last++] = "'%2F'";
            parString[last++] = "hm";
            parString[last++] = "'%23'";
            parString[last++] = "cs";
            parString[last++] = "'css'";

            parString[last++] = "vendorname";
            parString[last++] = rtl::OString("''");
            parString[last++] = "vendorversion";
            parString[last++] = rtl::OString("''");
            parString[last++] = "vendorshort";
            parString[last++] = rtl::OString("''");
        }
        
		// Do we need to add extension path?
		::rtl::OUString aExtensionPath;
		rtl::OUString aJar = urlParam->get_jar();

		bool bAddExtensionPath = false;
        rtl::OUString aExtensionRegistryPath;
        sal_Int32 nQuestionMark1 = aJar.indexOf( sal_Unicode('?') );
        sal_Int32 nQuestionMark2 = aJar.lastIndexOf( sal_Unicode('?') );
		if( nQuestionMark1 != -1 && nQuestionMark2 != -1 && nQuestionMark1 != nQuestionMark2 )
		{
			aExtensionPath = aJar.copy( nQuestionMark1 + 1, nQuestionMark2 - nQuestionMark1 - 1 );
            aExtensionRegistryPath = urlParam->get_ExtensionRegistryPath();
			bAddExtensionPath = true;
		}
		else
		{
			// Path not yet specified, search directly
			Reference< XHierarchicalNameAccess > xNA = pDatabases->findJarFileForPath
				( aJar, urlParam->get_language(), urlParam->get_path(), &aExtensionPath, &aExtensionRegistryPath );
			if( xNA.is() && aExtensionPath.getLength() )
				bAddExtensionPath = true;
		}

		if( bAddExtensionPath )
		{
			Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
			Reference< XPropertySet > xProps( xFactory, UNO_QUERY );
			OSL_ASSERT( xProps.is() );
			Reference< XComponentContext > xContext;
			if (xProps.is())
			{
				xProps->getPropertyValue(
					::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xContext;
			}
			if( !xContext.is() )
			{
				throw RuntimeException(
					::rtl::OUString::createFromAscii( "InputStreamTransformer::InputStreamTransformer(), no XComponentContext" ),
					Reference< XInterface >() );
			}

			rtl::OUString aOUExpandedExtensionPath = Databases::expandURL( aExtensionRegistryPath, xContext );
			rtl::OString aExpandedExtensionPath = rtl::OUStringToOString( aOUExpandedExtensionPath, osl_getThreadTextEncoding() );

			parString[last++] = "ExtensionPath";
			parString[last++] = rtl::OString('\'') + aExpandedExtensionPath + rtl::OString('\'');

			// ExtensionId
			rtl::OString aPureExtensionId;
			sal_Int32 iSlash = aPath.indexOf( '/' );
			if( iSlash != -1 )
				aPureExtensionId = aPath.copy( 0, iSlash );

			parString[last++] = "ExtensionId";
			parString[last++] = rtl::OString('\'') + aPureExtensionId + rtl::OString('\'');
		}

		for( int i = 0; i < last; ++i )
			parameter[i] = parString[i].getStr();
		parameter[last] = 0;
		
		rtl::OUString xslURL = pDatabases->getInstallPathAsURL();
		
		rtl::OString xslURLascii( 
			xslURL.getStr(),
			xslURL.getLength(),
			RTL_TEXTENCODING_UTF8);
		xslURLascii += "main_transform.xsl";

        ugblData = &userData;

        xmlInitParser();
        xmlRegisterInputCallbacks(zipMatch, zipOpen, zipRead, uriClose);
        xmlRegisterInputCallbacks(helpMatch, helpOpen, helpRead, uriClose);
		xmlRegisterInputCallbacks(fileMatch, fileOpen, fileRead, fileClose);
		//xmlSetStructuredErrorFunc( NULL, (xmlStructuredErrorFunc)StructuredXMLErrorFunction ); 

        xsltStylesheetPtr cur = 
            xsltParseStylesheetFile((const xmlChar *)xslURLascii.getStr());

        xmlDocPtr doc = xmlParseFile("vnd.sun.star.zip:/");

        xmlDocPtr res = xsltApplyStylesheet(cur, doc, parameter);
        if (res)
		{
			xmlChar *doc_txt_ptr=0;
			int doc_txt_len;
			xsltSaveResultToString(&doc_txt_ptr, &doc_txt_len, res, cur);
			addToBuffer((const char*)doc_txt_ptr, doc_txt_len);
			xmlFree(doc_txt_ptr);
        }
        xmlPopInputCallbacks();	//filePatch
        xmlPopInputCallbacks();	//helpPatch
        xmlPopInputCallbacks();	//zipMatch
        xmlFreeDoc(res);
        xmlFreeDoc(doc);
        xsltFreeStylesheet(cur);
	}
}


InputStreamTransformer::~InputStreamTransformer()
{
	delete[] buffer;
}


Any SAL_CALL InputStreamTransformer::queryInterface( const Type& rType ) throw( RuntimeException )
{
	Any aRet = ::cppu::queryInterface( rType,
									   SAL_STATIC_CAST( XInputStream*,this ),
									   SAL_STATIC_CAST( XSeekable*,this ) );
	
	return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
}



void SAL_CALL InputStreamTransformer::acquire( void ) throw()
{
	OWeakObject::acquire();
}



void SAL_CALL InputStreamTransformer::release( void ) throw()
{
	OWeakObject::release();
}



sal_Int32 SAL_CALL InputStreamTransformer::readBytes( Sequence< sal_Int8 >& aData,sal_Int32 nBytesToRead )
	throw( NotConnectedException,
		   BufferSizeExceededException,
		   IOException,
		   RuntimeException)
{
	osl::MutexGuard aGuard( m_aMutex );

	int curr,available_ = len-pos;
	if( nBytesToRead <= available_ )
		curr = nBytesToRead;
	else
		curr = available_;
	
	if( 0 <= curr && aData.getLength() < curr )
		aData.realloc( curr ); 
	
	for( int k = 0; k < curr; ++k )
		aData[k] = buffer[pos++];
	
	return curr > 0 ? curr : 0;
}


sal_Int32 SAL_CALL InputStreamTransformer::readSomeBytes( Sequence< sal_Int8 >& aData,sal_Int32 nMaxBytesToRead )
	throw( NotConnectedException,
		   BufferSizeExceededException,
		   IOException,
		   RuntimeException)
{
	return readBytes( aData,nMaxBytesToRead );
}



void SAL_CALL InputStreamTransformer::skipBytes( sal_Int32 nBytesToSkip ) throw( NotConnectedException,
																				 BufferSizeExceededException,
																				 IOException,
																				 RuntimeException )
{
	osl::MutexGuard aGuard( m_aMutex );
	while( nBytesToSkip-- ) ++pos;
}



sal_Int32 SAL_CALL InputStreamTransformer::available( void ) throw( NotConnectedException,
																	IOException,
																	RuntimeException )
{
	osl::MutexGuard aGuard( m_aMutex );
	return len-pos > 0 ? len - pos : 0 ;
}



void SAL_CALL InputStreamTransformer::closeInput( void ) throw( NotConnectedException,
																IOException,
																RuntimeException )
{
}



void SAL_CALL InputStreamTransformer::seek( sal_Int64 location ) throw( IllegalArgumentException,
																		IOException,
																		RuntimeException )
{
	osl::MutexGuard aGuard( m_aMutex );
	if( location < 0 )
		throw IllegalArgumentException();
	else
		pos = sal::static_int_cast<sal_Int32>( location );
	
	if( pos > len )
		pos = len;
}



sal_Int64 SAL_CALL InputStreamTransformer::getPosition( void ) throw( IOException,
																	  RuntimeException )
{
	osl::MutexGuard aGuard( m_aMutex );
	return sal_Int64( pos );
}



sal_Int64 SAL_CALL InputStreamTransformer::getLength( void ) throw( IOException,RuntimeException )
{
	osl::MutexGuard aGuard( m_aMutex );
	
	return len;
}


void InputStreamTransformer::addToBuffer( const char* buffer_,int len_ )
{
	osl::MutexGuard aGuard( m_aMutex );
	
	char* tmp = buffer;
	buffer = new char[ len+len_ ];
	rtl_copyMemory( (void*)(buffer),(void*)(tmp),sal_uInt32( len ) );
	rtl_copyMemory( (void*)(buffer+len),(void*)(buffer_),sal_uInt32( len_ ) );
	delete[] tmp;
	len += len_;
}
