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