/**************************************************************
 *
 * 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"

#include <string.h>
#include <rtl/ustrbuf.hxx>
#ifndef _VOS_DIAGNOSE_HXX_
#include <vos/diagnose.hxx>
#endif
#include "tvread.hxx"
#include <expat.h>
#include <osl/file.hxx>
#include <com/sun/star/frame/XConfigManager.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>

#include <comphelper/processfactory.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>
#include "com/sun/star/deployment/thePackageManagerFactory.hpp"
#include <com/sun/star/util/XMacroExpander.hpp>
#include <com/sun/star/uri/XUriReferenceFactory.hpp>
#include <com/sun/star/uri/XVndSunStarExpandUrl.hpp>
#include <comphelper/locale.hxx>

namespace treeview {


	class TVDom
	{
		friend class TVChildTarget;
		friend class TVRead;

	public:

		TVDom( TVDom* arent = 0 )
			: kind( other ),
              parent( arent ),
			  childs( 0 )
		{
		}

		~TVDom()
		{
			for( unsigned i = 0; i < childs.size(); ++i )
				delete childs[i];
		}


		TVDom* newChild()
		{
			childs.push_back( new TVDom( this ) );
			return childs.back();
		}


		TVDom* getParent() const
		{
			if( parent )
				return parent;
			else
				return const_cast<TVDom*>(this);    // I am my own parent, if I am the root
		}

		enum Kind {
			tree_view,
			tree_node,
			tree_leaf,
			other
		};

		bool isLeaf() const { return kind == TVDom::tree_leaf; }
		void setKind( Kind ind ) { kind = ind; }
		Kind getKind( ) const { return kind; }


		void setApplication( const char* appl )
		{
			application = rtl::OUString( (sal_Char*)(appl),
										 strlen( appl ),
										 RTL_TEXTENCODING_UTF8 );
		}

		void setTitle( const char* itle )
		{
			title += rtl::OUString( (sal_Char*)(itle),
                                    strlen( itle ),
                                    RTL_TEXTENCODING_UTF8 );
		}

		void setTitle( const XML_Char* itle,int len )
		{
			title += rtl::OUString( (sal_Char*)(itle),
                                    len,
                                    RTL_TEXTENCODING_UTF8 );
		}

		void setId( const char* d )
		{
			id = rtl::OUString( (sal_Char*)(d),
								strlen( d ),
								RTL_TEXTENCODING_UTF8 );
		}

		void setAnchor( const char* nchor )
		{
			anchor = rtl::OUString( (sal_Char*)(nchor),
									strlen( nchor ),
									RTL_TEXTENCODING_UTF8 );
		}

		rtl::OUString getTargetURL()
		{
			if( ! targetURL.getLength() )
			{
				sal_Int32 len;
                for ( const TVDom* p = this;; p = p->parent )
                {
                    len = p->application.getLength();
                    if ( len != 0 )
                        break;
                }

				rtl::OUStringBuffer strBuff( 22 + len + id.getLength() );
				strBuff.appendAscii(
									"vnd.sun.star.help://"
									).append(id);

				targetURL = strBuff.makeStringAndClear();
			}

			return targetURL;
		}

	private:

		Kind   kind;
		rtl::OUString  application;
		rtl::OUString  title;
		rtl::OUString  id;
		rtl::OUString  anchor;
		rtl::OUString  targetURL;

		TVDom *parent;
		std::vector< TVDom* > childs;
	};

}



using namespace treeview;
using namespace com::sun::star;
using namespace com::sun::star::uno;
using namespace com::sun::star::beans;
using namespace com::sun::star::lang;
using namespace com::sun::star::util;
using namespace com::sun::star::frame;
using namespace com::sun::star::container;
using namespace com::sun::star::deployment;


ConfigData::ConfigData()
	: prodName( rtl::OUString::createFromAscii( "%PRODUCTNAME" ) ),
	  prodVersion( rtl::OUString::createFromAscii( "%PRODUCTVERSION" ) ),
	  vendName( rtl::OUString::createFromAscii( "%VENDORNAME" ) ),
	  vendVersion( rtl::OUString::createFromAscii( "%VENDORVERSION" ) ),
	  vendShort( rtl::OUString::createFromAscii( "%VENDORSHORT" ) )
{
}

void SAL_CALL ConfigData::replaceName( rtl::OUString& oustring ) const
{
	sal_Int32 idx = -1,k = 0,off;
	bool cap = false;
	rtl::OUStringBuffer aStrBuf( 0 );

	while( ( idx = oustring.indexOf( sal_Unicode('%'),++idx ) ) != -1 )
	{
		if( oustring.indexOf( prodName,idx ) == idx )
			off = PRODUCTNAME;
		else if( oustring.indexOf( prodVersion,idx ) == idx )
			off = PRODUCTVERSION;
		else if( oustring.indexOf( vendName,idx ) == idx )
			off = VENDORNAME;
		else if( oustring.indexOf( vendVersion,idx ) == idx )
			off = VENDORVERSION;
		else if( oustring.indexOf( vendShort,idx ) == idx )
			off = VENDORSHORT;
		else
			off = -1;

		if( off != -1 )
		{
			if( ! cap )
			{
				cap = true;
				aStrBuf.ensureCapacity( 256 );
			}

			aStrBuf.append( &oustring.getStr()[k],idx - k );
			aStrBuf.append( m_vReplacement[off] );
			k = idx + m_vAdd[off];
		}
	}

	if( cap )
	{
		if( k < oustring.getLength() )
			aStrBuf.append( &oustring.getStr()[k],oustring.getLength()-k );
		oustring = aStrBuf.makeStringAndClear();
	}
}




//////////////////////////////////////////////////////////////////////////
// XInterface
//////////////////////////////////////////////////////////////////////////


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


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


Any SAL_CALL
TVBase::queryInterface(
	const Type& rType )
	throw( RuntimeException )
{
	Any aRet = cppu::queryInterface( rType,
									 SAL_STATIC_CAST( XTypeProvider*, this ),
									 SAL_STATIC_CAST( XNameAccess*, this ),
									 SAL_STATIC_CAST( XHierarchicalNameAccess*, this ),
									 SAL_STATIC_CAST( XChangesNotifier*, this ),
									 SAL_STATIC_CAST( XComponent*, this ) );

	return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
}


////////////////////////////////////////////////////////////////////////////////
//
// XTypeProvider methods.

XTYPEPROVIDER_IMPL_5( TVBase,
				   	  XTypeProvider,
					  XNameAccess,
					  XHierarchicalNameAccess,
					  XChangesNotifier,
					  XComponent );






// TVRead


TVRead::TVRead( const ConfigData& configData,TVDom* tvDom )
{
	if( ! tvDom )
		return;

	Title = tvDom->title;
	configData.replaceName( Title );
	if( tvDom->isLeaf() )
	{
		TargetURL = ( tvDom->getTargetURL() + configData.appendix );
		if( tvDom->anchor.getLength() )
			TargetURL += ( rtl::OUString::createFromAscii( "#" ) +
						   tvDom->anchor );
	}
	else
		Children = new TVChildTarget( configData,tvDom );
}



TVRead::~TVRead()
{
}






// XNameAccess

Any SAL_CALL
TVRead::getByName( const rtl::OUString& aName )
	throw( NoSuchElementException,
		   WrappedTargetException,
		   RuntimeException )
{
	bool found( true );
	Any aAny;
	if( aName.compareToAscii( "Title" ) == 0 )
		aAny <<= Title;
	else if( aName.compareToAscii( "TargetURL" ) == 0 )
		aAny <<= TargetURL;
	else if( aName.compareToAscii( "Children" ) == 0 )
	{
		cppu::OWeakObject* p = Children.get();
		aAny <<= Reference< XInterface >( p );
	}
	else
		found = false;

	if( found )
		return aAny;

	throw NoSuchElementException();
}




Sequence< rtl::OUString > SAL_CALL
TVRead::getElementNames( )
	throw( RuntimeException )
{
	Sequence< rtl::OUString > seq( 3 );

	seq[0] = rtl::OUString::createFromAscii( "Title" );
	seq[1] = rtl::OUString::createFromAscii( "TargetURL" );
	seq[2] = rtl::OUString::createFromAscii( "Children" );

	return seq;
}



sal_Bool SAL_CALL
TVRead::hasByName( const rtl::OUString& aName )
	throw( RuntimeException )
{
	if( aName.compareToAscii( "Title" ) == 0        ||
		aName.compareToAscii( "TargetURL" ) == 0    ||
		aName.compareToAscii( "Children" ) == 0 )
		return true;

	return false;
}


// XHierarchicalNameAccess

Any SAL_CALL
TVRead::getByHierarchicalName( const rtl::OUString& aName )
	throw( NoSuchElementException,
		   RuntimeException )
{
	sal_Int32 idx;
	rtl::OUString name( aName );

	if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1  &&
		name.copy( 0,idx ).compareToAscii( "Children" ) == 0 )
		return Children->getByHierarchicalName( name.copy( 1 + idx ) );

	return getByName( name );
}




sal_Bool SAL_CALL
TVRead::hasByHierarchicalName( const rtl::OUString& aName )
	throw( RuntimeException )
{
	sal_Int32 idx;
	rtl::OUString name( aName );

   	if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1  &&
		name.copy( 0,idx ).compareToAscii( "Children" ) == 0 )
		return Children->hasByHierarchicalName( name.copy( 1 + idx ) );

	return hasByName( name );
}



/**************************************************************************/
/*                                                                        */
/*                      TVChildTarget                                     */
/*                                                                        */
/**************************************************************************/




