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