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