extern "C" void start_handler(void *userData,
				   const XML_Char *name,
				   const XML_Char **atts)
{
	TVDom::Kind kind;

	if( strcmp( name,"help_section" ) == 0  ||
		strcmp( name,"node" ) == 0 )
		kind = TVDom::tree_node;
	else if( strcmp( name,"topic" ) == 0 )
		kind = TVDom::tree_leaf;
	else
		return;

	TVDom **tvDom = static_cast< TVDom** >( userData );
	TVDom  *p;
	p = *tvDom;

	*tvDom = p->newChild();
	p = *tvDom;

	p->setKind( kind );
	while( *atts )
	{
		if( strcmp( *atts,"application" ) == 0 )
			p->setApplication( *(atts+1) );
		else if( strcmp( *atts,"title" ) == 0 )
			p->setTitle( *(atts+1) );
		else if( strcmp( *atts,"id" ) == 0 )
			p->setId( *(atts+1) );
		else if( strcmp( *atts,"anchor" ) == 0 )
			p->setAnchor( *(atts+1) );

		atts+=2;
	}
}


extern "C" void end_handler(void *userData,
				 const XML_Char *name )
{
	(void)name;

	TVDom **tvDom = static_cast< TVDom** >( userData );
	*tvDom = (*tvDom)->getParent();
}


