1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <osl/diagnose.h>
22 #include <osl/thread.h>
23 #include <osl/process.h>
24 #include <rtl/uri.hxx>
25 #include <osl/file.hxx>
26 #include <com/sun/star/lang/Locale.hpp>
27 #include <com/sun/star/awt/Toolkit.hpp>
28 #include <com/sun/star/i18n/Collator.hpp>
29 #include <rtl/ustrbuf.hxx>
30 #include "inputstream.hxx"
35 #include <helpcompiler/HelpIndexer.hxx>
38 #include <com/sun/star/deployment/ExtensionManager.hpp>
39 #include <com/sun/star/deployment/thePackageManagerFactory.hpp>
40 #include <comphelper/processfactory.hxx>
41 #include <com/sun/star/uno/XComponentContext.hpp>
42 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
43 #include <com/sun/star/beans/Optional.hpp>
44 #include <com/sun/star/beans/PropertyValue.hpp>
45 #include <com/sun/star/beans/NamedValue.hpp>
46 #include <com/sun/star/configuration/theDefaultProvider.hpp>
47 #include <com/sun/star/frame/XConfigManager.hpp>
48 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
49 #include <com/sun/star/util/theMacroExpander.hpp>
50 #include <com/sun/star/uri/UriReferenceFactory.hpp>
51 #include <com/sun/star/uri/XVndSunStarExpandUrl.hpp>
52 #include <com/sun/star/script/XInvocation.hpp>
53 #include <i18nlangtag/languagetag.hxx>
55 #include <com/sun/star/awt/XToolkit.hpp>
56 #include <com/sun/star/awt/XExtendedToolkit.hpp>
57 #include <com/sun/star/awt/XWindowPeer.hpp>
58 #include <com/sun/star/awt/XVclWindowPeer.hpp>
59 #include <com/sun/star/awt/XTopWindow.hpp>
61 #include <comphelper/storagehelper.hxx>
62 #include <comphelper/string.hxx>
64 #include <vcl/svapp.hxx>
66 #include "databases.hxx"
67 #include "urlparameter.hxx"
73 using namespace chelp
;
74 using namespace com::sun::star
;
75 using namespace com::sun::star::uno
;
76 using namespace com::sun::star::io
;
77 using namespace com::sun::star::container
;
78 using namespace com::sun::star::i18n
;
79 using namespace com::sun::star::lang
;
80 using namespace com::sun::star::deployment
;
81 using namespace com::sun::star::beans
;
83 OUString
Databases::expandURL( const OUString
& aURL
)
85 osl::MutexGuard
aGuard( m_aMutex
);
86 OUString aRetURL
= expandURL( aURL
, m_xContext
);
90 OUString
Databases::expandURL( const OUString
& aURL
, Reference
< uno::XComponentContext
> xContext
)
92 static Reference
< util::XMacroExpander
> xMacroExpander
;
93 static Reference
< uri::XUriReferenceFactory
> xFac
;
95 if( !xMacroExpander
.is() || !xFac
.is() )
97 xFac
= uri::UriReferenceFactory::create( xContext
);
99 xMacroExpander
= util::theMacroExpander::get(xContext
);
102 OUString aRetURL
= aURL
;
103 if( xMacroExpander
.is() )
105 Reference
< uri::XUriReference
> uriRef
;
108 uriRef
= Reference
< uri::XUriReference
>( xFac
->parse( aRetURL
), UNO_QUERY
);
111 Reference
< uri::XVndSunStarExpandUrl
> sxUri( uriRef
, UNO_QUERY
);
115 aRetURL
= sxUri
->expand( xMacroExpander
);
122 Databases::Databases( bool showBasic
,
123 const OUString
& instPath
,
124 const OUString
& productName
,
125 const OUString
& productVersion
,
126 const OUString
& styleSheet
,
127 Reference
< uno::XComponentContext
> xContext
)
128 : m_xContext( xContext
),
129 m_bShowBasic(showBasic
),
131 m_nCustomCSSDocLength( 0 ),
132 m_pCustomCSSDoc( 0 ),
133 m_aCSS(styleSheet
.toAsciiLowerCase()),
134 newProdName( "$[officename]" ),
135 newProdVersion( "$[officeversion]" ),
136 prodName( "%PRODUCTNAME" ),
137 prodVersion( "%PRODUCTVERSION" ),
138 vendName( "%VENDORNAME" ),
139 vendVersion( "%VENDORVERSION" ),
140 vendShort( "%VENDORSHORT" )
142 m_xSMgr
= Reference
< XMultiComponentFactory
>( m_xContext
->getServiceManager(), UNO_QUERY
);
152 m_vReplacement
[0] = productName
;
153 m_vReplacement
[1] = productVersion
;
154 // m_vReplacement[2...4] (vendorName/-Version/-Short) are empty strings
155 m_vReplacement
[5] = productName
;
156 m_vReplacement
[6] = productVersion
;
158 setInstallPath( instPath
);
160 m_xSFA
= ucb::SimpleFileAccess::create(m_xContext
);
163 Databases::~Databases()
165 // release stylesheet
167 delete[] m_pCustomCSSDoc
;
169 // release errorDocument
171 delete[] m_pErrorDoc
;
173 // unload the databases
177 DatabasesTable::iterator it
= m_aDatabases
.begin();
178 while( it
!= m_aDatabases
.end() )
188 ModInfoTable::iterator it
= m_aModInfo
.begin();
189 while( it
!= m_aModInfo
.end() )
199 KeywordInfoTable::iterator it
= m_aKeywordInfo
.begin();
200 while( it
!= m_aKeywordInfo
.end() )
208 OString
Databases::getImageTheme()
210 uno::Reference
< lang::XMultiServiceFactory
> xConfigProvider
=
211 configuration::theDefaultProvider::get(m_xContext
);
214 uno::Sequence
< uno::Any
> lParams(1);
215 beans::PropertyValue aParam
;
216 aParam
.Name
= "nodepath";
217 aParam
.Value
<<= OUString("org.openoffice.Office.Common");
218 lParams
[0] = uno::makeAny(aParam
);
221 uno::Reference
< uno::XInterface
> xCFG( xConfigProvider
->createInstanceWithArguments(
222 OUString("com.sun.star.configuration.ConfigurationAccess"),
225 uno::Reference
< container::XHierarchicalNameAccess
> xAccess(xCFG
, uno::UNO_QUERY_THROW
);
226 uno::Any aResult
= xAccess
->getByHierarchicalName(OUString("Misc/SymbolStyle"));
227 OUString aSymbolsStyleName
;
228 aResult
>>= aSymbolsStyleName
;
230 if ( aSymbolsStyleName
.isEmpty() || aSymbolsStyleName
== "auto" )
232 aSymbolsStyleName
= "tango";
234 return aSymbolsStyleName
.toUtf8();
237 void Databases::replaceName( OUString
& oustring
) const
239 sal_Int32 idx
= -1,idx1
= -1,idx2
= -1,k
= 0,off
;
241 OUStringBuffer
aStrBuf( 0 );
246 idx1
= oustring
.indexOf( '%', idx
);
247 idx2
= oustring
.indexOf( '$', idx
);
249 if(idx1
== -1 && idx2
== -1)
260 else if(idx2
< idx1
)
264 if( oustring
.indexOf( prodName
,idx
) == idx
)
266 else if( oustring
.indexOf( prodVersion
,idx
) == idx
)
267 off
= PRODUCTVERSION
;
268 else if( oustring
.indexOf( vendName
,idx
) == idx
)
270 else if( oustring
.indexOf( vendVersion
,idx
) == idx
)
272 else if( oustring
.indexOf( vendShort
,idx
) == idx
)
274 else if( oustring
.indexOf( newProdName
,idx
) == idx
)
275 off
= NEWPRODUCTNAME
;
276 else if( oustring
.indexOf( newProdVersion
,idx
) == idx
)
277 off
= NEWPRODUCTVERSION
;
286 aStrBuf
.ensureCapacity( 256 );
289 aStrBuf
.append( &oustring
.getStr()[k
],idx
- k
);
290 aStrBuf
.append( m_vReplacement
[off
] );
291 k
= idx
+ m_vAdd
[off
];
297 if( k
< oustring
.getLength() )
298 aStrBuf
.append( &oustring
.getStr()[k
],oustring
.getLength()-k
);
299 oustring
= aStrBuf
.makeStringAndClear();
303 OUString
Databases::getInstallPathAsURL()
305 osl::MutexGuard
aGuard( m_aMutex
);
307 return m_aInstallDirectory
;
310 const std::vector
< OUString
>& Databases::getModuleList( const OUString
& Language
)
312 if( m_avModules
.empty() )
314 OUString fileName
,dirName
= getInstallPathAsURL() + processLang( Language
);
315 osl::Directory
dirFile( dirName
);
317 osl::DirectoryItem aDirItem
;
318 osl::FileStatus
aStatus( osl_FileStatus_Mask_FileName
);
322 if( osl::FileBase::E_None
!= dirFile
.open() )
325 while( dirFile
.getNextItem( aDirItem
) == osl::FileBase::E_None
&&
326 aDirItem
.getFileStatus( aStatus
) == osl::FileBase::E_None
)
328 if( ! aStatus
.isValid( osl_FileStatus_Mask_FileName
) )
331 fileName
= aStatus
.getFileName();
333 // Check, whether fileName is of the form *.cfg
334 idx
= fileName
.lastIndexOf( '.' );
339 const sal_Unicode
* str
= fileName
.getStr();
341 if( fileName
.getLength() == idx
+ 4 &&
342 ( str
[idx
+ 1] == 'c' || str
[idx
+ 1] == 'C' ) &&
343 ( str
[idx
+ 2] == 'f' || str
[idx
+ 2] == 'F' ) &&
344 ( str
[idx
+ 3] == 'g' || str
[idx
+ 3] == 'G' ) &&
345 ( fileName
= fileName
.copy(0,idx
).toAsciiLowerCase() ) != "picture" ) {
346 if(! m_bShowBasic
&& fileName
== "sbasic" )
348 m_avModules
.push_back( fileName
);
355 StaticModuleInformation
* Databases::getStaticInformationForModule( const OUString
& Module
,
356 const OUString
& Language
)
358 osl::MutexGuard
aGuard( m_aMutex
);
360 OUString key
= processLang(Language
) + "/" + Module
;
362 std::pair
< ModInfoTable::iterator
,bool > aPair
=
363 m_aModInfo
.insert( ModInfoTable::value_type( key
,(StaticModuleInformation
*)0 ) );
365 ModInfoTable::iterator it
= aPair
.first
;
367 if( aPair
.second
&& ! it
->second
)
369 osl::File
cfgFile( getInstallPathAsURL() + key
+ ".cfg" );
371 if( osl::FileBase::E_None
!= cfgFile
.open( osl_File_OpenFlag_Read
) )
377 sal_Char buffer
[2048];
378 sal_Unicode lineBuffer
[1028];
379 OUString fileContent
;
381 while( osl::FileBase::E_None
== cfgFile
.read( &buffer
,2048,nRead
) && nRead
)
382 fileContent
+= OUString( buffer
,sal_Int32( nRead
),RTL_TEXTENCODING_UTF8
);
386 const sal_Unicode
* str
= fileContent
.getStr();
387 OUString current
,lang_
,program
,startid
,title
,heading
,fulltext
;
388 OUString
order( "1" );
390 for( sal_Int32 i
= 0;i
< fileContent
.getLength();i
++ )
392 sal_Unicode ch
= str
[ i
];
393 if( ch
== '\n' || ch
== '\r' )
397 current
= OUString( lineBuffer
,pos
);
399 if( current
.startsWith("Title") )
401 title
= current
.copy( current
.indexOf( '=' ) + 1 );
403 else if( current
.startsWith("Start") )
405 startid
= current
.copy( current
.indexOf('=') + 1 );
407 else if( current
.startsWith("Language") )
409 lang_
= current
.copy( current
.indexOf('=') + 1 );
411 else if( current
.startsWith("Program") )
413 program
= current
.copy( current
.indexOf('=') + 1 );
415 else if( current
.startsWith("Heading") )
417 heading
= current
.copy( current
.indexOf('=') + 1 );
419 else if( current
.startsWith("FullText") )
421 fulltext
= current
.copy( current
.indexOf('=') + 1 );
423 else if( current
.startsWith("Order") )
425 order
= current
.copy( current
.indexOf('=') + 1 );
431 lineBuffer
[ pos
++ ] = ch
;
433 replaceName( title
);
434 it
->second
= new StaticModuleInformation( title
,
446 OUString
Databases::processLang( const OUString
& Language
)
448 osl::MutexGuard
aGuard( m_aMutex
);
451 LangSetTable::iterator it
= m_aLangSet
.find( Language
);
453 if( it
== m_aLangSet
.end() )
456 osl::DirectoryItem aDirItem
;
458 if( osl::FileBase::E_None
== osl::DirectoryItem::get( getInstallPathAsURL() + Language
,aDirItem
) )
461 m_aLangSet
[ Language
] = ret
;
463 else if( ( ( idx
= Language
.indexOf( '-' ) ) != -1 ||
464 ( idx
= Language
.indexOf( '_' ) ) != -1 ) &&
465 osl::FileBase::E_None
== osl::DirectoryItem::get( getInstallPathAsURL() + Language
.copy( 0,idx
),
468 ret
= Language
.copy( 0,idx
);
469 m_aLangSet
[ Language
] = ret
;
478 OUString
Databases::country( const OUString
& Language
)
481 if( ( idx
= Language
.indexOf( '-' ) ) != -1 ||
482 ( idx
= Language
.indexOf( '_' ) ) != -1 )
483 return Language
.copy( 1+idx
);
488 helpdatafileproxy::Hdf
* Databases::getHelpDataFile( const OUString
& Database
,
489 const OUString
& Language
, bool helpText
,
490 const OUString
* pExtensionPath
)
492 if( Database
.isEmpty() || Language
.isEmpty() )
495 osl::MutexGuard
aGuard( m_aMutex
);
497 OUString
aFileExt( helpText
? OUString(".ht") : OUString(".db") );
498 OUString dbFileName
= "/" + Database
+ aFileExt
;
500 if( pExtensionPath
== NULL
)
501 key
= processLang( Language
) + dbFileName
;
503 key
= *pExtensionPath
+ Language
+ dbFileName
; // make unique, don't change language
505 std::pair
< DatabasesTable::iterator
,bool > aPair
=
506 m_aDatabases
.insert( DatabasesTable::value_type( key
, reinterpret_cast<helpdatafileproxy::Hdf
*>(0) ) );
508 DatabasesTable::iterator it
= aPair
.first
;
510 if( aPair
.second
&& ! it
->second
)
512 helpdatafileproxy::Hdf
* pHdf
= 0;
516 fileURL
= expandURL(*pExtensionPath
) + Language
+ dbFileName
;
518 fileURL
= getInstallPathAsURL() + key
;
520 OUString
fileNameHDFHelp( fileURL
);
521 //Extensions always use the new format
522 if( pExtensionPath
!= NULL
)
523 fileNameHDFHelp
+= "_";
524 //SimpleFileAccess takes file URLs as arguments!!! Using filenames works accidentally but
525 //fails for example when using long path names on Windows (starting with \\?\)
526 if( m_xSFA
->exists( fileNameHDFHelp
) )
528 pHdf
= new helpdatafileproxy::Hdf( fileNameHDFHelp
, m_xSFA
);
537 Reference
< XCollator
>
538 Databases::getCollator( const OUString
& Language
,
539 const OUString
& System
)
543 OUString key
= Language
;
545 osl::MutexGuard
aGuard( m_aMutex
);
547 CollatorTable::iterator it
=
548 m_aCollatorTable
.insert( CollatorTable::value_type( key
, Reference
< XCollator
>() ) ).first
;
550 if( ! it
->second
.is() )
552 it
->second
= Collator::create(m_xContext
);
553 OUString langStr
= processLang(Language
);
554 OUString countryStr
= country(Language
);
555 if( countryStr
.isEmpty() )
557 if( langStr
== "de" )
559 else if( langStr
== "en" )
561 else if( langStr
== "es" )
563 else if( langStr
== "it" )
565 else if( langStr
== "fr" )
567 else if( langStr
== "sv" )
569 else if( langStr
== "ja" )
571 else if( langStr
== "ko" )
574 /* FIXME-BCP47: all this does not look right for language tag context,
575 * also check processLang() and country() methods */
576 it
->second
->loadDefaultCollator( Locale( langStr
,
587 struct KeywordElementComparator
589 KeywordElementComparator( const Reference
< XCollator
>& xCollator
)
590 : m_xCollator( xCollator
)
593 bool operator()( const KeywordInfo::KeywordElement
& la
,
594 const KeywordInfo::KeywordElement
& ra
) const
596 const OUString
& l
= la
.key
;
597 const OUString
& r
= ra
.key
;
601 if( m_xCollator
.is() )
603 sal_Int32 l1
= l
.indexOf( ';' );
604 sal_Int32 l3
= ( l1
== -1 ? l
.getLength() : l1
);
606 sal_Int32 r1
= r
.indexOf( ';' );
607 sal_Int32 r3
= ( r1
== -1 ? r
.getLength() : r1
);
609 sal_Int32 c1
= m_xCollator
->compareSubstring( l
,0,l3
,r
,0,r3
);
615 sal_Int32 l2
= l
.getLength() - l1
- 1;
616 sal_Int32 r2
= r
.getLength() - r1
- 1;
617 ret
= ( m_xCollator
->compareSubstring( l
,1+l1
,l2
,r
,1+r1
,r2
) < 0 );
628 Reference
< XCollator
> m_xCollator
;
629 }; // end struct KeywordElementComparator
633 KeywordInfo::KeywordElement::KeywordElement( Databases
*pDatabases
,
634 helpdatafileproxy::Hdf
* pHdf
,
639 pDatabases
->replaceName( key
);
640 init( pDatabases
,pHdf
,data
);
643 void KeywordInfo::KeywordElement::init( Databases
*pDatabases
,helpdatafileproxy::Hdf
* pHdf
,const OUString
& ids
)
645 const sal_Unicode
* idstr
= ids
.getStr();
646 std::vector
< OUString
> id
,anchor
;
648 while( ( idx
= ids
.indexOf( ';',k
= ++idx
) ) != -1 )
650 int h
= ids
.indexOf( '#', k
);
654 id
.push_back( OUString( &idstr
[k
],h
-k
) );
655 anchor
.push_back( OUString( &idstr
[h
+1],idx
-h
-1 ) );
659 id
.push_back( OUString( &idstr
[k
],idx
-k
) );
660 anchor
.push_back( OUString() );
664 listId
.realloc( id
.size() );
665 listAnchor
.realloc( id
.size() );
666 listTitle
.realloc( id
.size() );
668 for( sal_uInt32 i
= 0; i
< id
.size(); ++i
)
671 listAnchor
[i
] = anchor
[i
];
673 helpdatafileproxy::HDFData aHDFData
;
674 const sal_Char
* pData
= NULL
;
678 OString
idi( id
[i
].getStr(),id
[i
].getLength(),RTL_TEXTENCODING_UTF8
);
679 bool bSuccess
= pHdf
->getValueForKey( idi
, aHDFData
);
681 pData
= aHDFData
.getData();
684 DbtToStringConverter
converter( pData
);
686 OUString title
= converter
.getTitle();
687 pDatabases
->replaceName( title
);
688 listTitle
[i
] = title
;
692 KeywordInfo::KeywordInfo( const std::vector
< KeywordElement
>& aVec
)
693 : listKey( aVec
.size() ),
694 listId( aVec
.size() ),
695 listAnchor( aVec
.size() ),
696 listTitle( aVec
.size() )
698 for( unsigned int i
= 0; i
< aVec
.size(); ++i
)
700 listKey
[i
] = aVec
[i
].key
;
701 listId
[i
] = aVec
[i
].listId
;
702 listAnchor
[i
] = aVec
[i
].listAnchor
;
703 listTitle
[i
] = aVec
[i
].listTitle
;
707 bool Databases::checkModuleMatchForExtension
708 ( const OUString
& Database
, const OUString
& doclist
)
710 bool bBelongsToDatabase
= true;
712 // Analyse doclist string to find module assignments
713 bool bFoundAtLeastOneModule
= false;
714 bool bModuleMatch
= false;
715 sal_Int32 nLen
= doclist
.getLength();
716 sal_Int32 nLastFound
= doclist
.lastIndexOf( ';' );
717 if( nLastFound
== -1 )
719 const sal_Unicode
* pStr
= doclist
.getStr();
720 sal_Int32 nFound
= doclist
.lastIndexOf( '_' );
721 while( nFound
!= -1 )
723 // Simple optimization, stop if '_' is followed by "id"
724 if( nLen
- nFound
> 2 )
726 if( pStr
[ nFound
+ 1 ] == 'i' &&
727 pStr
[ nFound
+ 2 ] == 'd' )
731 OUString aModule
= doclist
.copy( nFound
+ 1, nLastFound
- nFound
- 1 );
732 std::vector
< OUString
>::iterator result
= std::find( m_avModules
.begin(), m_avModules
.end(), aModule
);
733 if( result
!= m_avModules
.end() )
735 bFoundAtLeastOneModule
= true;
736 if( Database
== aModule
)
744 if( nLastFound
== 0 )
746 nFound
= doclist
.lastIndexOf( '_', nLastFound
- 1 );
749 if( bFoundAtLeastOneModule
&& !bModuleMatch
)
750 bBelongsToDatabase
= false;
752 return bBelongsToDatabase
;
755 KeywordInfo
* Databases::getKeyword( const OUString
& Database
,
756 const OUString
& Language
)
758 osl::MutexGuard
aGuard( m_aMutex
);
760 OUString key
= processLang(Language
) + "/" + Database
;
762 std::pair
< KeywordInfoTable::iterator
,bool > aPair
=
763 m_aKeywordInfo
.insert( KeywordInfoTable::value_type( key
,(KeywordInfo
*)0 ) );
765 KeywordInfoTable::iterator it
= aPair
.first
;
767 if( aPair
.second
&& ! it
->second
)
769 std::vector
<KeywordInfo::KeywordElement
> aVector
;
771 KeyDataBaseFileIterator
aDbFileIt( m_xContext
, *this, Database
, Language
);
773 bool bExtension
= false;
774 while( !(fileURL
= aDbFileIt
.nextDbFile( bExtension
)).isEmpty() )
776 OUString
fileNameHDFHelp( fileURL
);
778 fileNameHDFHelp
+= "_";
779 if( m_xSFA
->exists( fileNameHDFHelp
) )
781 helpdatafileproxy::Hdf
aHdf( fileNameHDFHelp
, m_xSFA
);
782 helpdatafileproxy::HDFData aKey
;
783 helpdatafileproxy::HDFData aValue
;
784 if( aHdf
.startIteration() )
786 helpdatafileproxy::Hdf
* pHdf
= getHelpDataFile( Database
,Language
);
789 bool bOptimizeForPerformance
= true;
790 pHdf
->releaseHashMap();
791 pHdf
->createHashMap( bOptimizeForPerformance
);
794 while( aHdf
.getNextKeyAndValue( aKey
, aValue
) )
796 OUString
keyword( aKey
.getData(), aKey
.getSize(),
797 RTL_TEXTENCODING_UTF8
);
798 OUString
doclist( aValue
.getData(), aValue
.getSize(),
799 RTL_TEXTENCODING_UTF8
);
801 bool bBelongsToDatabase
= true;
803 bBelongsToDatabase
= checkModuleMatchForExtension( Database
, doclist
);
805 if( !bBelongsToDatabase
)
808 aVector
.push_back( KeywordInfo::KeywordElement( this,
813 aHdf
.stopIteration();
816 pHdf
->releaseHashMap();
822 Reference
< XCollator
> xCollator
= getCollator( Language
,OUString());
823 KeywordElementComparator
aComparator( xCollator
);
824 std::sort(aVector
.begin(),aVector
.end(),aComparator
);
826 KeywordInfo
* pInfo
= it
->second
= new KeywordInfo( aVector
);
833 Reference
< XHierarchicalNameAccess
> Databases::jarFile( const OUString
& jar
,
834 const OUString
& Language
)
836 if( jar
.isEmpty() || Language
.isEmpty() )
838 return Reference
< XHierarchicalNameAccess
>( 0 );
840 OUString key
= processLang(Language
) + "/" + jar
;
842 osl::MutexGuard
aGuard( m_aMutex
);
844 ZipFileTable::iterator it
=
845 m_aZipFileTable
.insert( ZipFileTable::value_type( key
,Reference
< XHierarchicalNameAccess
>(0) ) ).first
;
847 if( ! it
->second
.is() )
852 // Extension jar file? Search for ?
853 sal_Int32 nQuestionMark1
= jar
.indexOf( '?' );
854 sal_Int32 nQuestionMark2
= jar
.lastIndexOf( '?' );
855 if( nQuestionMark1
!= -1 && nQuestionMark2
!= -1 && nQuestionMark1
!= nQuestionMark2
)
857 OUString aExtensionPath
= jar
.copy( nQuestionMark1
+ 1, nQuestionMark2
- nQuestionMark1
- 1 );
858 OUString aPureJar
= jar
.copy( nQuestionMark2
+ 1 );
860 zipFile
= expandURL( aExtensionPath
+ "/" + aPureJar
);
864 zipFile
= getInstallPathAsURL() + key
;
867 Sequence
< Any
> aArguments( 2 );
869 XInputStream_impl
* p
= new XInputStream_impl( zipFile
);
870 if( p
->CtorSuccess() )
872 Reference
< XInputStream
> xInputStream( p
);
873 aArguments
[ 0 ] <<= xInputStream
;
878 aArguments
[ 0 ] <<= zipFile
;
881 // let ZipPackage be used ( no manifest.xml is required )
882 beans::NamedValue aArg
;
883 aArg
.Name
= "StorageFormat";
884 aArg
.Value
<<= OUString(ZIP_STORAGE_FORMAT_STRING
);
885 aArguments
[ 1 ] <<= aArg
;
887 Reference
< XInterface
> xIfc
888 = m_xSMgr
->createInstanceWithArgumentsAndContext(
890 "com.sun.star.packages.comp.ZipPackage" ),
891 aArguments
, m_xContext
);
895 it
->second
= Reference
< XHierarchicalNameAccess
>( xIfc
, UNO_QUERY
);
897 OSL_ENSURE( it
->second
.is(),
898 "ContentProvider::createPackage - "
899 "Got no hierarchical name access!" );
903 catch ( RuntimeException
& )
906 catch ( Exception
& )
914 Reference
< XHierarchicalNameAccess
> Databases::findJarFileForPath
915 ( const OUString
& jar
, const OUString
& Language
,
916 const OUString
& path
, OUString
* o_pExtensionPath
,
917 OUString
* o_pExtensionRegistryPath
)
919 Reference
< XHierarchicalNameAccess
> xNA
;
920 if( jar
.isEmpty() || Language
.isEmpty() )
925 JarFileIterator
aJarFileIt( m_xContext
, *this, jar
, Language
);
926 Reference
< XHierarchicalNameAccess
> xTestNA
;
927 Reference
< deployment::XPackage
> xParentPackageBundle
;
928 while( (xTestNA
= aJarFileIt
.nextJarFile( xParentPackageBundle
, o_pExtensionPath
, o_pExtensionRegistryPath
)).is() )
930 if( xTestNA
.is() && xTestNA
->hasByHierarchicalName( path
) )
932 bool bSuccess
= true;
933 if( xParentPackageBundle
.is() )
935 OUString aIdentifierInPath
;
936 sal_Int32 nFindSlash
= path
.indexOf( '/' );
937 if( nFindSlash
!= -1 )
938 aIdentifierInPath
= path
.copy( 0, nFindSlash
);
940 beans::Optional
<OUString
> aIdentifierOptional
= xParentPackageBundle
->getIdentifier();
941 if( !aIdentifierInPath
.isEmpty() && aIdentifierOptional
.IsPresent
)
943 OUString aUnencodedIdentifier
= aIdentifierOptional
.Value
;
944 OUString aIdentifier
= rtl::Uri::encode( aUnencodedIdentifier
,
945 rtl_UriCharClassPchar
, rtl_UriEncodeIgnoreEscapes
, RTL_TEXTENCODING_UTF8
);
947 if( !aIdentifierInPath
.equals( aIdentifier
) )
949 // path does not start with extension identifier -> ignore
955 // No identifier -> ignore
971 void Databases::changeCSS(const OUString
& newStyleSheet
)
973 m_aCSS
= newStyleSheet
.toAsciiLowerCase();
974 delete[] m_pCustomCSSDoc
, m_pCustomCSSDoc
= 0,m_nCustomCSSDocLength
= 0;
977 void Databases::cascadingStylesheet( const OUString
& Language
,
981 if( ! m_pCustomCSSDoc
)
987 bool bHighContrastMode
= false;
988 OUString
aCSS( m_aCSS
);
989 if ( aCSS
== "default" )
991 // #i50760: "default" needs to adapt HC mode
992 uno::Reference
< awt::XToolkit2
> xToolkit
=
993 awt::Toolkit::create( ::comphelper::getProcessComponentContext() );
994 uno::Reference
< awt::XTopWindow
> xTopWindow
= xToolkit
->getActiveTopWindow();
995 if ( xTopWindow
.is() )
997 uno::Reference
< awt::XVclWindowPeer
> xVclWindowPeer( xTopWindow
, uno::UNO_QUERY
);
998 if ( xVclWindowPeer
.is() )
1000 uno::Any aHCMode
= xVclWindowPeer
->getProperty( OUString( "HighContrastMode" ) );
1001 if ( ( aHCMode
>>= bHighContrastMode
) && bHighContrastMode
)
1003 aCSS
= "highcontrastblack";
1006 LONG lResult
= RegOpenKeyExA( HKEY_CURRENT_USER
, "Control Panel\\Accessibility\\HighContrast", 0, KEY_QUERY_VALUE
, &hKey
);
1007 if ( ERROR_SUCCESS
== lResult
)
1009 CHAR szBuffer
[1024];
1010 DWORD nSize
= sizeof( szBuffer
);
1011 lResult
= RegQueryValueExA( hKey
, "High Contrast Scheme", NULL
, NULL
, (LPBYTE
)szBuffer
, &nSize
);
1012 if ( ERROR_SUCCESS
== lResult
&& nSize
> 0 )
1014 szBuffer
[nSize
] = '\0';
1015 if ( strncmp( szBuffer
, "High Contrast #1", strlen("High Contrast #1") ) == 0 )
1016 aCSS
= "highcontrast1";
1017 if ( strncmp( szBuffer
, "High Contrast #2", strlen("High Contrast #2") ) == 0 )
1018 aCSS
= "highcontrast2";
1019 if ( strncmp( szBuffer
, "High Contrast White", strlen("High Contrast White") ) == 0 )
1020 aCSS
= "highcontrastwhite";
1022 RegCloseKey( hKey
);
1030 while( error
&& retry
)
1035 getInstallPathAsURL() +
1036 processLang( Language
) +
1040 else if( retry
== 1 )
1042 getInstallPathAsURL() +
1046 osl::DirectoryItem aDirItem
;
1047 osl::File
aFile( fileURL
);
1048 osl::FileStatus
aStatus( osl_FileStatus_Mask_FileSize
);
1050 if( osl::FileBase::E_None
== osl::DirectoryItem::get( fileURL
,aDirItem
) &&
1051 osl::FileBase::E_None
== aFile
.open( osl_File_OpenFlag_Read
) &&
1052 osl::FileBase::E_None
== aDirItem
.getFileStatus( aStatus
) )
1055 aFile
.getSize( nSize
);
1056 m_nCustomCSSDocLength
= (int)nSize
;
1057 m_pCustomCSSDoc
= new char[ 1 + m_nCustomCSSDocLength
];
1058 m_pCustomCSSDoc
[ m_nCustomCSSDocLength
] = 0;
1059 sal_uInt64 a
= m_nCustomCSSDocLength
,b
= m_nCustomCSSDocLength
;
1060 aFile
.read( m_pCustomCSSDoc
,a
,b
);
1066 if ( !retry
&& error
&& bHighContrastMode
)
1068 // fall back to default css
1071 bHighContrastMode
= false;
1077 m_nCustomCSSDocLength
= 0;
1078 m_pCustomCSSDoc
= new char[ 1 ]; // Initialize with 1 to avoid gcc compiler warning
1082 *byteCount
= m_nCustomCSSDocLength
;
1083 *buffer
= new char[ 1 + *byteCount
];
1084 (*buffer
)[*byteCount
] = 0;
1085 memcpy( *buffer
,m_pCustomCSSDoc
,m_nCustomCSSDocLength
);
1089 void Databases::setActiveText( const OUString
& Module
,
1090 const OUString
& Language
,
1095 DataBaseIterator
aDbIt( m_xContext
, *this, Module
, Language
, true );
1097 // #i84550 Cache information about failed ids
1098 OString
id( Id
.getStr(),Id
.getLength(),RTL_TEXTENCODING_UTF8
);
1099 EmptyActiveTextSet::iterator it
= m_aEmptyActiveTextSet
.find( id
);
1100 bool bFoundAsEmpty
= ( it
!= m_aEmptyActiveTextSet
.end() );
1101 helpdatafileproxy::HDFData aHDFData
;
1104 const sal_Char
* pData
= NULL
;
1106 bool bSuccess
= false;
1107 if( !bFoundAsEmpty
)
1109 helpdatafileproxy::Hdf
* pHdf
= 0;
1110 while( !bSuccess
&& (pHdf
= aDbIt
.nextHdf()) != NULL
)
1112 bSuccess
= pHdf
->getValueForKey( id
, aHDFData
);
1113 nSize
= aHDFData
.getSize();
1114 pData
= aHDFData
.getData();
1120 // ensure existence of tmp after for
1122 for( int i
= 0; i
< nSize
; ++i
)
1123 if( pData
[i
] == '%' || pData
[i
] == '$' )
1125 // need of replacement
1126 OUString temp
= OUString( pData
, nSize
, RTL_TEXTENCODING_UTF8
);
1127 replaceName( temp
);
1128 tmp
= OString( temp
.getStr(),
1130 RTL_TEXTENCODING_UTF8
);
1131 nSize
= tmp
.getLength();
1132 pData
= tmp
.getStr();
1137 *buffer
= new char[ 1 + nSize
];
1138 (*buffer
)[nSize
] = 0;
1139 memcpy( *buffer
, pData
, nSize
);
1144 *buffer
= new char[1]; // Initialize with 1 to avoid compiler warnings
1145 if( !bFoundAsEmpty
)
1146 m_aEmptyActiveTextSet
.insert( id
);
1150 void Databases::setInstallPath( const OUString
& aInstDir
)
1152 osl::MutexGuard
aGuard( m_aMutex
);
1154 osl::FileBase::getFileURLFromSystemPath( aInstDir
,m_aInstallDirectory
);
1155 //TODO: check returned error code
1157 if( !m_aInstallDirectory
.endsWith( "/" ) )
1158 m_aInstallDirectory
+= "/";
1161 // class ExtensionIteratorBase
1163 ExtensionHelpExistanceMap
ExtensionIteratorBase::aHelpExistanceMap
;
1165 ExtensionIteratorBase::ExtensionIteratorBase( Reference
< XComponentContext
> xContext
,
1166 Databases
& rDatabases
, const OUString
& aInitialModule
, const OUString
& aLanguage
)
1167 : m_xContext( xContext
)
1168 , m_rDatabases( rDatabases
)
1169 , m_eState( INITIAL_MODULE
)
1170 , m_aInitialModule( aInitialModule
)
1171 , m_aLanguage( aLanguage
)
1173 assert( m_xContext
.is() );
1177 ExtensionIteratorBase::ExtensionIteratorBase( Databases
& rDatabases
,
1178 const OUString
& aInitialModule
, const OUString
& aLanguage
)
1179 : m_xContext( comphelper::getProcessComponentContext() )
1180 , m_rDatabases( rDatabases
)
1181 , m_eState( INITIAL_MODULE
)
1182 , m_aInitialModule( aInitialModule
)
1183 , m_aLanguage( aLanguage
)
1188 void ExtensionIteratorBase::init()
1190 m_xSFA
= ucb::SimpleFileAccess::create(m_xContext
);
1192 m_bUserPackagesLoaded
= false;
1193 m_bSharedPackagesLoaded
= false;
1194 m_bBundledPackagesLoaded
= false;
1196 m_iSharedPackage
= 0;
1197 m_iBundledPackage
= 0;
1200 Reference
< deployment::XPackage
> ExtensionIteratorBase::implGetHelpPackageFromPackage
1201 ( Reference
< deployment::XPackage
> xPackage
, Reference
< deployment::XPackage
>& o_xParentPackageBundle
)
1203 o_xParentPackageBundle
.clear();
1205 Reference
< deployment::XPackage
> xHelpPackage
;
1206 if( !xPackage
.is() )
1207 return xHelpPackage
;
1209 // #i84550 Cache information about help content in extension
1210 OUString aExtensionPath
= xPackage
->getURL();
1211 ExtensionHelpExistanceMap::iterator it
= aHelpExistanceMap
.find( aExtensionPath
);
1212 bool bFound
= ( it
!= aHelpExistanceMap
.end() );
1213 bool bHasHelp
= bFound
&& it
->second
;
1214 if( bFound
&& !bHasHelp
)
1215 return xHelpPackage
;
1217 // Check if parent package is registered
1218 beans::Optional
< beans::Ambiguous
<sal_Bool
> > option( xPackage
->isRegistered
1219 ( Reference
<task::XAbortChannel
>(), Reference
<ucb::XCommandEnvironment
>() ) );
1220 bool bRegistered
= false;
1221 if( option
.IsPresent
)
1223 beans::Ambiguous
<sal_Bool
> const & reg
= option
.Value
;
1224 if( !reg
.IsAmbiguous
&& reg
.Value
)
1229 OUString
aHelpMediaType( "application/vnd.sun.star.help" );
1230 if( xPackage
->isBundle() )
1232 Sequence
< Reference
< deployment::XPackage
> > aPkgSeq
= xPackage
->getBundle
1233 ( Reference
<task::XAbortChannel
>(), Reference
<ucb::XCommandEnvironment
>() );
1234 sal_Int32 nPkgCount
= aPkgSeq
.getLength();
1235 const Reference
< deployment::XPackage
>* pSeq
= aPkgSeq
.getConstArray();
1236 for( sal_Int32 iPkg
= 0 ; iPkg
< nPkgCount
; ++iPkg
)
1238 const Reference
< deployment::XPackage
> xSubPkg
= pSeq
[ iPkg
];
1239 const Reference
< deployment::XPackageTypeInfo
> xPackageTypeInfo
= xSubPkg
->getPackageType();
1240 OUString aMediaType
= xPackageTypeInfo
->getMediaType();
1241 if( aMediaType
.equals( aHelpMediaType
) )
1243 xHelpPackage
= xSubPkg
;
1244 o_xParentPackageBundle
= xPackage
;
1251 const Reference
< deployment::XPackageTypeInfo
> xPackageTypeInfo
= xPackage
->getPackageType();
1252 OUString aMediaType
= xPackageTypeInfo
->getMediaType();
1253 if( aMediaType
.equals( aHelpMediaType
) )
1254 xHelpPackage
= xPackage
;
1259 aHelpExistanceMap
[ aExtensionPath
] = xHelpPackage
.is();
1261 return xHelpPackage
;
1264 Reference
< deployment::XPackage
> ExtensionIteratorBase::implGetNextUserHelpPackage
1265 ( Reference
< deployment::XPackage
>& o_xParentPackageBundle
)
1267 Reference
< deployment::XPackage
> xHelpPackage
;
1269 if( !m_bUserPackagesLoaded
)
1271 Reference
< XExtensionManager
> xExtensionManager
= ExtensionManager::get(m_xContext
);
1272 m_aUserPackagesSeq
= xExtensionManager
->getDeployedExtensions
1273 ( OUString("user"), Reference
< task::XAbortChannel
>(), Reference
< ucb::XCommandEnvironment
>() );
1274 m_bUserPackagesLoaded
= true;
1277 if( m_iUserPackage
== m_aUserPackagesSeq
.getLength() )
1279 m_eState
= SHARED_EXTENSIONS
; // Later: SHARED_MODULE
1283 const Reference
< deployment::XPackage
>* pUserPackages
= m_aUserPackagesSeq
.getConstArray();
1284 Reference
< deployment::XPackage
> xPackage
= pUserPackages
[ m_iUserPackage
++ ];
1285 OSL_ENSURE( xPackage
.is(), "ExtensionIteratorBase::implGetNextUserHelpPackage(): Invalid package" );
1286 xHelpPackage
= implGetHelpPackageFromPackage( xPackage
, o_xParentPackageBundle
);
1289 return xHelpPackage
;
1292 Reference
< deployment::XPackage
> ExtensionIteratorBase::implGetNextSharedHelpPackage
1293 ( Reference
< deployment::XPackage
>& o_xParentPackageBundle
)
1295 Reference
< deployment::XPackage
> xHelpPackage
;
1297 if( !m_bSharedPackagesLoaded
)
1299 Reference
< XExtensionManager
> xExtensionManager
= ExtensionManager::get(m_xContext
);
1300 m_aSharedPackagesSeq
= xExtensionManager
->getDeployedExtensions
1301 ( OUString("shared"), Reference
< task::XAbortChannel
>(), Reference
< ucb::XCommandEnvironment
>() );
1302 m_bSharedPackagesLoaded
= true;
1305 if( m_iSharedPackage
== m_aSharedPackagesSeq
.getLength() )
1307 m_eState
= BUNDLED_EXTENSIONS
;
1311 const Reference
< deployment::XPackage
>* pSharedPackages
= m_aSharedPackagesSeq
.getConstArray();
1312 Reference
< deployment::XPackage
> xPackage
= pSharedPackages
[ m_iSharedPackage
++ ];
1313 OSL_ENSURE( xPackage
.is(), "ExtensionIteratorBase::implGetNextSharedHelpPackage(): Invalid package" );
1314 xHelpPackage
= implGetHelpPackageFromPackage( xPackage
, o_xParentPackageBundle
);
1317 return xHelpPackage
;
1320 Reference
< deployment::XPackage
> ExtensionIteratorBase::implGetNextBundledHelpPackage
1321 ( Reference
< deployment::XPackage
>& o_xParentPackageBundle
)
1323 Reference
< deployment::XPackage
> xHelpPackage
;
1325 if( !m_bBundledPackagesLoaded
)
1327 Reference
< XExtensionManager
> xExtensionManager
= ExtensionManager::get(m_xContext
);
1328 m_aBundledPackagesSeq
= xExtensionManager
->getDeployedExtensions
1329 ( OUString("bundled"), Reference
< task::XAbortChannel
>(), Reference
< ucb::XCommandEnvironment
>() );
1330 m_bBundledPackagesLoaded
= true;
1333 if( m_iBundledPackage
== m_aBundledPackagesSeq
.getLength() )
1335 m_eState
= END_REACHED
;
1339 const Reference
< deployment::XPackage
>* pBundledPackages
=
1340 m_aBundledPackagesSeq
.getConstArray();
1341 Reference
< deployment::XPackage
> xPackage
= pBundledPackages
[ m_iBundledPackage
++ ];
1342 OSL_ENSURE( xPackage
.is(), "ExtensionIteratorBase::implGetNextBundledHelpPackage(): Invalid package" );
1343 xHelpPackage
= implGetHelpPackageFromPackage( xPackage
, o_xParentPackageBundle
);
1346 return xHelpPackage
;
1349 OUString
ExtensionIteratorBase::implGetFileFromPackage(
1350 const OUString
& rFileExtension
, Reference
< deployment::XPackage
> xPackage
)
1352 // No extension -> search for pure language folder
1353 bool bLangFolderOnly
= rFileExtension
.isEmpty();
1356 OUString aLanguage
= m_aLanguage
;
1357 for( sal_Int32 iPass
= 0 ; iPass
< 2 ; ++iPass
)
1359 OUString aStr
= xPackage
->getRegistrationDataURL().Value
+ "/" + aLanguage
;
1360 if( !bLangFolderOnly
)
1362 aStr
+= "/help" + rFileExtension
;
1365 aFile
= m_rDatabases
.expandURL( aStr
);
1368 if( m_xSFA
->exists( aFile
) )
1371 ::std::vector
< OUString
> av
;
1372 implGetLanguageVectorFromPackage( av
, xPackage
);
1373 ::std::vector
< OUString
>::const_iterator pFound
= LanguageTag::getFallback( av
, m_aLanguage
);
1374 if( pFound
!= av
.end() )
1375 aLanguage
= *pFound
;
1381 inline bool isLetter( sal_Unicode c
)
1383 return comphelper::string::isalphaAscii(c
);
1386 void ExtensionIteratorBase::implGetLanguageVectorFromPackage( ::std::vector
< OUString
> &rv
,
1387 com::sun::star::uno::Reference
< com::sun::star::deployment::XPackage
> xPackage
)
1390 OUString aExtensionPath
= xPackage
->getURL();
1391 Sequence
< OUString
> aEntrySeq
= m_xSFA
->getFolderContents( aExtensionPath
, true );
1393 const OUString
* pSeq
= aEntrySeq
.getConstArray();
1394 sal_Int32 nCount
= aEntrySeq
.getLength();
1395 for( sal_Int32 i
= 0 ; i
< nCount
; ++i
)
1397 OUString aEntry
= pSeq
[i
];
1398 if( m_xSFA
->isFolder( aEntry
) )
1400 sal_Int32 nLastSlash
= aEntry
.lastIndexOf( '/' );
1401 if( nLastSlash
!= -1 )
1403 OUString aPureEntry
= aEntry
.copy( nLastSlash
+ 1 );
1405 // Check language scheme
1406 int nLen
= aPureEntry
.getLength();
1407 const sal_Unicode
* pc
= aPureEntry
.getStr();
1408 bool bStartCanBeLanguage
= ( nLen
>= 2 && isLetter( pc
[0] ) && isLetter( pc
[1] ) );
1409 bool bIsLanguage
= bStartCanBeLanguage
&&
1410 ( nLen
== 2 || (nLen
== 5 && pc
[2] == '-' && isLetter( pc
[3] ) && isLetter( pc
[4] )) );
1412 rv
.push_back( aPureEntry
);
1418 // class DataBaseIterator
1420 helpdatafileproxy::Hdf
* DataBaseIterator::nextHdf( OUString
* o_pExtensionPath
, OUString
* o_pExtensionRegistryPath
)
1422 helpdatafileproxy::Hdf
* pRetHdf
= NULL
;
1424 while( !pRetHdf
&& m_eState
!= END_REACHED
)
1428 case INITIAL_MODULE
:
1429 pRetHdf
= m_rDatabases
.getHelpDataFile( m_aInitialModule
, m_aLanguage
, m_bHelpText
);
1430 m_eState
= USER_EXTENSIONS
; // Later: SHARED_MODULE
1434 //case SHARED_MODULE
1437 case USER_EXTENSIONS
:
1439 Reference
< deployment::XPackage
> xParentPackageBundle
;
1440 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextUserHelpPackage( xParentPackageBundle
);
1441 if( !xHelpPackage
.is() )
1443 pRetHdf
= implGetHdfFromPackage( xHelpPackage
, o_pExtensionPath
, o_pExtensionRegistryPath
);
1447 case SHARED_EXTENSIONS
:
1449 Reference
< deployment::XPackage
> xParentPackageBundle
;
1450 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextSharedHelpPackage( xParentPackageBundle
);
1451 if( !xHelpPackage
.is() )
1454 pRetHdf
= implGetHdfFromPackage( xHelpPackage
, o_pExtensionPath
, o_pExtensionRegistryPath
);
1458 case BUNDLED_EXTENSIONS
:
1460 Reference
< deployment::XPackage
> xParentPackageBundle
;
1461 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextBundledHelpPackage( xParentPackageBundle
);
1462 if( !xHelpPackage
.is() )
1465 pRetHdf
= implGetHdfFromPackage( xHelpPackage
, o_pExtensionPath
, o_pExtensionRegistryPath
);
1470 OSL_FAIL( "DataBaseIterator::nextDb(): Invalid case END_REACHED" );
1478 helpdatafileproxy::Hdf
* DataBaseIterator::implGetHdfFromPackage( Reference
< deployment::XPackage
> xPackage
,
1479 OUString
* o_pExtensionPath
, OUString
* o_pExtensionRegistryPath
)
1482 beans::Optional
< OUString
> optRegData
;
1485 optRegData
= xPackage
->getRegistrationDataURL();
1487 catch ( deployment::ExtensionRemovedException
&)
1492 helpdatafileproxy::Hdf
* pRetHdf
= NULL
;
1493 if (optRegData
.IsPresent
&& !optRegData
.Value
.isEmpty())
1495 OUString aRegDataUrl
= optRegData
.Value
+ "/";
1497 OUString
aHelpFilesBaseName("help");
1499 OUString aUsedLanguage
= m_aLanguage
;
1500 pRetHdf
= m_rDatabases
.getHelpDataFile(
1501 aHelpFilesBaseName
, aUsedLanguage
, m_bHelpText
, &aRegDataUrl
);
1503 // Language fallback
1506 ::std::vector
< OUString
> av
;
1507 implGetLanguageVectorFromPackage( av
, xPackage
);
1508 ::std::vector
< OUString
>::const_iterator pFound
= LanguageTag::getFallback( av
, m_aLanguage
);
1509 if( pFound
!= av
.end() )
1511 aUsedLanguage
= *pFound
;
1512 pRetHdf
= m_rDatabases
.getHelpDataFile(
1513 aHelpFilesBaseName
, aUsedLanguage
, m_bHelpText
, &aRegDataUrl
);
1517 if( o_pExtensionPath
)
1518 *o_pExtensionPath
= aRegDataUrl
+ aUsedLanguage
;
1520 if( o_pExtensionRegistryPath
)
1521 *o_pExtensionRegistryPath
= xPackage
->getURL() + "/" + aUsedLanguage
;
1527 // class KeyDataBaseFileIterator
1529 //returns a file URL
1530 OUString
KeyDataBaseFileIterator::nextDbFile( bool& o_rbExtension
)
1534 while( aRetFile
.isEmpty() && m_eState
!= END_REACHED
)
1538 case INITIAL_MODULE
:
1539 aRetFile
= OUStringBuffer(m_rDatabases
.getInstallPathAsURL()).
1540 append(m_rDatabases
.processLang(m_aLanguage
)).append('/').
1541 append(m_aInitialModule
).append(".key").makeStringAndClear();
1543 o_rbExtension
= false;
1545 m_eState
= USER_EXTENSIONS
; // Later: SHARED_MODULE
1549 //case SHARED_MODULE
1552 case USER_EXTENSIONS
:
1554 Reference
< deployment::XPackage
> xParentPackageBundle
;
1555 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextUserHelpPackage( xParentPackageBundle
);
1556 if( !xHelpPackage
.is() )
1559 aRetFile
= implGetDbFileFromPackage( xHelpPackage
);
1560 o_rbExtension
= true;
1564 case SHARED_EXTENSIONS
:
1566 Reference
< deployment::XPackage
> xParentPackageBundle
;
1567 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextSharedHelpPackage( xParentPackageBundle
);
1568 if( !xHelpPackage
.is() )
1571 aRetFile
= implGetDbFileFromPackage( xHelpPackage
);
1572 o_rbExtension
= true;
1576 case BUNDLED_EXTENSIONS
:
1578 Reference
< deployment::XPackage
> xParentPackageBundle
;
1579 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextBundledHelpPackage( xParentPackageBundle
);
1580 if( !xHelpPackage
.is() )
1583 aRetFile
= implGetDbFileFromPackage( xHelpPackage
);
1584 o_rbExtension
= true;
1589 OSL_FAIL( "DataBaseIterator::nextDbFile(): Invalid case END_REACHED" );
1597 //Returns a file URL, that does not contain macros
1598 OUString
KeyDataBaseFileIterator::implGetDbFileFromPackage
1599 ( Reference
< deployment::XPackage
> xPackage
)
1601 OUString aExpandedURL
=
1602 implGetFileFromPackage( OUString( ".key" ), xPackage
);
1604 return aExpandedURL
;
1607 // class JarFileIterator
1609 Reference
< XHierarchicalNameAccess
> JarFileIterator::nextJarFile
1610 ( Reference
< deployment::XPackage
>& o_xParentPackageBundle
,
1611 OUString
* o_pExtensionPath
, OUString
* o_pExtensionRegistryPath
)
1613 Reference
< XHierarchicalNameAccess
> xNA
;
1615 while( !xNA
.is() && m_eState
!= END_REACHED
)
1619 case INITIAL_MODULE
:
1620 xNA
= m_rDatabases
.jarFile( m_aInitialModule
, m_aLanguage
);
1621 m_eState
= USER_EXTENSIONS
; // Later: SHARED_MODULE
1625 //case SHARED_MODULE
1628 case USER_EXTENSIONS
:
1630 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextUserHelpPackage( o_xParentPackageBundle
);
1631 if( !xHelpPackage
.is() )
1634 xNA
= implGetJarFromPackage( xHelpPackage
, o_pExtensionPath
, o_pExtensionRegistryPath
);
1638 case SHARED_EXTENSIONS
:
1640 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextSharedHelpPackage( o_xParentPackageBundle
);
1641 if( !xHelpPackage
.is() )
1644 xNA
= implGetJarFromPackage( xHelpPackage
, o_pExtensionPath
, o_pExtensionRegistryPath
);
1648 case BUNDLED_EXTENSIONS
:
1650 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextBundledHelpPackage( o_xParentPackageBundle
);
1651 if( !xHelpPackage
.is() )
1654 xNA
= implGetJarFromPackage( xHelpPackage
, o_pExtensionPath
, o_pExtensionRegistryPath
);
1659 OSL_FAIL( "JarFileIterator::nextJarFile(): Invalid case END_REACHED" );
1667 Reference
< XHierarchicalNameAccess
> JarFileIterator::implGetJarFromPackage
1668 ( Reference
< deployment::XPackage
> xPackage
, OUString
* o_pExtensionPath
, OUString
* o_pExtensionRegistryPath
)
1670 Reference
< XHierarchicalNameAccess
> xNA
;
1673 implGetFileFromPackage( OUString( ".jar" ), xPackage
);
1677 Sequence
< Any
> aArguments( 2 );
1678 aArguments
[ 0 ] <<= zipFile
;
1680 // let ZipPackage be used ( no manifest.xml is required )
1681 beans::NamedValue aArg
;
1682 aArg
.Name
= "StorageFormat";
1683 aArg
.Value
<<= OUString(ZIP_STORAGE_FORMAT_STRING
);
1684 aArguments
[ 1 ] <<= aArg
;
1686 Reference
< XMultiComponentFactory
>xSMgr( m_xContext
->getServiceManager(), UNO_QUERY
);
1687 Reference
< XInterface
> xIfc
1688 = xSMgr
->createInstanceWithArgumentsAndContext(
1690 "com.sun.star.packages.comp.ZipPackage" ),
1691 aArguments
, m_xContext
);
1695 xNA
= Reference
< XHierarchicalNameAccess
>( xIfc
, UNO_QUERY
);
1697 OSL_ENSURE( xNA
.is(),
1698 "JarFileIterator::implGetJarFromPackage() - "
1699 "Got no hierarchical name access!" );
1702 catch ( RuntimeException
& )
1704 catch ( Exception
& )
1707 if( xNA
.is() && o_pExtensionPath
!= NULL
)
1709 // Extract path including language from file name
1710 sal_Int32 nLastSlash
= zipFile
.lastIndexOf( '/' );
1711 if( nLastSlash
!= -1 )
1712 *o_pExtensionPath
= zipFile
.copy( 0, nLastSlash
);
1714 if( o_pExtensionRegistryPath
!= NULL
)
1716 OUString
& rPath
= *o_pExtensionPath
;
1717 sal_Int32 nLastSlashInPath
= rPath
.lastIndexOf( '/', rPath
.getLength() - 1 );
1719 *o_pExtensionRegistryPath
= xPackage
->getURL();
1720 *o_pExtensionRegistryPath
+= rPath
.copy( nLastSlashInPath
);
1727 // class IndexFolderIterator
1729 OUString
IndexFolderIterator::nextIndexFolder( bool& o_rbExtension
, bool& o_rbTemporary
)
1731 OUString aIndexFolder
;
1733 while( aIndexFolder
.isEmpty() && m_eState
!= END_REACHED
)
1737 case INITIAL_MODULE
:
1738 aIndexFolder
= m_rDatabases
.getInstallPathAsURL()
1739 + m_rDatabases
.processLang(m_aLanguage
) + "/"
1740 + m_aInitialModule
+ ".idxl";
1742 o_rbTemporary
= false;
1743 o_rbExtension
= false;
1745 m_eState
= USER_EXTENSIONS
; // Later: SHARED_MODULE
1749 //case SHARED_MODULE
1752 case USER_EXTENSIONS
:
1754 Reference
< deployment::XPackage
> xParentPackageBundle
;
1755 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextUserHelpPackage( xParentPackageBundle
);
1756 if( !xHelpPackage
.is() )
1759 aIndexFolder
= implGetIndexFolderFromPackage( o_rbTemporary
, xHelpPackage
);
1760 o_rbExtension
= true;
1764 case SHARED_EXTENSIONS
:
1766 Reference
< deployment::XPackage
> xParentPackageBundle
;
1767 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextSharedHelpPackage( xParentPackageBundle
);
1768 if( !xHelpPackage
.is() )
1771 aIndexFolder
= implGetIndexFolderFromPackage( o_rbTemporary
, xHelpPackage
);
1772 o_rbExtension
= true;
1776 case BUNDLED_EXTENSIONS
:
1778 Reference
< deployment::XPackage
> xParentPackageBundle
;
1779 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextBundledHelpPackage( xParentPackageBundle
);
1780 if( !xHelpPackage
.is() )
1783 aIndexFolder
= implGetIndexFolderFromPackage( o_rbTemporary
, xHelpPackage
);
1784 o_rbExtension
= true;
1789 OSL_FAIL( "IndexFolderIterator::nextIndexFolder(): Invalid case END_REACHED" );
1794 return aIndexFolder
;
1797 OUString
IndexFolderIterator::implGetIndexFolderFromPackage( bool& o_rbTemporary
, Reference
< deployment::XPackage
> xPackage
)
1799 OUString aIndexFolder
=
1800 implGetFileFromPackage( OUString( ".idxl" ), xPackage
);
1802 o_rbTemporary
= false;
1803 if( !m_xSFA
->isFolder( aIndexFolder
) )
1805 // i98680: Missing index? Try to generate now
1806 OUString aLangURL
= implGetFileFromPackage( OUString(), xPackage
);
1807 if( m_xSFA
->isFolder( aLangURL
) )
1809 // Test write access (shared extension may be read only)
1810 bool bIsWriteAccess
= false;
1813 OUString aCreateTestFolder
= aLangURL
+ "CreateTestFolder";
1814 m_xSFA
->createFolder( aCreateTestFolder
);
1815 if( m_xSFA
->isFolder( aCreateTestFolder
) )
1816 bIsWriteAccess
= true;
1818 m_xSFA
->kill( aCreateTestFolder
);
1820 catch (const Exception
&)
1825 //bIsWriteAccess = false;
1830 sal_Int32 nLastSlash
= aLangURL
.lastIndexOf( '/' );
1831 if( nLastSlash
!= -1 )
1832 aLang
= aLangURL
.copy( nLastSlash
+ 1 );
1836 OUString
aMod("help");
1838 OUString aZipDir
= aLangURL
;
1839 if( !bIsWriteAccess
)
1841 OUString aTempFileURL
;
1842 ::osl::FileBase::RC eErr
= ::osl::File::createTempFile( 0, 0, &aTempFileURL
);
1843 if( eErr
== ::osl::FileBase::E_None
)
1845 OUString aTempDirURL
= aTempFileURL
;
1848 m_xSFA
->kill( aTempDirURL
);
1850 catch (const Exception
&)
1853 m_xSFA
->createFolder( aTempDirURL
);
1855 aZipDir
= aTempDirURL
;
1856 o_rbTemporary
= true;
1860 HelpIndexer
aIndexer(aLang
, aMod
, aLangURL
, aZipDir
);
1861 aIndexer
.indexDocuments();
1863 if( bIsWriteAccess
)
1864 aIndexFolder
= implGetFileFromPackage( OUString( ".idxl" ), xPackage
);
1866 aIndexFolder
= aZipDir
+ "/help.idxl";
1868 catch (const Exception
&)
1874 return aIndexFolder
;
1877 void IndexFolderIterator::deleteTempIndexFolder( const OUString
& aIndexFolder
)
1879 sal_Int32 nLastSlash
= aIndexFolder
.lastIndexOf( '/' );
1880 if( nLastSlash
!= -1 )
1882 OUString aTmpFolder
= aIndexFolder
.copy( 0, nLastSlash
);
1885 m_xSFA
->kill( aTmpFolder
);
1887 catch (const Exception
&)
1893 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */