xref: /aoo41x/main/xmlhelp/source/treeview/tvread.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 
29 // MARKER(update_precomp.py): autogen include statement, do not remove
30 #include "precompiled_xmlhelp.hxx"
31 
32 #include <string.h>
33 #include <rtl/ustrbuf.hxx>
34 #ifndef _VOS_DIAGNOSE_HXX_
35 #include <vos/diagnose.hxx>
36 #endif
37 #include "tvread.hxx"
38 #include <expat.h>
39 #include <osl/file.hxx>
40 #include <com/sun/star/frame/XConfigManager.hpp>
41 #include <com/sun/star/beans/PropertyValue.hpp>
42 
43 #include <comphelper/processfactory.hxx>
44 #include <com/sun/star/beans/XPropertySet.hpp>
45 #include "com/sun/star/deployment/thePackageManagerFactory.hpp"
46 #include <com/sun/star/util/XMacroExpander.hpp>
47 #include <com/sun/star/uri/XUriReferenceFactory.hpp>
48 #include <com/sun/star/uri/XVndSunStarExpandUrl.hpp>
49 #include <comphelper/locale.hxx>
50 
51 namespace treeview {
52 
53 
54 	class TVDom
55 	{
56 		friend class TVChildTarget;
57 		friend class TVRead;
58 
59 	public:
60 
61 		TVDom( TVDom* arent = 0 )
62 			: kind( other ),
63               parent( arent ),
64 			  childs( 0 )
65 		{
66 		}
67 
68 		~TVDom()
69 		{
70 			for( unsigned i = 0; i < childs.size(); ++i )
71 				delete childs[i];
72 		}
73 
74 
75 		TVDom* newChild()
76 		{
77 			childs.push_back( new TVDom( this ) );
78 			return childs.back();
79 		}
80 
81 
82 		TVDom* getParent() const
83 		{
84 			if( parent )
85 				return parent;
86 			else
87 				return const_cast<TVDom*>(this);    // I am my own parent, if I am the root
88 		}
89 
90 		enum Kind {
91 			tree_view,
92 			tree_node,
93 			tree_leaf,
94 			other
95 		};
96 
97 		bool isLeaf() const { return kind == TVDom::tree_leaf; }
98 		void setKind( Kind ind ) { kind = ind; }
99 		Kind getKind( ) const { return kind; }
100 
101 
102 		void setApplication( const char* appl )
103 		{
104 			application = rtl::OUString( (sal_Char*)(appl),
105 										 strlen( appl ),
106 										 RTL_TEXTENCODING_UTF8 );
107 		}
108 
109 		void setTitle( const char* itle )
110 		{
111 			title += rtl::OUString( (sal_Char*)(itle),
112                                     strlen( itle ),
113                                     RTL_TEXTENCODING_UTF8 );
114 		}
115 
116 		void setTitle( const XML_Char* itle,int len )
117 		{
118 			title += rtl::OUString( (sal_Char*)(itle),
119                                     len,
120                                     RTL_TEXTENCODING_UTF8 );
121 		}
122 
123 		void setId( const char* d )
124 		{
125 			id = rtl::OUString( (sal_Char*)(d),
126 								strlen( d ),
127 								RTL_TEXTENCODING_UTF8 );
128 		}
129 
130 		void setAnchor( const char* nchor )
131 		{
132 			anchor = rtl::OUString( (sal_Char*)(nchor),
133 									strlen( nchor ),
134 									RTL_TEXTENCODING_UTF8 );
135 		}
136 
137 		rtl::OUString getTargetURL()
138 		{
139 			if( ! targetURL.getLength() )
140 			{
141 				sal_Int32 len;
142                 for ( const TVDom* p = this;; p = p->parent )
143                 {
144                     len = p->application.getLength();
145                     if ( len != 0 )
146                         break;
147                 }
148 
149 				rtl::OUStringBuffer strBuff( 22 + len + id.getLength() );
150 				strBuff.appendAscii(
151 									"vnd.sun.star.help://"
152 									).append(id);
153 
154 				targetURL = strBuff.makeStringAndClear();
155 			}
156 
157 			return targetURL;
158 		}
159 
160 	private:
161 
162 		Kind   kind;
163 		rtl::OUString  application;
164 		rtl::OUString  title;
165 		rtl::OUString  id;
166 		rtl::OUString  anchor;
167 		rtl::OUString  targetURL;
168 
169 		TVDom *parent;
170 		std::vector< TVDom* > childs;
171 	};
172 
173 }
174 
175 
176 
177 using namespace treeview;
178 using namespace com::sun::star;
179 using namespace com::sun::star::uno;
180 using namespace com::sun::star::beans;
181 using namespace com::sun::star::lang;
182 using namespace com::sun::star::util;
183 using namespace com::sun::star::frame;
184 using namespace com::sun::star::container;
185 using namespace com::sun::star::deployment;
186 
187 
188 ConfigData::ConfigData()
189 	: prodName( rtl::OUString::createFromAscii( "%PRODUCTNAME" ) ),
190 	  prodVersion( rtl::OUString::createFromAscii( "%PRODUCTVERSION" ) ),
191 	  vendName( rtl::OUString::createFromAscii( "%VENDORNAME" ) ),
192 	  vendVersion( rtl::OUString::createFromAscii( "%VENDORVERSION" ) ),
193 	  vendShort( rtl::OUString::createFromAscii( "%VENDORSHORT" ) )
194 {
195 }
196 
197 void SAL_CALL ConfigData::replaceName( rtl::OUString& oustring ) const
198 {
199 	sal_Int32 idx = -1,k = 0,off;
200 	bool cap = false;
201 	rtl::OUStringBuffer aStrBuf( 0 );
202 
203 	while( ( idx = oustring.indexOf( sal_Unicode('%'),++idx ) ) != -1 )
204 	{
205 		if( oustring.indexOf( prodName,idx ) == idx )
206 			off = PRODUCTNAME;
207 		else if( oustring.indexOf( prodVersion,idx ) == idx )
208 			off = PRODUCTVERSION;
209 		else if( oustring.indexOf( vendName,idx ) == idx )
210 			off = VENDORNAME;
211 		else if( oustring.indexOf( vendVersion,idx ) == idx )
212 			off = VENDORVERSION;
213 		else if( oustring.indexOf( vendShort,idx ) == idx )
214 			off = VENDORSHORT;
215 		else
216 			off = -1;
217 
218 		if( off != -1 )
219 		{
220 			if( ! cap )
221 			{
222 				cap = true;
223 				aStrBuf.ensureCapacity( 256 );
224 			}
225 
226 			aStrBuf.append( &oustring.getStr()[k],idx - k );
227 			aStrBuf.append( m_vReplacement[off] );
228 			k = idx + m_vAdd[off];
229 		}
230 	}
231 
232 	if( cap )
233 	{
234 		if( k < oustring.getLength() )
235 			aStrBuf.append( &oustring.getStr()[k],oustring.getLength()-k );
236 		oustring = aStrBuf.makeStringAndClear();
237 	}
238 }
239 
240 
241 
242 
243 //////////////////////////////////////////////////////////////////////////
244 // XInterface
245 //////////////////////////////////////////////////////////////////////////
246 
247 
248 void SAL_CALL
249 TVBase::acquire(
250 	void )
251 	throw()
252 {
253   OWeakObject::acquire();
254 }
255 
256 
257 void SAL_CALL
258 TVBase::release(
259 		      void )
260   throw()
261 {
262   OWeakObject::release();
263 }
264 
265 
266 Any SAL_CALL
267 TVBase::queryInterface(
268 	const Type& rType )
269 	throw( RuntimeException )
270 {
271 	Any aRet = cppu::queryInterface( rType,
272 									 SAL_STATIC_CAST( XTypeProvider*, this ),
273 									 SAL_STATIC_CAST( XNameAccess*, this ),
274 									 SAL_STATIC_CAST( XHierarchicalNameAccess*, this ),
275 									 SAL_STATIC_CAST( XChangesNotifier*, this ),
276 									 SAL_STATIC_CAST( XComponent*, this ) );
277 
278 	return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
279 }
280 
281 
282 ////////////////////////////////////////////////////////////////////////////////
283 //
284 // XTypeProvider methods.
285 
286 XTYPEPROVIDER_IMPL_5( TVBase,
287 				   	  XTypeProvider,
288 					  XNameAccess,
289 					  XHierarchicalNameAccess,
290 					  XChangesNotifier,
291 					  XComponent );
292 
293 
294 
295 
296 
297 
298 // TVRead
299 
300 
301 TVRead::TVRead( const ConfigData& configData,TVDom* tvDom )
302 {
303 	if( ! tvDom )
304 		return;
305 
306 	Title = tvDom->title;
307 	configData.replaceName( Title );
308 	if( tvDom->isLeaf() )
309 	{
310 		TargetURL = ( tvDom->getTargetURL() + configData.appendix );
311 		if( tvDom->anchor.getLength() )
312 			TargetURL += ( rtl::OUString::createFromAscii( "#" ) +
313 						   tvDom->anchor );
314 	}
315 	else
316 		Children = new TVChildTarget( configData,tvDom );
317 }
318 
319 
320 
321 TVRead::~TVRead()
322 {
323 }
324 
325 
326 
327 
328 
329 
330 // XNameAccess
331 
332 Any SAL_CALL
333 TVRead::getByName( const rtl::OUString& aName )
334 	throw( NoSuchElementException,
335 		   WrappedTargetException,
336 		   RuntimeException )
337 {
338 	bool found( true );
339 	Any aAny;
340 	if( aName.compareToAscii( "Title" ) == 0 )
341 		aAny <<= Title;
342 	else if( aName.compareToAscii( "TargetURL" ) == 0 )
343 		aAny <<= TargetURL;
344 	else if( aName.compareToAscii( "Children" ) == 0 )
345 	{
346 		cppu::OWeakObject* p = Children.get();
347 		aAny <<= Reference< XInterface >( p );
348 	}
349 	else
350 		found = false;
351 
352 	if( found )
353 		return aAny;
354 
355 	throw NoSuchElementException();
356 }
357 
358 
359 
360 
361 Sequence< rtl::OUString > SAL_CALL
362 TVRead::getElementNames( )
363 	throw( RuntimeException )
364 {
365 	Sequence< rtl::OUString > seq( 3 );
366 
367 	seq[0] = rtl::OUString::createFromAscii( "Title" );
368 	seq[1] = rtl::OUString::createFromAscii( "TargetURL" );
369 	seq[2] = rtl::OUString::createFromAscii( "Children" );
370 
371 	return seq;
372 }
373 
374 
375 
376 sal_Bool SAL_CALL
377 TVRead::hasByName( const rtl::OUString& aName )
378 	throw( RuntimeException )
379 {
380 	if( aName.compareToAscii( "Title" ) == 0        ||
381 		aName.compareToAscii( "TargetURL" ) == 0    ||
382 		aName.compareToAscii( "Children" ) == 0 )
383 		return true;
384 
385 	return false;
386 }
387 
388 
389 // XHierarchicalNameAccess
390 
391 Any SAL_CALL
392 TVRead::getByHierarchicalName( const rtl::OUString& aName )
393 	throw( NoSuchElementException,
394 		   RuntimeException )
395 {
396 	sal_Int32 idx;
397 	rtl::OUString name( aName );
398 
399 	if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1  &&
400 		name.copy( 0,idx ).compareToAscii( "Children" ) == 0 )
401 		return Children->getByHierarchicalName( name.copy( 1 + idx ) );
402 
403 	return getByName( name );
404 }
405 
406 
407 
408 
409 sal_Bool SAL_CALL
410 TVRead::hasByHierarchicalName( const rtl::OUString& aName )
411 	throw( RuntimeException )
412 {
413 	sal_Int32 idx;
414 	rtl::OUString name( aName );
415 
416    	if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1  &&
417 		name.copy( 0,idx ).compareToAscii( "Children" ) == 0 )
418 		return Children->hasByHierarchicalName( name.copy( 1 + idx ) );
419 
420 	return hasByName( name );
421 }
422 
423 
424 
425 /**************************************************************************/
426 /*                                                                        */
427 /*                      TVChildTarget                                     */
428 /*                                                                        */
429 /**************************************************************************/
430 
431 
432 
433 
434 extern "C" void start_handler(void *userData,
435 				   const XML_Char *name,
436 				   const XML_Char **atts)
437 {
438 	TVDom::Kind kind;
439 
440 	if( strcmp( name,"help_section" ) == 0  ||
441 		strcmp( name,"node" ) == 0 )
442 		kind = TVDom::tree_node;
443 	else if( strcmp( name,"topic" ) == 0 )
444 		kind = TVDom::tree_leaf;
445 	else
446 		return;
447 
448 	TVDom **tvDom = static_cast< TVDom** >( userData );
449 	TVDom  *p;
450 	p = *tvDom;
451 
452 	*tvDom = p->newChild();
453 	p = *tvDom;
454 
455 	p->setKind( kind );
456 	while( *atts )
457 	{
458 		if( strcmp( *atts,"application" ) == 0 )
459 			p->setApplication( *(atts+1) );
460 		else if( strcmp( *atts,"title" ) == 0 )
461 			p->setTitle( *(atts+1) );
462 		else if( strcmp( *atts,"id" ) == 0 )
463 			p->setId( *(atts+1) );
464 		else if( strcmp( *atts,"anchor" ) == 0 )
465 			p->setAnchor( *(atts+1) );
466 
467 		atts+=2;
468 	}
469 }
470 
471 
472 extern "C" void end_handler(void *userData,
473 				 const XML_Char *name )
474 {
475 	(void)name;
476 
477 	TVDom **tvDom = static_cast< TVDom** >( userData );
478 	*tvDom = (*tvDom)->getParent();
479 }
480 
481 
482 extern "C" void data_handler( void *userData,
483 				   const XML_Char *s,
484 				   int len)
485 {
486 	TVDom **tvDom = static_cast< TVDom** >( userData );
487 	if( (*tvDom)->isLeaf() )
488 		(*tvDom)->setTitle( s,len );
489 }
490 
491 
492 
493 TVChildTarget::TVChildTarget( const ConfigData& configData,TVDom* tvDom )
494 {
495 	Elements.resize( tvDom->childs.size() );
496 	for( unsigned i = 0; i < Elements.size(); ++i )
497 		Elements[i] = new TVRead( configData,tvDom->childs[i] );
498 }
499 
500 
501 
502 
503 
504 TVChildTarget::TVChildTarget( const Reference< XMultiServiceFactory >& xMSF )
505 {
506 	ConfigData configData = init( xMSF );
507 
508 	if( ! configData.locale.getLength()  ||
509 		! configData.system.getLength() )
510 		return;
511 
512 	sal_uInt64 	ret,len = 0;
513 	int j = configData.vFileURL.size();
514 
515 	TVDom tvDom;
516 	TVDom* pTVDom = &tvDom;
517 
518 	while( j )
519 	{
520 		len = configData.vFileLen[--j];
521 		char* s = new char[ int(len) ];  // the buffer to hold the installed files
522 		osl::File aFile( configData.vFileURL[j] );
523 		aFile.open( OpenFlag_Read );
524 		aFile.read( s,len,ret );
525 		aFile.close();
526 
527 		XML_Parser parser = XML_ParserCreate( 0 );
528 		XML_SetElementHandler( parser,
529 							   start_handler,
530 							   end_handler );
531 		XML_SetCharacterDataHandler( parser,
532 									 data_handler);
533 		XML_SetUserData( parser,&pTVDom ); // does not return this
534 
535 		int parsed = XML_Parse( parser,s,int( len ),j==0 );
536         (void)parsed;
537 		OSL_ENSURE( parsed, "TVChildTarget::TVChildTarget(): Tree file parsing failed" );
538 
539 		XML_ParserFree( parser );
540 		delete[] s;
541 	}
542 
543 	// now TVDom holds the relevant information
544 
545 	Elements.resize( tvDom.childs.size() );
546 	for( unsigned i = 0; i < Elements.size(); ++i )
547 		Elements[i] = new TVRead( configData,tvDom.childs[i] );
548 }
549 
550 
551 TVChildTarget::~TVChildTarget()
552 {
553 }
554 
555 
556 
557 Any SAL_CALL
558 TVChildTarget::getByName( const rtl::OUString& aName )
559 	throw( NoSuchElementException,
560 		   WrappedTargetException,
561 		   RuntimeException )
562 {
563 	rtl::OUString num( aName.getStr()+2,aName.getLength()-4 );
564 	sal_Int32 idx = num.toInt32() - 1;
565 	if( idx < 0 || Elements.size() <= sal_uInt32( idx ) )
566 		throw NoSuchElementException();
567 
568 	Any aAny;
569 	cppu::OWeakObject* p = Elements[idx].get();
570 	aAny <<= Reference< XInterface >( p );
571 	return aAny;
572 }
573 
574 
575 
576 
577 Sequence< rtl::OUString > SAL_CALL
578 TVChildTarget::getElementNames( )
579 	throw( RuntimeException )
580 {
581 	Sequence< rtl::OUString > seq( Elements.size() );
582 	for( unsigned i = 0; i < Elements.size(); ++i )
583 		seq[i] = rtl::OUString::valueOf( sal_Int32( 1+i ) );
584 
585 	return seq;
586 }
587 
588 
589 
590 sal_Bool SAL_CALL
591 TVChildTarget::hasByName( const rtl::OUString& aName )
592 	throw( RuntimeException )
593 {
594 	rtl::OUString num( aName.getStr()+2,aName.getLength()-4 );
595 	sal_Int32 idx = num.toInt32() - 1;
596 	if( idx < 0 || Elements.size() <= sal_uInt32( idx ) )
597 		return false;
598 
599 	return true;
600 }
601 
602 
603 
604 // XHierarchicalNameAccess
605 
606 Any SAL_CALL
607 TVChildTarget::getByHierarchicalName( const rtl::OUString& aName )
608 	throw( NoSuchElementException,
609 		   RuntimeException )
610 {
611 	sal_Int32 idx;
612 	rtl::OUString name( aName );
613 
614 	if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 )
615 	{
616 		rtl::OUString num( name.getStr()+2,idx-4 );
617 		sal_Int32 pref = num.toInt32() - 1;
618 
619 		if( pref < 0 || Elements.size() <= sal_uInt32( pref ) )
620 			throw NoSuchElementException();
621 
622 		return Elements[pref]->getByHierarchicalName( name.copy( 1 + idx ) );
623 	}
624 	else
625 		return getByName( name );
626 }
627 
628 
629 
630 sal_Bool SAL_CALL
631 TVChildTarget::hasByHierarchicalName( const rtl::OUString& aName )
632 	throw( RuntimeException )
633 {
634 	sal_Int32 idx;
635 	rtl::OUString name( aName );
636 
637    	if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 )
638 	{
639 		rtl::OUString num( name.getStr()+2,idx-4 );
640 		sal_Int32 pref = num.toInt32() - 1;
641 		if( pref < 0 || Elements.size() <= sal_uInt32( pref ) )
642 			return false;
643 
644 		return Elements[pref]->hasByHierarchicalName( name.copy( 1 + idx ) );
645 	}
646 	else
647 		return hasByName( name );
648 }
649 
650 
651 
652 
653 
654 
655 ConfigData TVChildTarget::init( const Reference< XMultiServiceFactory >& xSMgr )
656 {
657 	ConfigData configData;
658 	Reference< XMultiServiceFactory >  sProvider( getConfiguration(xSMgr) );
659 
660 	/**********************************************************************/
661 	/*                       reading Office.Common                        */
662 	/**********************************************************************/
663 
664 	Reference< XHierarchicalNameAccess > xHierAccess( getHierAccess( sProvider,
665 																	 "org.openoffice.Office.Common" ) );
666 	rtl::OUString system( getKey( xHierAccess,"Help/System" ) );
667 	sal_Bool showBasic( getBooleanKey(xHierAccess,"Help/ShowBasic") );
668 	rtl::OUString instPath( getKey( xHierAccess,"Path/Current/Help" ) );
669 	if( ! instPath.getLength() )
670 	  // try to determine path from default
671 	  instPath = rtl::OUString::createFromAscii( "$(instpath)/help" );
672 
673 	// replace anything like $(instpath);
674 	subst( xSMgr,instPath );
675 
676 	/**********************************************************************/
677 	/*                       reading setup                                */
678 	/**********************************************************************/
679 
680 	xHierAccess = getHierAccess( sProvider,
681 								 "org.openoffice.Setup" );
682 
683 	rtl::OUString productName( getKey(  xHierAccess,"Product/ooName" ) );
684     rtl::OUString setupversion( getKey( xHierAccess,"Product/ooSetupVersion" ) );
685     rtl::OUString setupextension;
686 
687     try
688     {
689         uno::Reference< lang::XMultiServiceFactory > xConfigProvider(
690 	          xSMgr ->createInstance(::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider")), uno::UNO_QUERY_THROW);
691 
692         uno::Sequence < uno::Any > lParams(1);
693         beans::PropertyValue                       aParam ;
694         aParam.Name    = ::rtl::OUString::createFromAscii("nodepath");
695         aParam.Value <<= ::rtl::OUString::createFromAscii("/org.openoffice.Setup/Product");
696         lParams[0] = uno::makeAny(aParam);
697 
698         // open it
699         uno::Reference< uno::XInterface > xCFG( xConfigProvider->createInstanceWithArguments(
700                     ::rtl::OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess"),
701                     lParams) );
702 
703         uno::Reference< container::XNameAccess > xDirectAccess(xCFG, uno::UNO_QUERY);
704         uno::Any aRet = xDirectAccess->getByName(::rtl::OUString::createFromAscii("ooSetupExtension"));
705 
706         aRet >>= setupextension;
707     }
708     catch ( uno::Exception& )
709     {
710     }
711 
712 	rtl::OUString productVersion( setupversion +
713 								  rtl::OUString::createFromAscii( " " ) +
714 								  setupextension );
715 	rtl::OUString locale( getKey( xHierAccess,"L10N/ooLocale" ) );
716 
717 
718 	// Determine fileurl from url and locale
719 	rtl::OUString url;
720 	osl::FileBase::RC errFile = osl::FileBase::getFileURLFromSystemPath( instPath,url );
721 	if( errFile != osl::FileBase::E_None ) return configData;
722 	if( url.lastIndexOf( sal_Unicode( '/' ) ) != url.getLength() - 1 )
723 		url += rtl::OUString::createFromAscii( "/" );
724 	rtl::OUString ret;
725 	sal_Int32 idx;
726 	osl::DirectoryItem aDirItem;
727 	if( osl::FileBase::E_None == osl::DirectoryItem::get( url + locale,aDirItem ) )
728 		ret = locale;
729 	else if( ( ( idx = locale.indexOf( '-' ) ) != -1 ||
730 			   ( idx = locale.indexOf( '_' ) ) != -1 ) &&
731 			 osl::FileBase::E_None == osl::DirectoryItem::get( url + locale.copy( 0,idx ),
732 															   aDirItem ) )
733 		ret = locale.copy( 0,idx );
734     else
735         {
736         locale = rtl::OUString::createFromAscii( "en-US" );
737         ret = rtl::OUString::createFromAscii("en");
738         }
739 	url = url + ret;
740 
741 	// first of all, try do determine whether there are any *.tree files present
742 
743 	// Start with extensions to set them at the end of the list
744 	TreeFileIterator aTreeIt( locale );
745 	rtl::OUString aTreeFile;
746 	sal_Int32 nFileSize;
747 	while( (aTreeFile = aTreeIt.nextTreeFile( nFileSize ) ).getLength() > 0 )
748 	{
749 		configData.vFileLen.push_back( nFileSize );
750 		configData.vFileURL.push_back( aTreeFile );
751 	}
752 
753 	osl::Directory aDirectory( url );
754 	osl::FileStatus aFileStatus( FileStatusMask_FileName | FileStatusMask_FileSize | FileStatusMask_FileURL );
755 	if( osl::Directory::E_None == aDirectory.open() )
756 	{
757 		int idx_ = 0;
758 		rtl::OUString aFileUrl, aFileName;
759 		while( aDirectory.getNextItem( aDirItem ) == osl::FileBase::E_None &&
760 			   aDirItem.getFileStatus( aFileStatus ) == osl::FileBase::E_None &&
761 			   aFileStatus.isValid( FileStatusMask_FileURL ) &&
762 			   aFileStatus.isValid( FileStatusMask_FileName ) )
763 		  {
764 			aFileUrl = aFileStatus.getFileURL();
765 			aFileName = aFileStatus.getFileName();
766 			idx_ = aFileName.lastIndexOf( sal_Unicode( '.' ) );
767 			if( idx_ == -1 )
768 			  continue;
769 
770 			const sal_Unicode* str = aFileName.getStr();
771 
772 			if( aFileName.getLength() == idx_ + 5                   &&
773 				( str[idx_ + 1] == 't' || str[idx_ + 1] == 'T' )    &&
774 				( str[idx_ + 2] == 'r' || str[idx_ + 2] == 'R' )    &&
775 				( str[idx_ + 3] == 'e' || str[idx_ + 3] == 'E' )    &&
776 				( str[idx_ + 4] == 'e' || str[idx_ + 4] == 'E' ) )
777 			  {
778 				OSL_ENSURE( aFileStatus.isValid( FileStatusMask_FileSize ),
779                             "invalid file size" );
780 
781 				rtl::OUString baseName = aFileName.copy(0,idx_).toAsciiLowerCase();
782 				if(! showBasic && baseName.compareToAscii("sbasic") == 0 )
783 				  continue;
784 
785 				configData.vFileLen.push_back( aFileStatus.getFileSize() );
786 				configData.vFileURL.push_back( aFileUrl );
787 			  }
788 		  }
789 		aDirectory.close();
790 	}
791 
792 	configData.m_vAdd[0] = 12;
793 	configData.m_vAdd[1] = 15;
794 	configData.m_vAdd[2] = 11;
795 	configData.m_vAdd[3] = 14;
796 	configData.m_vAdd[4] = 12;
797 	configData.m_vReplacement[0] = productName;
798 	configData.m_vReplacement[1] = productVersion;
799 	// m_vReplacement[2...4] (vendorName/-Version/-Short) are empty strings
800 
801    	configData.system = system;
802 	configData.locale = locale;
803 	configData.appendix =
804 		rtl::OUString::createFromAscii( "?Language=" ) +
805 		configData.locale +
806 		rtl::OUString::createFromAscii( "&System=" ) +
807 		configData.system +
808         rtl::OUString::createFromAscii( "&UseDB=no" ) ;
809 
810 	return configData;
811 }
812 
813 
814 
815 
816 
817 
818 
819 
820 
821 Reference< XMultiServiceFactory >
822 TVChildTarget::getConfiguration(const Reference< XMultiServiceFactory >& m_xSMgr) const
823 {
824 	Reference< XMultiServiceFactory > sProvider;
825 	if( m_xSMgr.is() )
826 	{
827 		try
828 		{
829 			rtl::OUString sProviderService =
830 				rtl::OUString::createFromAscii( "com.sun.star.configuration.ConfigurationProvider" );
831 			sProvider =
832 				Reference< XMultiServiceFactory >(
833 					m_xSMgr->createInstance( sProviderService ),
834 					UNO_QUERY );
835 		}
836 		catch( const com::sun::star::uno::Exception& )
837 		{
838 			OSL_ENSURE( sProvider.is(),"cant instantiate configuration" );
839 		}
840 	}
841 
842 	return sProvider;
843 }
844 
845 
846 
847 Reference< XHierarchicalNameAccess >
848 TVChildTarget::getHierAccess( const Reference< XMultiServiceFactory >& sProvider,
849 							  const char* file ) const
850 {
851 	Reference< XHierarchicalNameAccess > xHierAccess;
852 
853 	if( sProvider.is() )
854 	{
855 		Sequence< Any > seq(1);
856 		rtl::OUString sReaderService =
857 			rtl::OUString::createFromAscii( "com.sun.star.configuration.ConfigurationAccess" );
858 
859 		seq[0] <<= rtl::OUString::createFromAscii( file );
860 
861 		try
862 		{
863 			xHierAccess =
864 				Reference< XHierarchicalNameAccess >
865 				( sProvider->createInstanceWithArguments( sReaderService,seq ),
866 				  UNO_QUERY );
867 		}
868 		catch( const com::sun::star::uno::Exception& )
869 		{
870 		}
871 	}
872 
873 	return xHierAccess;
874 }
875 
876 
877 
878 rtl::OUString
879 TVChildTarget::getKey( const Reference< XHierarchicalNameAccess >& xHierAccess,
880 					   const char* key ) const
881 {
882     rtl::OUString instPath;
883 	if( xHierAccess.is() )
884 	{
885 		Any aAny;
886 		try
887 		{
888 			aAny =
889 				xHierAccess->getByHierarchicalName( rtl::OUString::createFromAscii( key ) );
890 		}
891 		catch( const com::sun::star::container::NoSuchElementException& )
892 		{
893 		}
894 		aAny >>= instPath;
895 	}
896 	return instPath;
897 }
898 
899 
900 sal_Bool
901 TVChildTarget::getBooleanKey(const Reference<
902 							 XHierarchicalNameAccess >& xHierAccess,
903 							 const char* key) const
904 {
905   sal_Bool ret = sal_False;
906   if( xHierAccess.is() )
907 	{
908 	  Any aAny;
909 	  try
910 		{
911 		  aAny =
912 			xHierAccess->getByHierarchicalName(
913 											   rtl::OUString::createFromAscii(key));
914 		}
915 	  catch( const com::sun::star::container::NoSuchElementException& )
916 		{
917 		}
918 	  aAny >>= ret;
919 	}
920   return ret;
921 }
922 
923 
924 void TVChildTarget::subst( const Reference< XMultiServiceFactory >& m_xSMgr,
925 						   rtl::OUString& instpath ) const
926 {
927 	Reference< XConfigManager >  xCfgMgr;
928 	if( m_xSMgr.is() )
929 	{
930 		try
931 		{
932 			xCfgMgr =
933 				Reference< XConfigManager >(
934 					m_xSMgr->createInstance( rtl::OUString::createFromAscii( "com.sun.star.config.SpecialConfigManager" ) ),
935 					UNO_QUERY );
936 		}
937 		catch( const com::sun::star::uno::Exception& )
938 		{
939 			OSL_ENSURE( xCfgMgr.is()," cant instantiate the special config manager " );
940 		}
941     }
942 
943 	OSL_ENSURE( xCfgMgr.is(), "specialconfigmanager not found\n" );
944 
945 	if( xCfgMgr.is() )
946         instpath = xCfgMgr->substituteVariables( instpath );
947 }
948 
949 
950 //===================================================================
951 // class ExtensionIteratorBase
952 
953 static rtl::OUString aSlash( rtl::OUString::createFromAscii( "/" ) );
954 static rtl::OUString aHelpFilesBaseName( rtl::OUString::createFromAscii( "help" ) );
955 static rtl::OUString aHelpMediaType( rtl::OUString::createFromAscii( "application/vnd.sun.star.help" ) );
956 
957 ExtensionIteratorBase::ExtensionIteratorBase( const rtl::OUString& aLanguage )
958 		: m_eState( USER_EXTENSIONS )
959 		, m_aLanguage( aLanguage )
960 {
961 	init();
962 }
963 
964 void ExtensionIteratorBase::init()
965 {
966 	Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
967 	Reference< XPropertySet > xProps( xFactory, UNO_QUERY );
968 	OSL_ASSERT( xProps.is() );
969 	if (xProps.is())
970 	{
971 		xProps->getPropertyValue(
972 			::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= m_xContext;
973 		OSL_ASSERT( m_xContext.is() );
974 	}
975 	if( !m_xContext.is() )
976 	{
977 		throw RuntimeException(
978 			::rtl::OUString::createFromAscii( "ExtensionIteratorBase::init(), no XComponentContext" ),
979 			Reference< XInterface >() );
980 	}
981 
982 	Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager(), UNO_QUERY );
983 	m_xSFA = Reference< ucb::XSimpleFileAccess >(
984 		xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ),
985 		m_xContext ), UNO_QUERY_THROW );
986 
987 	m_bUserPackagesLoaded = false;
988 	m_bSharedPackagesLoaded = false;
989     m_bBundledPackagesLoaded = false;
990 	m_iUserPackage = 0;
991 	m_iSharedPackage = 0;
992     m_iBundledPackage = 0;
993 }
994 
995 Reference< deployment::XPackage > ExtensionIteratorBase::implGetHelpPackageFromPackage
996 	( Reference< deployment::XPackage > xPackage, Reference< deployment::XPackage >& o_xParentPackageBundle )
997 {
998 	o_xParentPackageBundle.clear();
999 
1000 	Reference< deployment::XPackage > xHelpPackage;
1001 	if( !xPackage.is() )
1002 		return xHelpPackage;
1003 
1004 	// Check if parent package is registered
1005     beans::Optional< beans::Ambiguous<sal_Bool> > option( xPackage->isRegistered
1006 		( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ) );
1007 	bool bRegistered = false;
1008     if( option.IsPresent )
1009     {
1010         beans::Ambiguous<sal_Bool> const & reg = option.Value;
1011         if( !reg.IsAmbiguous && reg.Value )
1012 			bRegistered = true;
1013     }
1014 	if( !bRegistered )
1015 		return xHelpPackage;
1016 
1017 	if( xPackage->isBundle() )
1018 	{
1019 		Sequence< Reference< deployment::XPackage > > aPkgSeq = xPackage->getBundle
1020 			( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() );
1021 		sal_Int32 nPkgCount = aPkgSeq.getLength();
1022 		const Reference< deployment::XPackage >* pSeq = aPkgSeq.getConstArray();
1023 		for( sal_Int32 iPkg = 0 ; iPkg < nPkgCount ; ++iPkg )
1024 		{
1025 			const Reference< deployment::XPackage > xSubPkg = pSeq[ iPkg ];
1026 			const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xSubPkg->getPackageType();
1027 			rtl::OUString aMediaType = xPackageTypeInfo->getMediaType();
1028 			if( aMediaType.equals( aHelpMediaType ) )
1029 			{
1030 				xHelpPackage = xSubPkg;
1031 				o_xParentPackageBundle = xPackage;
1032 				break;
1033 			}
1034 		}
1035 	}
1036 	else
1037 	{
1038 		const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xPackage->getPackageType();
1039 		rtl::OUString aMediaType = xPackageTypeInfo->getMediaType();
1040 		if( aMediaType.equals( aHelpMediaType ) )
1041 			xHelpPackage = xPackage;
1042 	}
1043 
1044 	return xHelpPackage;
1045 }
1046 
1047 Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextUserHelpPackage
1048 	( Reference< deployment::XPackage >& o_xParentPackageBundle )
1049 {
1050 	Reference< deployment::XPackage > xHelpPackage;
1051 
1052 	if( !m_bUserPackagesLoaded )
1053 	{
1054 		Reference< XPackageManager > xUserManager =
1055 			thePackageManagerFactory::get( m_xContext )->getPackageManager( rtl::OUString::createFromAscii("user") );
1056 		m_aUserPackagesSeq = xUserManager->getDeployedPackages
1057 			( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() );
1058 
1059 		m_bUserPackagesLoaded = true;
1060 	}
1061 
1062 	if( m_iUserPackage == m_aUserPackagesSeq.getLength() )
1063 	{
1064 		m_eState = SHARED_EXTENSIONS;		// Later: SHARED_MODULE
1065 	}
1066 	else
1067 	{
1068 		const Reference< deployment::XPackage >* pUserPackages = m_aUserPackagesSeq.getConstArray();
1069 		Reference< deployment::XPackage > xPackage = pUserPackages[ m_iUserPackage++ ];
1070 		VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextUserHelpPackage(): Invalid package" );
1071 		xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle );
1072 	}
1073 
1074 	return xHelpPackage;
1075 }
1076 
1077 Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextSharedHelpPackage
1078 	( Reference< deployment::XPackage >& o_xParentPackageBundle )
1079 {
1080 	Reference< deployment::XPackage > xHelpPackage;
1081 
1082 	if( !m_bSharedPackagesLoaded )
1083 	{
1084 		Reference< XPackageManager > xSharedManager =
1085 			thePackageManagerFactory::get( m_xContext )->getPackageManager( rtl::OUString::createFromAscii("shared") );
1086 		m_aSharedPackagesSeq = xSharedManager->getDeployedPackages
1087 			( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() );
1088 
1089 		m_bSharedPackagesLoaded = true;
1090 	}
1091 
1092 	if( m_iSharedPackage == m_aSharedPackagesSeq.getLength() )
1093 	{
1094 		m_eState = BUNDLED_EXTENSIONS;
1095 	}
1096 	else
1097 	{
1098 		const Reference< deployment::XPackage >* pSharedPackages = m_aSharedPackagesSeq.getConstArray();
1099 		Reference< deployment::XPackage > xPackage = pSharedPackages[ m_iSharedPackage++ ];
1100 		VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextSharedHelpPackage(): Invalid package" );
1101 		xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle );
1102 	}
1103 
1104 	return xHelpPackage;
1105 }
1106 
1107 Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextBundledHelpPackage
1108 	( Reference< deployment::XPackage >& o_xParentPackageBundle )
1109 {
1110 	Reference< deployment::XPackage > xHelpPackage;
1111 
1112 	if( !m_bBundledPackagesLoaded )
1113 	{
1114 		Reference< XPackageManager > xBundledManager =
1115 			thePackageManagerFactory::get( m_xContext )->getPackageManager( rtl::OUString::createFromAscii("bundled") );
1116 		m_aBundledPackagesSeq = xBundledManager->getDeployedPackages
1117 			( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() );
1118 
1119 		m_bBundledPackagesLoaded = true;
1120 	}
1121 
1122 	if( m_iBundledPackage == m_aBundledPackagesSeq.getLength() )
1123 	{
1124 		m_eState = END_REACHED;
1125 	}
1126 	else
1127 	{
1128 		const Reference< deployment::XPackage >* pBundledPackages = m_aBundledPackagesSeq.getConstArray();
1129 		Reference< deployment::XPackage > xPackage = pBundledPackages[ m_iBundledPackage++ ];
1130 		VOS_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextBundledHelpPackage(): Invalid package" );
1131 		xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle );
1132 	}
1133 
1134 	return xHelpPackage;
1135 }
1136 
1137 inline bool isLetter( sal_Unicode c )
1138 {
1139 	bool bLetter = ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
1140 	return bLetter;
1141 }
1142 
1143 void ExtensionIteratorBase::implGetLanguageVectorFromPackage( ::std::vector< ::rtl::OUString > &rv,
1144 	com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage )
1145 {
1146 	rv.clear();
1147 	rtl::OUString aExtensionPath = xPackage->getURL();
1148 	Sequence< rtl::OUString > aEntrySeq = m_xSFA->getFolderContents( aExtensionPath, true );
1149 
1150 	const rtl::OUString* pSeq = aEntrySeq.getConstArray();
1151     sal_Int32 nCount = aEntrySeq.getLength();
1152 	for( sal_Int32 i = 0 ; i < nCount ; ++i )
1153 	{
1154 		rtl::OUString aEntry = pSeq[i];
1155 		if( m_xSFA->isFolder( aEntry ) )
1156 		{
1157 			sal_Int32 nLastSlash = aEntry.lastIndexOf( '/' );
1158 			if( nLastSlash != -1 )
1159 			{
1160 				rtl::OUString aPureEntry = aEntry.copy( nLastSlash + 1 );
1161 
1162 				// Check language sceme
1163 				int nLen = aPureEntry.getLength();
1164 				const sal_Unicode* pc = aPureEntry.getStr();
1165 				bool bStartCanBeLanguage = ( nLen >= 2 && isLetter( pc[0] ) && isLetter( pc[1] ) );
1166 				bool bIsLanguage = bStartCanBeLanguage &&
1167 					( nLen == 2 || (nLen == 5 && pc[2] == '-' && isLetter( pc[3] ) && isLetter( pc[4] )) );
1168 				if( bIsLanguage )
1169 					rv.push_back( aPureEntry );
1170 			}
1171 		}
1172 	}
1173 }
1174 
1175 
1176 //===================================================================
1177 // class TreeFileIterator
1178 
1179 rtl::OUString TreeFileIterator::nextTreeFile( sal_Int32& rnFileSize )
1180 {
1181 	rtl::OUString aRetFile;
1182 
1183 	while( !aRetFile.getLength() && m_eState != END_REACHED )
1184 	{
1185 		switch( m_eState )
1186 		{
1187 			case USER_EXTENSIONS:
1188 			{
1189 				Reference< deployment::XPackage > xParentPackageBundle;
1190 				Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( xParentPackageBundle );
1191 				if( !xHelpPackage.is() )
1192 					break;
1193 
1194 				aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage );
1195 				break;
1196 			}
1197 
1198 			case SHARED_EXTENSIONS:
1199 			{
1200 				Reference< deployment::XPackage > xParentPackageBundle;
1201 				Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( xParentPackageBundle );
1202 				if( !xHelpPackage.is() )
1203 					break;
1204 
1205 				aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage );
1206 				break;
1207 			}
1208 			case BUNDLED_EXTENSIONS:
1209 			{
1210 				Reference< deployment::XPackage > xParentPackageBundle;
1211 				Reference< deployment::XPackage > xHelpPackage = implGetNextBundledHelpPackage( xParentPackageBundle );
1212 				if( !xHelpPackage.is() )
1213 					break;
1214 
1215 				aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage );
1216 				break;
1217 			}
1218 
1219         case END_REACHED:
1220 				VOS_ENSURE( false, "DataBaseIterator::nextTreeFile(): Invalid case END_REACHED" );
1221 				break;
1222 		}
1223 	}
1224 
1225 	return aRetFile;
1226 }
1227 
1228 rtl::OUString TreeFileIterator::expandURL( const rtl::OUString& aURL )
1229 {
1230 	static Reference< util::XMacroExpander > xMacroExpander;
1231 	static Reference< uri::XUriReferenceFactory > xFac;
1232 
1233 	osl::MutexGuard aGuard( m_aMutex );
1234 
1235 	if( !xMacroExpander.is() || !xFac.is() )
1236 	{
1237 		Reference< XMultiComponentFactory > xSMgr( m_xContext->getServiceManager(), UNO_QUERY );
1238 
1239 		xFac = Reference< uri::XUriReferenceFactory >(
1240 			xSMgr->createInstanceWithContext( rtl::OUString::createFromAscii(
1241 			"com.sun.star.uri.UriReferenceFactory"), m_xContext ) , UNO_QUERY );
1242 		if( !xFac.is() )
1243 		{
1244 			throw RuntimeException(
1245 				::rtl::OUString::createFromAscii( "Databases::expand(), could not instatiate UriReferenceFactory." ),
1246 				Reference< XInterface >() );
1247 		}
1248 
1249 		xMacroExpander = Reference< util::XMacroExpander >(
1250 			m_xContext->getValueByName(
1251 			::rtl::OUString::createFromAscii( "/singletons/com.sun.star.util.theMacroExpander" ) ),
1252 			UNO_QUERY_THROW );
1253  	}
1254 
1255 	rtl::OUString aRetURL = aURL;
1256 	if( xMacroExpander.is() )
1257 	{
1258 		Reference< uri::XUriReference > uriRef;
1259 		for (;;)
1260 		{
1261 			uriRef = Reference< uri::XUriReference >( xFac->parse( aRetURL ), UNO_QUERY );
1262 			if ( uriRef.is() )
1263 			{
1264 				Reference < uri::XVndSunStarExpandUrl > sxUri( uriRef, UNO_QUERY );
1265 				if( !sxUri.is() )
1266 					break;
1267 
1268 				aRetURL = sxUri->expand( xMacroExpander );
1269 			}
1270 		}
1271  	}
1272 	return aRetURL;
1273 }
1274 
1275 rtl::OUString TreeFileIterator::implGetTreeFileFromPackage
1276 	( sal_Int32& rnFileSize, Reference< deployment::XPackage > xPackage )
1277 {
1278 	rtl::OUString aRetFile;
1279 	rtl::OUString aLanguage = m_aLanguage;
1280 	for( sal_Int32 iPass = 0 ; iPass < 2 ; ++iPass )
1281 	{
1282 		rtl::OUStringBuffer aStrBuf;
1283 		aStrBuf.append( xPackage->getURL() );
1284 		aStrBuf.append( aSlash );
1285 		aStrBuf.append( aLanguage );
1286 		aStrBuf.append( aSlash );
1287 		aStrBuf.append( aHelpFilesBaseName );
1288 		aStrBuf.appendAscii( ".tree" );
1289 
1290 		aRetFile = expandURL( aStrBuf.makeStringAndClear() );
1291 		if( iPass == 0 )
1292 		{
1293 			if( m_xSFA->exists( aRetFile ) )
1294 				break;
1295 
1296 			::std::vector< ::rtl::OUString > av;
1297 			implGetLanguageVectorFromPackage( av, xPackage );
1298 			::std::vector< ::rtl::OUString >::const_iterator pFound = av.end();
1299 			try
1300 			{
1301 				pFound = ::comphelper::Locale::getFallback( av, m_aLanguage );
1302 			}
1303 			catch( ::comphelper::Locale::MalFormedLocaleException& )
1304 			{}
1305 			if( pFound != av.end() )
1306 				aLanguage = *pFound;
1307 		}
1308 	}
1309 
1310 	rnFileSize = 0;
1311 	if( m_xSFA->exists( aRetFile ) )
1312 		rnFileSize = m_xSFA->getSize( aRetFile );
1313 	else
1314 		aRetFile = rtl::OUString();
1315 
1316 	return aRetFile;
1317 }
1318 
1319 
1320 
1321