extern "C" void data_handler( void *userData,
				   const XML_Char *s,
				   int len)
{
	TVDom **tvDom = static_cast< TVDom** >( userData );
	if( (*tvDom)->isLeaf() )
		(*tvDom)->setTitle( s,len );
}



TVChildTarget::TVChildTarget( const ConfigData& configData,TVDom* tvDom )
{
	Elements.resize( tvDom->childs.size() );
	for( unsigned i = 0; i < Elements.size(); ++i )
		Elements[i] = new TVRead( configData,tvDom->childs[i] );
}





TVChildTarget::TVChildTarget( const Reference< XMultiServiceFactory >& xMSF )
{
	ConfigData configData = init( xMSF );

	if( ! configData.locale.getLength()  ||
		! configData.system.getLength() )
		return;

	sal_uInt64 	ret,len = 0;
	int j = configData.vFileURL.size();

	TVDom tvDom;
	TVDom* pTVDom = &tvDom;

	while( j )
	{
		len = configData.vFileLen[--j];
		char* s = new char[ int(len) ];  // the buffer to hold the installed files
		osl::File aFile( configData.vFileURL[j] );
		aFile.open( OpenFlag_Read );
		aFile.read( s,len,ret );
		aFile.close();

		XML_Parser parser = XML_ParserCreate( 0 );
		XML_SetElementHandler( parser,
							   start_handler,
							   end_handler );
		XML_SetCharacterDataHandler( parser,
									 data_handler);
		XML_SetUserData( parser,&pTVDom ); // does not return this

		int parsed = XML_Parse( parser,s,int( len ),j==0 );
        (void)parsed;
		OSL_ENSURE( parsed, "TVChildTarget::TVChildTarget(): Tree file parsing failed" );

		XML_ParserFree( parser );
		delete[] s;
	}

	// now TVDom holds the relevant information

	Elements.resize( tvDom.childs.size() );
	for( unsigned i = 0; i < Elements.size(); ++i )
		Elements[i] = new TVRead( configData,tvDom.childs[i] );
}


TVChildTarget::~TVChildTarget()
{
}



Any SAL_CALL
TVChildTarget::getByName( const rtl::OUString& aName )
	throw( NoSuchElementException,
		   WrappedTargetException,
		   RuntimeException )
{
	rtl::OUString num( aName.getStr()+2,aName.getLength()-4 );
	sal_Int32 idx = num.toInt32() - 1;
	if( idx < 0 || Elements.size() <= sal_uInt32( idx ) )
		throw NoSuchElementException();

	Any aAny;
	cppu::OWeakObject* p = Elements[idx].get();
	aAny <<= Reference< XInterface >( p );
	return aAny;
}




Sequence< rtl::OUString > SAL_CALL
TVChildTarget::getElementNames( )
	throw( RuntimeException )
{
	Sequence< rtl::OUString > seq( Elements.size() );
	for( unsigned i = 0; i < Elements.size(); ++i )
		seq[i] = rtl::OUString::valueOf( sal_Int32( 1+i ) );

	return seq;
}



sal_Bool SAL_CALL
TVChildTarget::hasByName( const rtl::OUString& aName )
	throw( RuntimeException )
{
	rtl::OUString num( aName.getStr()+2,aName.getLength()-4 );
	sal_Int32 idx = num.toInt32() - 1;
	if( idx < 0 || Elements.size() <= sal_uInt32( idx ) )
		return false;

	return true;
}



// XHierarchicalNameAccess

Any SAL_CALL
TVChildTarget::getByHierarchicalName( const rtl::OUString& aName )
	throw( NoSuchElementException,
		   RuntimeException )
{
	sal_Int32 idx;
	rtl::OUString name( aName );

	if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 )
	{
		rtl::OUString num( name.getStr()+2,idx-4 );
		sal_Int32 pref = num.toInt32() - 1;

		if( pref < 0 || Elements.size() <= sal_uInt32( pref ) )
			throw NoSuchElementException();

		return Elements[pref]->getByHierarchicalName( name.copy( 1 + idx ) );
	}
	else
		return getByName( name );
}



sal_Bool SAL_CALL
TVChildTarget::hasByHierarchicalName( const rtl::OUString& aName )
	throw( RuntimeException )
{
	sal_Int32 idx;
	rtl::OUString name( aName );

   	if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 )
	{
		rtl::OUString num( name.getStr()+2,idx-4 );
		sal_Int32 pref = num.toInt32() - 1;
		if( pref < 0 || Elements.size() <= sal_uInt32( pref ) )
			return false;

		return Elements[pref]->hasByHierarchicalName( name.copy( 1 + idx ) );
	}
	else
		return hasByName( name );
}






ConfigData TVChildTarget::init( const Reference< XMultiServiceFactory >& xSMgr )
{
	ConfigData configData;
	Reference< XMultiServiceFactory >  sProvider( getConfiguration(xSMgr) );

	/**********************************************************************/
	/*                       reading Office.Common                        */
	/**********************************************************************/

	Reference< XHierarchicalNameAccess > xHierAccess( getHierAccess( sProvider,
																	 "org.openoffice.Office.Common" ) );
	rtl::OUString system( getKey( xHierAccess,"Help/System" ) );
	sal_Bool showBasic( getBooleanKey(xHierAccess,"Help/ShowBasic") );
	rtl::OUString instPath( getKey( xHierAccess,"Path/Current/Help" ) );
	if( ! instPath.getLength() )
	  // try to determine path from default
	  instPath = rtl::OUString::createFromAscii( "$(instpath)/help" );

	// replace anything like $(instpath);
	subst( xSMgr,instPath );

	/**********************************************************************/
	/*                       reading setup                                */
	/**********************************************************************/

	xHierAccess = getHierAccess( sProvider,
								 "org.openoffice.Setup" );

	rtl::OUString productName( getKey(  xHierAccess,"Product/ooName" ) );
    rtl::OUString setupversion( getKey( xHierAccess,"Product/ooSetupVersion" ) );
    rtl::OUString setupextension;

    try
    {
        uno::Reference< lang::XMultiServiceFactory > xConfigProvider(
	          xSMgr ->createInstance(::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider")), uno::UNO_QUERY_THROW);

        uno::Sequence < uno::Any > lParams(1);
        beans::PropertyValue                       aParam ;
        aParam.Name    = ::rtl::OUString::createFromAscii("nodepath");
        aParam.Value <<= ::rtl::OUString::createFromAscii("/org.openoffice.Setup/Product");
        lParams[0] = uno::makeAny(aParam);

        // open it
        uno::Reference< uno::XInterface > xCFG( xConfigProvider->createInstanceWithArguments(
                    ::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess"),
                    lParams) );

        uno::Reference< container::XNameAccess > xDirectAccess(xCFG, uno::UNO_QUERY);
        uno::Any aRet = xDirectAccess->getByName(::rtl::OUString::createFromAscii("ooSetupExtension"));

        aRet >>= setupextension;
    }
    catch ( uno::Exception& )
    {
    }

	rtl::OUString productVersion( setupversion +
								  rtl::OUString::createFromAscii( " " ) +
								  setupextension );
	rtl::OUString locale( getKey( xHierAccess,"L10N/ooLocale" ) );


	// Determine fileurl from url and locale
	rtl::OUString url;
	osl::FileBase::RC errFile = osl::FileBase::getFileURLFromSystemPath( instPath,url );
	if( errFile != osl::FileBase::E_None ) return configData;
	if( url.lastIndexOf( sal_Unicode( '/' ) ) != url.getLength() - 1 )
		url += rtl::OUString::createFromAscii( "/" );
	rtl::OUString ret;
	sal_Int32 idx;
	osl::DirectoryItem aDirItem;
	if( osl::FileBase::E_None == osl::DirectoryItem::get( url + locale,aDirItem ) )
		ret = locale;
	else if( ( ( idx = locale.indexOf( '-' ) ) != -1 ||
			   ( idx = locale.indexOf( '_' ) ) != -1 ) &&
			 osl::FileBase::E_None == osl::DirectoryItem::get( url + locale.copy( 0,idx ),
															   aDirItem ) )
		ret = locale.copy( 0,idx );
    else
        {
        locale = rtl::OUString::createFromAscii( "en-US" );
        ret = rtl::OUString::createFromAscii("en");
        }
	url = url + ret;

	// first of all, try do determine whether there are any *.tree files present

	// Start with extensions to set them at the end of the list
	TreeFileIterator aTreeIt( locale );
	rtl::OUString aTreeFile;
	sal_Int32 nFileSize;
	while( (aTreeFile = aTreeIt.nextTreeFile( nFileSize ) ).getLength() > 0 )
	{
		configData.vFileLen.push_back( nFileSize );
		configData.vFileURL.push_back( aTreeFile );
	}

	osl::Directory aDirectory( url );
	osl::FileStatus aFileStatus( FileStatusMask_FileName | FileStatusMask_FileSize | FileStatusMask_FileURL );
	if( osl::Directory::E_None == aDirectory.open() )
	{
		int idx_ = 0;
		rtl::OUString aFileUrl, aFileName;
		while( aDirectory.getNextItem( aDirItem ) == osl::FileBase::E_None &&
			   aDirItem.getFileStatus( aFileStatus ) == osl::FileBase::E_None &&
			   aFileStatus.isValid( FileStatusMask_FileURL ) &&
			   aFileStatus.isValid( FileStatusMask_FileName ) )
		  {
			aFileUrl = aFileStatus.getFileURL();
			aFileName = aFileStatus.getFileName();
			idx_ = aFileName.lastIndexOf( sal_Unicode( '.' ) );
			if( idx_ == -1 )
			  continue;

			const sal_Unicode* str = aFileName.getStr();

			if( aFileName.getLength() == idx_ + 5                   &&
				( str[idx_ + 1] == 't' || str[idx_ + 1] == 'T' )    &&
				( str[idx_ + 2] == 'r' || str[idx_ + 2] == 'R' )    &&
				( str[idx_ + 3] == 'e' || str[idx_ + 3] == 'E' )    &&
				( str[idx_ + 4] == 'e' || str[idx_ + 4] == 'E' ) )
			  {
				OSL_ENSURE( aFileStatus.isValid( FileStatusMask_FileSize ),
                            "invalid file size" );

				rtl::OUString baseName = aFileName.copy(0,idx_).toAsciiLowerCase();
				if(! showBasic && baseName.compareToAscii("sbasic") == 0 )
				  continue;

				configData.vFileLen.push_back( aFileStatus.getFileSize() );
				configData.vFileURL.push_back( aFileUrl );
			  }
		  }
		aDirectory.close();
	}

	configData.m_vAdd[0] = 12;
	configData.m_vAdd[1] = 15;
	configData.m_vAdd[2] = 11;
	configData.m_vAdd[3] = 14;
	configData.m_vAdd[4] = 12;
	configData.m_vReplacement[0] = productName;
	configData.m_vReplacement[1] = productVersion;
	// m_vReplacement[2...4] (vendorName/-Version/-Short) are empty strings

   	configData.system = system;
	configData.locale = locale;
	configData.appendix =
		rtl::OUString::createFromAscii( "?Language=" ) +
		configData.locale +
		rtl::OUString::createFromAscii( "&System=" ) +
		configData.system +
        rtl::OUString::createFromAscii( "&UseDB=no" ) ;

	return configData;
}









Reference< XMultiServiceFactory >
TVChildTarget::getConfiguration(const Reference< XMultiServiceFactory >& m_xSMgr) const
{
	Reference< XMultiServiceFactory > sProvider;
	if( m_xSMgr.is() )
	{
		try
		{
			rtl::OUString sProviderService =
				rtl::OUString::createFromAscii( "com.sun.star.configuration.ConfigurationProvider" );
			sProvider =
				Reference< XMultiServiceFactory >(
					m_xSMgr->createInstance( sProviderService ),
					UNO_QUERY );
		}
		catch( const com::sun::star::uno::Exception& )
		{
			OSL_ENSURE( sProvider.is(),"can't instantiate configuration" );
		}
	}

	return sProvider;
}



Reference< XHierarchicalNameAccess >
TVChildTarget::getHierAccess( const Reference< XMultiServiceFactory >& sProvider,
							  const char* file ) const
{
	Reference< XHierarchicalNameAccess > xHierAccess;

	if( sProvider.is() )
	{
		Sequence< Any > seq(1);
		rtl::OUString sReaderService =
			rtl::OUString::createFromAscii( "com.sun.star.configuration.ConfigurationAccess" );

		seq[0] <<= rtl::OUString::createFromAscii( file );

		try
		{
			xHierAccess =
				Reference< XHierarchicalNameAccess >
				( sProvider->createInstanceWithArguments( sReaderService,seq ),
				  UNO_QUERY );
		}
		catch( const com::sun::star::uno::Exception& )
		{
		}
	}

	return xHierAccess;
}



rtl::OUString
TVChildTarget::getKey( const Reference< XHierarchicalNameAccess >& xHierAccess,
					   const char* key ) const
{
    rtl::OUString instPath;
	if( xHierAccess.is() )
	{
		Any aAny;
		try
		{
			aAny =
				xHierAccess->getByHierarchicalName( rtl::OUString::createFromAscii( key ) );
		}
		catch( const com::sun::star::container::NoSuchElementException& )
		{
		}
		aAny >>= instPath;
	}
	return instPath;
}


sal_Bool
TVChildTarget::getBooleanKey(const Reference<
							 XHierarchicalNameAccess >& xHierAccess,
							 const char* key) const
{
  sal_Bool ret = sal_False;
  if( xHierAccess.is() )
	{
	  Any aAny;
	  try
		{
		  aAny =
			xHierAccess->getByHierarchicalName(
											   rtl::OUString::createFromAscii(key));
		}
	  catch( const com::sun::star::container::NoSuchElementException& )
		{
		}
	  aAny >>= ret;
	}
  return ret;
}


void TVChildTarget::subst( const Reference< XMultiServiceFactory >& m_xSMgr,
						   rtl::OUString& instpath ) const
{
	Reference< XConfigManager >  xCfgMgr;
	if( m_xSMgr.is() )
	{
		try
		{
			xCfgMgr =
				Reference< XConfigManager >(
					m_xSMgr->createInstance( rtl::OUString::createFromAscii( "com.sun.star.config.SpecialConfigManager" ) ),
					UNO_QUERY );
		}
		catch( const com::sun::star::uno::Exception& )
		{
			OSL_ENSURE( xCfgMgr.is()," can't instantiate the special config manager " );
		}
    }

	OSL_ENSURE( xCfgMgr.is(), "specialconfigmanager not found\n" );

	if( xCfgMgr.is() )
        instpath = xCfgMgr->substituteVariables( instpath );
}


//===================================================================
// class ExtensionIteratorBase

static rtl::OUString aSlash( rtl::OUString::createFromAscii( "/" ) );
static rtl::OUString aHelpFilesBaseName( rtl::OUString::createFromAscii( "help" ) );
static rtl::OUString aHelpMediaType( rtl::OUString::createFromAscii( "application/vnd.sun.star.help" ) );

ExtensionIteratorBase::ExtensionIteratorBase( const rtl::OUString& aLanguage )
		: m_eState( USER_EXTENSIONS )
		, m_aLanguage( aLanguage )
{
	init();
}

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

	Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager(), UNO_QUERY );
	m_xSFA = Reference< ucb::XSimpleFileAccess >(
		xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ),
		m_xContext ), UNO_QUERY_THROW );

	m_bUserPackagesLoaded = false;
	m_bSharedPackagesLoaded = false;
    m_bBundledPackagesLoaded = false;
	m_iUserPackage = 0;
	m_iSharedPackage = 0;
    m_iBundledPackage = 0;
}

Reference< deployment::XPackage > ExtensionIteratorBase::implGetHelpPackageFromPackage
	( Reference< deployment::XPackage > xPackage, Reference< deployment::XPackage >& o_xParentPackageBundle )
{
	o_xParentPackageBundle.clear();

	Reference< deployment::XPackage > xHelpPackage;
	if( !xPackage.is() )
		return xHelpPackage;

	// Check if parent package is registered
    beans::Optional< beans::Ambiguous<sal_Bool> > option( xPackage->isRegistered
		( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ) );
	bool bRegistered = false;
    if( option.IsPresent )
    {
        beans::Ambiguous<sal_Bool> const & reg = option.Value;
        if( !reg.IsAmbiguous && reg.Value )
			bRegistered = true;
    }
	if( !bRegistered )
		return xHelpPackage;

	if( xPackage->isBundle() )
	{
		Sequence< Reference< deployment::XPackage > > aPkgSeq = xPackage->getBundle
			( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() );
		sal_Int32 nPkgCount = aPkgSeq.getLength();
		const Reference< deployment::XPackage >* pSeq = aPkgSeq.getConstArray();
		for( sal_Int32 iPkg = 0 ; iPkg < nPkgCount ; ++iPkg )
		{
			const Reference< deployment::XPackage > xSubPkg = pSeq[ iPkg ];
			const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xSubPkg->getPackageType();
			rtl::OUString aMediaType = xPackageTypeInfo->getMediaType();
			if( aMediaType.equals( aHelpMediaType ) )
			{
				xHelpPackage = xSubPkg;
				o_xParentPackageBundle = xPackage;
				break;
			}
		}
	}
	else
	{
		const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xPackage->getPackageType();
		rtl::OUString aMediaType = xPackageTypeInfo->getMediaType();
		if( aMediaType.equals( aHelpMediaType ) )
			xHelpPackage = xPackage;
	}

	return xHelpPackage;
}

Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextUserHelpPackage
	( Reference< deployment::XPackage >& o_xParentPackageBundle )
{
	Reference< deployment::XPackage > xHelpPackage;

	if( !m_bUserPackagesLoaded )
	{
		Reference< XPackageManager > xUserManager =
			thePackageManagerFactory::get( m_xContext )->getPackageManager( rtl::OUString::createFromAscii("user") );
		m_aUserPackagesSeq = xUserManager->getDeployedPackages
			( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() );

		m_bUserPackagesLoaded = true;
	}

	if( m_iUserPackage == m_aUserPackagesSeq.getLength() )
	{
		m_eState = SHARED_EXTENSIONS;		// Later: SHARED_MODULE
	}
	else
	{
		const Reference< deployment::XPackage >* pUserPackages = m_aUserPackagesSeq.getConstArray();
		Reference< deployment::XPackage > xPackage = pUserPackages[ m_iUserPackage++ ];
		VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextUserHelpPackage(): Invalid package" );
		xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle );
	}

	return xHelpPackage;
}

Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextSharedHelpPackage
	( Reference< deployment::XPackage >& o_xParentPackageBundle )
{
	Reference< deployment::XPackage > xHelpPackage;

	if( !m_bSharedPackagesLoaded )
	{
		Reference< XPackageManager > xSharedManager =
			thePackageManagerFactory::get( m_xContext )->getPackageManager( rtl::OUString::createFromAscii("shared") );
		m_aSharedPackagesSeq = xSharedManager->getDeployedPackages
			( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() );

		m_bSharedPackagesLoaded = true;
	}

	if( m_iSharedPackage == m_aSharedPackagesSeq.getLength() )
	{
		m_eState = BUNDLED_EXTENSIONS;
	}
	else
	{
		const Reference< deployment::XPackage >* pSharedPackages = m_aSharedPackagesSeq.getConstArray();
		Reference< deployment::XPackage > xPackage = pSharedPackages[ m_iSharedPackage++ ];
		VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextSharedHelpPackage(): Invalid package" );
		xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle );
	}

	return xHelpPackage;
}

Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextBundledHelpPackage
	( Reference< deployment::XPackage >& o_xParentPackageBundle )
{
	Reference< deployment::XPackage > xHelpPackage;

	if( !m_bBundledPackagesLoaded )
	{
		Reference< XPackageManager > xBundledManager =
			thePackageManagerFactory::get( m_xContext )->getPackageManager( rtl::OUString::createFromAscii("bundled") );
		m_aBundledPackagesSeq = xBundledManager->getDeployedPackages
			( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() );

		m_bBundledPackagesLoaded = true;
	}

	if( m_iBundledPackage == m_aBundledPackagesSeq.getLength() )
	{
		m_eState = END_REACHED;
	}
	else
	{
		const Reference< deployment::XPackage >* pBundledPackages = m_aBundledPackagesSeq.getConstArray();
		Reference< deployment::XPackage > xPackage = pBundledPackages[ m_iBundledPackage++ ];
		VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextBundledHelpPackage(): Invalid package" );
		xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle );
	}

	return xHelpPackage;
}

inline bool isLetter( sal_Unicode c )
{
	bool bLetter = ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
	return bLetter;
}

void ExtensionIteratorBase::implGetLanguageVectorFromPackage( ::std::vector< ::rtl::OUString > &rv,
	com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage )
{
	rv.clear();
	rtl::OUString aExtensionPath = xPackage->getURL();
	Sequence< rtl::OUString > aEntrySeq = m_xSFA->getFolderContents( aExtensionPath, true );

	const rtl::OUString* pSeq = aEntrySeq.getConstArray();
    sal_Int32 nCount = aEntrySeq.getLength();
	for( sal_Int32 i = 0 ; i < nCount ; ++i )
	{
		rtl::OUString aEntry = pSeq[i];
		if( m_xSFA->isFolder( aEntry ) )
		{
			sal_Int32 nLastSlash = aEntry.lastIndexOf( '/' );
			if( nLastSlash != -1 )
			{
				rtl::OUString aPureEntry = aEntry.copy( nLastSlash + 1 );

				// Check language sceme
				int nLen = aPureEntry.getLength();
				const sal_Unicode* pc = aPureEntry.getStr();
				bool bStartCanBeLanguage = ( nLen >= 2 && isLetter( pc[0] ) && isLetter( pc[1] ) );
				bool bIsLanguage = bStartCanBeLanguage &&
					( nLen == 2 || (nLen == 5 && pc[2] == '-' && isLetter( pc[3] ) && isLetter( pc[4] )) );
				if( bIsLanguage )
					rv.push_back( aPureEntry );
			}
		}
	}
}


//===================================================================
// class TreeFileIterator

rtl::OUString TreeFileIterator::nextTreeFile( sal_Int32& rnFileSize )
{
	rtl::OUString aRetFile;

	while( !aRetFile.getLength() && m_eState != END_REACHED )
	{
		switch( m_eState )
		{
			case USER_EXTENSIONS:
			{
				Reference< deployment::XPackage > xParentPackageBundle;
				Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( xParentPackageBundle );
				if( !xHelpPackage.is() )
					break;

				aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage );
				break;
			}

			case SHARED_EXTENSIONS:
			{
				Reference< deployment::XPackage > xParentPackageBundle;
				Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( xParentPackageBundle );
				if( !xHelpPackage.is() )
					break;

				aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage );
				break;
			}
			case BUNDLED_EXTENSIONS:
			{
				Reference< deployment::XPackage > xParentPackageBundle;
				Reference< deployment::XPackage > xHelpPackage = implGetNextBundledHelpPackage( xParentPackageBundle );
				if( !xHelpPackage.is() )
					break;

				aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage );
				break;
			}

        case END_REACHED:
				VOS_ENSURE( false, "DataBaseIterator::nextTreeFile(): Invalid case END_REACHED" );
				break;
		}
	}

	return aRetFile;
}

rtl::OUString TreeFileIterator::expandURL( const rtl::OUString& aURL )
{
	static Reference< util::XMacroExpander > xMacroExpander;
	static Reference< uri::XUriReferenceFactory > xFac;

	osl::MutexGuard aGuard( m_aMutex );

	if( !xMacroExpander.is() || !xFac.is() )
	{
		Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager(), UNO_QUERY );

		xFac = Reference< uri::XUriReferenceFactory >(
			xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii(
			"com.sun.star.uri.UriReferenceFactory"), m_xContext ) , UNO_QUERY );
		if( !xFac.is() )
		{
			throw RuntimeException(
				::rtl::OUString::createFromAscii( "Databases::expand(), could not instantiate UriReferenceFactory." ),
				Reference< XInterface >() );
		}

		xMacroExpander = Reference< util::XMacroExpander >(
			m_xContext->getValueByName(
			::rtl::OUString::createFromAscii( "/singletons/com.sun.star.util.theMacroExpander" ) ),
			UNO_QUERY_THROW );
 	}

	rtl::OUString aRetURL = aURL;
	if( xMacroExpander.is() )
	{
		Reference< uri::XUriReference > uriRef;
		for (;;)
		{
			uriRef = Reference< uri::XUriReference >( xFac->parse( aRetURL ), UNO_QUERY );
			if ( uriRef.is() )
			{
				Reference < uri::XVndSunStarExpandUrl > sxUri( uriRef, UNO_QUERY );
				if( !sxUri.is() )
					break;

				aRetURL = sxUri->expand( xMacroExpander );
			}
		}
 	}
	return aRetURL;
}

rtl::OUString TreeFileIterator::implGetTreeFileFromPackage
	( sal_Int32& rnFileSize, Reference< deployment::XPackage > xPackage )
{
	rtl::OUString aRetFile;
	rtl::OUString aLanguage = m_aLanguage;
	for( sal_Int32 iPass = 0 ; iPass < 2 ; ++iPass )
	{
		rtl::OUStringBuffer aStrBuf;
		aStrBuf.append( xPackage->getURL() );
		aStrBuf.append( aSlash );
		aStrBuf.append( aLanguage );
		aStrBuf.append( aSlash );
		aStrBuf.append( aHelpFilesBaseName );
		aStrBuf.appendAscii( ".tree" );

		aRetFile = expandURL( aStrBuf.makeStringAndClear() );
		if( iPass == 0 )
		{
			if( m_xSFA->exists( aRetFile ) )
				break;

			::std::vector< ::rtl::OUString > av;
			implGetLanguageVectorFromPackage( av, xPackage );
			::std::vector< ::rtl::OUString >::const_iterator pFound = av.end();
			try
			{
				pFound = ::comphelper::Locale::getFallback( av, m_aLanguage );
			}
			catch( ::comphelper::Locale::MalFormedLocaleException& )
			{}
			if( pFound != av.end() )
				aLanguage = *pFound;
		}
	}

	rnFileSize = 0;
	if( m_xSFA->exists( aRetFile ) )
		rnFileSize = m_xSFA->getSize( aRetFile );
	else
		aRetFile = rtl::OUString();

	return aRetFile;
}
