1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: databases.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_xmlhelp.hxx"
34 #include <vos/diagnose.hxx>
35 #include <osl/thread.h>
36 #include <osl/process.h>
37 #include <rtl/uri.hxx>
38 #include <osl/file.hxx>
39 #include <rtl/memory.h>
40 #include <com/sun/star/lang/Locale.hpp>
41 #include <rtl/ustrbuf.hxx>
42 #include <svtools/miscopt.hxx>
43 #include "inputstream.hxx"
48 #include "com/sun/star/deployment/thePackageManagerFactory.hpp"
49 #include <comphelper/processfactory.hxx>
50 #include <com/sun/star/beans/XPropertySet.hpp>
51 #include <com/sun/star/uno/XComponentContext.hpp>
52 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
53 #include <com/sun/star/beans/Optional.hpp>
54 #include <com/sun/star/beans/NamedValue.hpp>
55 #include <com/sun/star/frame/XConfigManager.hpp>
56 #include <com/sun/star/util/XMacroExpander.hpp>
57 #include <com/sun/star/uri/XUriReferenceFactory.hpp>
58 #include <com/sun/star/uri/XVndSunStarExpandUrl.hpp>
59 #include <com/sun/star/script/XInvocation.hpp>
60 #include <comphelper/locale.hxx>
62 #include <transex3/compilehelp.hxx>
63 #include <comphelper/storagehelper.hxx>
65 #include "databases.hxx"
66 #include "urlparameter.hxx"
68 using namespace chelp
;
69 using namespace berkeleydbproxy
;
70 using namespace com::sun::star
;
71 using namespace com::sun::star::uno
;
72 using namespace com::sun::star::io
;
73 using namespace com::sun::star::container
;
74 using namespace com::sun::star::i18n
;
75 using namespace com::sun::star::lang
;
76 using namespace com::sun::star::deployment
;
77 using namespace com::sun::star::beans
;
80 static rtl::OUString
aSlash( rtl::OUString::createFromAscii( "/" ) );
81 static rtl::OUString
aHelpFilesBaseName( rtl::OUString::createFromAscii( "help" ) );
82 static rtl::OUString
aHelpMediaType( rtl::OUString::createFromAscii( "application/vnd.sun.star.help" ) );
84 rtl::OUString
Databases::expandURL( const rtl::OUString
& aURL
)
86 osl::MutexGuard
aGuard( m_aMutex
);
87 rtl::OUString aRetURL
= expandURL( aURL
, m_xContext
);
91 rtl::OUString
Databases::expandURL( const rtl::OUString
& aURL
, Reference
< uno::XComponentContext
> xContext
)
93 static Reference
< util::XMacroExpander
> xMacroExpander
;
94 static Reference
< uri::XUriReferenceFactory
> xFac
;
97 return rtl::OUString();
99 if( !xMacroExpander
.is() || !xFac
.is() )
101 Reference
< XMultiComponentFactory
> xSMgr( xContext
->getServiceManager(), UNO_QUERY
);
103 xFac
= Reference
< uri::XUriReferenceFactory
>(
104 xSMgr
->createInstanceWithContext( rtl::OUString::createFromAscii(
105 "com.sun.star.uri.UriReferenceFactory"), xContext
) , UNO_QUERY
);
108 throw RuntimeException(
109 ::rtl::OUString::createFromAscii( "Databases::expand(), could not instatiate UriReferenceFactory." ),
110 Reference
< XInterface
>() );
113 xMacroExpander
= Reference
< util::XMacroExpander
>(
114 xContext
->getValueByName(
115 ::rtl::OUString::createFromAscii( "/singletons/com.sun.star.util.theMacroExpander" ) ),
119 rtl::OUString aRetURL
= aURL
;
120 if( xMacroExpander
.is() )
122 Reference
< uri::XUriReference
> uriRef
;
125 uriRef
= Reference
< uri::XUriReference
>( xFac
->parse( aRetURL
), UNO_QUERY
);
128 Reference
< uri::XVndSunStarExpandUrl
> sxUri( uriRef
, UNO_QUERY
);
132 aRetURL
= sxUri
->expand( xMacroExpander
);
139 Databases::Databases( sal_Bool showBasic
,
140 const rtl::OUString
& instPath
,
141 const com::sun::star::uno::Sequence
< rtl::OUString
>& imagesZipPaths
,
142 const rtl::OUString
& productName
,
143 const rtl::OUString
& productVersion
,
144 const rtl::OUString
& vendorName
,
145 const rtl::OUString
& vendorVersion
,
146 const rtl::OUString
& vendorShort
,
147 const rtl::OUString
& styleSheet
,
148 Reference
< uno::XComponentContext
> xContext
)
149 : m_xContext( xContext
),
150 m_bShowBasic(showBasic
),
151 m_nErrorDocLength( 0 ),
153 m_nCustomCSSDocLength( 0 ),
154 m_pCustomCSSDoc( 0 ),
155 m_aCSS(styleSheet
.toAsciiLowerCase()),
156 newProdName(rtl::OUString::createFromAscii( "$[officename]" ) ),
157 newProdVersion(rtl::OUString::createFromAscii( "$[officeversion]" ) ),
158 prodName( rtl::OUString::createFromAscii( "%PRODUCTNAME" ) ),
159 prodVersion( rtl::OUString::createFromAscii( "%PRODUCTVERSION" ) ),
160 vendName( rtl::OUString::createFromAscii( "%VENDORNAME" ) ),
161 vendVersion( rtl::OUString::createFromAscii( "%VENDORVERSION" ) ),
162 vendShort( rtl::OUString::createFromAscii( "%VENDORSHORT" ) ),
163 m_aImagesZipPaths( imagesZipPaths
),
166 m_xSMgr
= Reference
< XMultiComponentFactory
>( m_xContext
->getServiceManager(), UNO_QUERY
);
176 m_vReplacement
[0] = productName
;
177 m_vReplacement
[1] = productVersion
;
178 m_vReplacement
[2] = vendorName
;
179 m_vReplacement
[3] = vendorVersion
;
180 m_vReplacement
[4] = vendorShort
;
181 m_vReplacement
[5] = productName
;
182 m_vReplacement
[6] = productVersion
;
184 setInstallPath( instPath
);
186 m_xSFA
= Reference
< ucb::XSimpleFileAccess
>(
187 m_xSMgr
->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ),
188 m_xContext
), UNO_QUERY_THROW
);
191 Databases::~Databases()
193 // release stylesheet
195 delete[] m_pCustomCSSDoc
;
197 // release errorDocument
199 delete[] m_pErrorDoc
;
201 // unload the databases
205 DatabasesTable::iterator it
= m_aDatabases
.begin();
206 while( it
!= m_aDatabases
.end() )
209 it
->second
->close( 0 );
218 ModInfoTable::iterator it
= m_aModInfo
.begin();
219 while( it
!= m_aModInfo
.end() )
229 KeywordInfoTable::iterator it
= m_aKeywordInfo
.begin();
230 while( it
!= m_aKeywordInfo
.end() )
239 static bool impl_getZipFile(
240 Sequence
< rtl::OUString
> & rImagesZipPaths
,
241 const rtl::OUString
& rZipName
,
242 rtl::OUString
& rFileName
)
244 rtl::OUString aWorkingDir
;
245 osl_getProcessWorkingDir( &aWorkingDir
.pData
);
246 const rtl::OUString
*pPathArray
= rImagesZipPaths
.getArray();
247 for ( int i
= 0; i
< rImagesZipPaths
.getLength(); ++i
)
249 rtl::OUString aFileName
= pPathArray
[ i
];
250 if ( aFileName
.getLength() )
252 if ( 1 + aFileName
.lastIndexOf( '/' ) != aFileName
.getLength() )
254 aFileName
+= rtl::OUString::createFromAscii( "/" );
256 aFileName
+= rZipName
;
257 // the icons are not read when the URL is a symlink
258 osl::File::getAbsoluteFileURL( aWorkingDir
, aFileName
, rFileName
);
261 osl::DirectoryItem aDirItem
;
262 if ( osl::DirectoryItem::get( rFileName
, aDirItem
) == osl::FileBase::E_None
)
269 rtl::OString
Databases::getImagesZipFileURL()
271 sal_Int16 nSymbolsStyle
= SvtMiscOptions().GetCurrentSymbolsStyle();
272 if ( !m_aImagesZipFileURL
.getLength() || ( m_nSymbolsStyle
!= nSymbolsStyle
) )
274 m_nSymbolsStyle
= nSymbolsStyle
;
276 rtl::OUString aImageZip
;
277 rtl::OUString aSymbolsStyleName
= SvtMiscOptions().GetCurrentSymbolsStyleName();
280 if ( aSymbolsStyleName
.getLength() != 0 )
282 rtl::OUString aZipName
= rtl::OUString::createFromAscii( "images_" );
283 aZipName
+= aSymbolsStyleName
;
284 aZipName
+= rtl::OUString::createFromAscii( ".zip" );
286 bFound
= impl_getZipFile( m_aImagesZipPaths
, aZipName
, aImageZip
);
290 bFound
= impl_getZipFile( m_aImagesZipPaths
, rtl::OUString::createFromAscii( "images.zip" ), aImageZip
);
293 aImageZip
= rtl::OUString();
295 m_aImagesZipFileURL
= rtl::OUStringToOString(
298 rtl_UriCharClassPchar
,
299 rtl_UriEncodeIgnoreEscapes
,
300 RTL_TEXTENCODING_UTF8
), RTL_TEXTENCODING_UTF8
);
303 return m_aImagesZipFileURL
;
307 void Databases::replaceName( rtl::OUString
& oustring
) const
309 sal_Int32 idx
= -1,idx1
= -1,idx2
= -1,k
= 0,off
;
311 rtl::OUStringBuffer
aStrBuf( 0 );
316 idx1
= oustring
.indexOf( sal_Unicode('%'),idx
);
317 idx2
= oustring
.indexOf( sal_Unicode('$'),idx
);
319 if(idx1
== -1 && idx2
== -1)
330 else if(idx2
< idx1
)
334 if( oustring
.indexOf( prodName
,idx
) == idx
)
336 else if( oustring
.indexOf( prodVersion
,idx
) == idx
)
337 off
= PRODUCTVERSION
;
338 else if( oustring
.indexOf( vendName
,idx
) == idx
)
340 else if( oustring
.indexOf( vendVersion
,idx
) == idx
)
342 else if( oustring
.indexOf( vendShort
,idx
) == idx
)
344 else if( oustring
.indexOf( newProdName
,idx
) == idx
)
345 off
= NEWPRODUCTNAME
;
346 else if( oustring
.indexOf( newProdVersion
,idx
) == idx
)
347 off
= NEWPRODUCTVERSION
;
356 aStrBuf
.ensureCapacity( 256 );
359 aStrBuf
.append( &oustring
.getStr()[k
],idx
- k
);
360 aStrBuf
.append( m_vReplacement
[off
] );
361 k
= idx
+ m_vAdd
[off
];
367 if( k
< oustring
.getLength() )
368 aStrBuf
.append( &oustring
.getStr()[k
],oustring
.getLength()-k
);
369 oustring
= aStrBuf
.makeStringAndClear();
376 rtl::OUString
Databases::getInstallPathAsSystemPath()
378 osl::MutexGuard
aGuard( m_aMutex
);
380 if( ! m_aInstallDirectoryAsSystemPath
.getLength() )
384 osl::FileBase::E_None
==
385 osl::FileBase::getSystemPathFromFileURL( m_aInstallDirectory
,m_aInstallDirectoryAsSystemPath
);
386 VOS_ENSURE( bla
,"HelpProvider, no installpath" );
388 osl::FileBase::getSystemPathFromFileURL( m_aInstallDirectory
,m_aInstallDirectoryAsSystemPath
);
392 return m_aInstallDirectoryAsSystemPath
;
398 rtl::OUString
Databases::getInstallPathAsURL()
400 osl::MutexGuard
aGuard( m_aMutex
);
402 return m_aInstallDirectory
;
406 const std::vector
< rtl::OUString
>& Databases::getModuleList( const rtl::OUString
& Language
)
408 if( m_avModules
.size() == 0 )
410 rtl::OUString fileName
,dirName
= getInstallPathAsURL() + processLang( Language
);
411 osl::Directory
dirFile( dirName
);
413 osl::DirectoryItem aDirItem
;
414 osl::FileStatus
aStatus( FileStatusMask_FileName
);
418 if( osl::FileBase::E_None
!= dirFile
.open() )
421 while( dirFile
.getNextItem( aDirItem
) == osl::FileBase::E_None
&&
422 aDirItem
.getFileStatus( aStatus
) == osl::FileBase::E_None
)
424 if( ! aStatus
.isValid( FileStatusMask_FileName
) )
427 fileName
= aStatus
.getFileName();
429 // Check, whether fileName is of the form *.cfg
430 idx
= fileName
.lastIndexOf( sal_Unicode( '.' ) );
435 const sal_Unicode
* str
= fileName
.getStr();
437 if( fileName
.getLength() == idx
+ 4 &&
438 ( str
[idx
+ 1] == 'c' || str
[idx
+ 1] == 'C' ) &&
439 ( str
[idx
+ 2] == 'f' || str
[idx
+ 2] == 'F' ) &&
440 ( str
[idx
+ 3] == 'g' || str
[idx
+ 3] == 'G' ) &&
441 ( fileName
= fileName
.copy(0,idx
).toAsciiLowerCase() ).compareToAscii( "picture" ) != 0 ) {
442 if(! m_bShowBasic
&& fileName
.compareToAscii("sbasic") == 0 )
444 m_avModules
.push_back( fileName
);
453 StaticModuleInformation
* Databases::getStaticInformationForModule( const rtl::OUString
& Module
,
454 const rtl::OUString
& Language
)
456 osl::MutexGuard
aGuard( m_aMutex
);
458 rtl::OUString key
= processLang(Language
) + rtl::OUString::createFromAscii( "/" ) + Module
;
460 std::pair
< ModInfoTable::iterator
,bool > aPair
=
461 m_aModInfo
.insert( ModInfoTable::value_type( key
,0 ) );
463 ModInfoTable::iterator it
= aPair
.first
;
465 if( aPair
.second
&& ! it
->second
)
467 osl::File
cfgFile( getInstallPathAsURL() +
469 rtl::OUString::createFromAscii( ".cfg" ) );
471 if( osl::FileBase::E_None
!= cfgFile
.open( OpenFlag_Read
) )
477 sal_Char buffer
[2048];
478 sal_Unicode lineBuffer
[1028];
479 rtl::OUString fileContent
;
481 while( osl::FileBase::E_None
== cfgFile
.read( &buffer
,2048,nRead
) && nRead
)
482 fileContent
+= rtl::OUString( buffer
,sal_Int32( nRead
),RTL_TEXTENCODING_UTF8
);
486 const sal_Unicode
* str
= fileContent
.getStr();
487 rtl::OUString current
,lang_
,program
,startid
,title
,heading
,fulltext
;
488 rtl::OUString order
= rtl::OUString::createFromAscii( "1" );
490 for( sal_Int32 i
= 0;i
< fileContent
.getLength();i
++ )
492 sal_Unicode ch
= str
[ i
];
493 if( ch
== sal_Unicode( '\n' ) || ch
== sal_Unicode( '\r' ) )
497 current
= rtl::OUString( lineBuffer
,pos
);
499 if( current
.compareToAscii( "Title",5 ) == 0 )
501 title
= current
.copy( current
.indexOf(sal_Unicode( '=' ) ) + 1 );
503 else if( current
.compareToAscii( "Start",5 ) == 0 )
505 startid
= current
.copy( current
.indexOf('=') + 1 );
507 else if( current
.compareToAscii( "Language",8 ) == 0 )
509 lang_
= current
.copy( current
.indexOf('=') + 1 );
511 else if( current
.compareToAscii( "Program",7 ) == 0 )
513 program
= current
.copy( current
.indexOf('=') + 1 );
515 else if( current
.compareToAscii( "Heading",7 ) == 0 )
517 heading
= current
.copy( current
.indexOf('=') + 1 );
519 else if( current
.compareToAscii( "FullText",8 ) == 0 )
521 fulltext
= current
.copy( current
.indexOf('=') + 1 );
523 else if( current
.compareToAscii( "Order",5 ) == 0 )
525 order
= current
.copy( current
.indexOf('=') + 1 );
531 lineBuffer
[ pos
++ ] = ch
;
533 replaceName( title
);
534 it
->second
= new StaticModuleInformation( title
,
549 rtl::OUString
Databases::processLang( const rtl::OUString
& Language
)
551 osl::MutexGuard
aGuard( m_aMutex
);
554 LangSetTable::iterator it
= m_aLangSet
.find( Language
);
556 if( it
== m_aLangSet
.end() )
559 osl::DirectoryItem aDirItem
;
561 if( osl::FileBase::E_None
== osl::DirectoryItem::get( getInstallPathAsURL() + Language
,aDirItem
) )
564 m_aLangSet
[ Language
] = ret
;
566 else if( ( ( idx
= Language
.indexOf( '-' ) ) != -1 ||
567 ( idx
= Language
.indexOf( '_' ) ) != -1 ) &&
568 osl::FileBase::E_None
== osl::DirectoryItem::get( getInstallPathAsURL() + Language
.copy( 0,idx
),
571 ret
= Language
.copy( 0,idx
);
572 m_aLangSet
[ Language
] = ret
;
582 rtl::OUString
Databases::country( const rtl::OUString
& Language
)
585 if( ( idx
= Language
.indexOf( '-' ) ) != -1 ||
586 ( idx
= Language
.indexOf( '_' ) ) != -1 )
587 return Language
.copy( 1+idx
);
589 return rtl::OUString();
594 Db
* Databases::getBerkeley( const rtl::OUString
& Database
,
595 const rtl::OUString
& Language
, bool helpText
,
596 const rtl::OUString
* pExtensionPath
)
598 if( ! Database
.getLength() || ! Language
.getLength() )
601 osl::MutexGuard
aGuard( m_aMutex
);
604 rtl::OUString
aFileExt( rtl::OUString::createFromAscii( helpText
? ".ht" : ".db" ) );
605 rtl::OUString dbFileName
= aSlash
+ Database
+ aFileExt
;
607 if( pExtensionPath
== NULL
)
608 key
= processLang( Language
) + dbFileName
;
610 key
= *pExtensionPath
+ Language
+ dbFileName
; // make unique, don't change language
612 std::pair
< DatabasesTable::iterator
,bool > aPair
=
613 m_aDatabases
.insert( DatabasesTable::value_type( key
,0 ) );
615 DatabasesTable::iterator it
= aPair
.first
;
617 if( aPair
.second
&& ! it
->second
)
619 Db
* table
= new Db();
621 rtl::OUString fileNameOU
;
624 rtl::OUString aExpandedURL
= expandURL( *pExtensionPath
);
625 aExpandedURL
+= Language
+ dbFileName
;
626 osl::FileBase::getSystemPathFromFileURL( aExpandedURL
, fileNameOU
);
629 fileNameOU
= getInstallPathAsSystemPath() + key
;
632 rtl::OString
fileName( fileNameOU
.getStr(),fileNameOU
.getLength(),osl_getThreadTextEncoding() );
634 rtl::OUString
fileNameDBHelp( fileNameOU
);
635 if( pExtensionPath
!= NULL
)
636 fileNameDBHelp
+= rtl::OUString::createFromAscii( "_" );
637 if( m_xSFA
->exists( fileNameDBHelp
) )
639 DBHelp
* pDBHelp
= new DBHelp( fileNameDBHelp
, m_xSFA
);
640 table
->setDBHelp( pDBHelp
);
644 bool bOldDbAccess
= false;
645 bSuccess
= pDBHelp
->testAgainstDb( fileName
, bOldDbAccess
);
648 bSuccess
= pDBHelp
->testAgainstDb( fileName
, bOldDbAccess
);
651 else if( table
->open( 0,fileName
.getStr(),0,DB_BTREE
,DB_RDONLY
,0644 ) )
664 Reference
< XCollator
>
665 Databases::getCollator( const rtl::OUString
& Language
,
666 const rtl::OUString
& System
)
670 rtl::OUString key
= Language
;
672 osl::MutexGuard
aGuard( m_aMutex
);
674 CollatorTable::iterator it
=
675 m_aCollatorTable
.insert( CollatorTable::value_type( key
,0 ) ).first
;
677 if( ! it
->second
.is() )
680 Reference
< XCollator
> (
681 m_xSMgr
->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.i18n.Collator" ),
682 m_xContext
), UNO_QUERY
);
683 rtl::OUString langStr
= processLang(Language
);
684 rtl::OUString countryStr
= country(Language
);
685 if( !countryStr
.getLength() )
687 if( langStr
.compareToAscii("de") == 0 )
688 countryStr
= rtl::OUString::createFromAscii("DE");
689 else if( langStr
.compareToAscii("en") == 0 )
690 countryStr
= rtl::OUString::createFromAscii("US");
691 else if( langStr
.compareToAscii("es") == 0 )
692 countryStr
= rtl::OUString::createFromAscii("ES");
693 else if( langStr
.compareToAscii("it") == 0 )
694 countryStr
= rtl::OUString::createFromAscii("IT");
695 else if( langStr
.compareToAscii("fr") == 0 )
696 countryStr
= rtl::OUString::createFromAscii("FR");
697 else if( langStr
.compareToAscii("sv") == 0 )
698 countryStr
= rtl::OUString::createFromAscii("SE");
699 else if( langStr
.compareToAscii("ja") == 0 )
700 countryStr
= rtl::OUString::createFromAscii("JP");
701 else if( langStr
.compareToAscii("ko") == 0 )
702 countryStr
= rtl::OUString::createFromAscii("KR");
704 it
->second
->loadDefaultCollator( Locale( langStr
,
717 struct KeywordElementComparator
719 KeywordElementComparator( const Reference
< XCollator
>& xCollator
)
720 : m_xCollator( xCollator
)
723 bool operator()( const KeywordInfo::KeywordElement
& la
,
724 const KeywordInfo::KeywordElement
& ra
) const
726 const rtl::OUString
& l
= la
.key
;
727 const rtl::OUString
& r
= ra
.key
;
731 if( m_xCollator
.is() )
733 sal_Int32 l1
= l
.indexOf( sal_Unicode( ';' ) );
734 sal_Int32 l3
= ( l1
== -1 ? l
.getLength() : l1
);
736 sal_Int32 r1
= r
.indexOf( sal_Unicode( ';' ) );
737 sal_Int32 r3
= ( r1
== -1 ? r
.getLength() : r1
);
739 sal_Int32 c1
= m_xCollator
->compareSubstring( l
,0,l3
,r
,0,r3
);
745 sal_Int32 l2
= l
.getLength() - l1
- 1;
746 sal_Int32 r2
= r
.getLength() - r1
- 1;
747 ret
= ( m_xCollator
->compareSubstring( l
,1+l1
,l2
,r
,1+r1
,r2
) < 0 );
758 Reference
< XCollator
> m_xCollator
;
759 }; // end struct KeywordElementComparator
765 KeywordInfo::KeywordElement::KeywordElement( Databases
*pDatabases
,
768 rtl::OUString
& data
)
771 pDatabases
->replaceName( key
);
772 init( pDatabases
,pDb
,data
);
777 void KeywordInfo::KeywordElement::init( Databases
*pDatabases
,Db
* pDb
,const rtl::OUString
& ids
)
779 const sal_Unicode
* idstr
= ids
.getStr();
780 std::vector
< rtl::OUString
> id
,anchor
;
782 while( ( idx
= ids
.indexOf( ';',k
= ++idx
) ) != -1 )
784 int h
= ids
.indexOf( sal_Unicode( '#' ),k
);
788 id
.push_back( rtl::OUString( &idstr
[k
],h
-k
) );
789 anchor
.push_back( rtl::OUString( &idstr
[h
+1],idx
-h
-1 ) );
793 id
.push_back( rtl::OUString( &idstr
[k
],idx
-k
) );
794 anchor
.push_back( rtl::OUString() );
798 listId
.realloc( id
.size() );
799 listAnchor
.realloc( id
.size() );
800 listTitle
.realloc( id
.size() );
803 const sal_Char
* pData
= NULL
;
804 const sal_Char pEmpty
[] = "";
806 for( sal_uInt32 i
= 0; i
< id
.size(); ++i
)
809 listAnchor
[i
] = anchor
[i
];
815 rtl::OString
idi( id
[i
].getStr(),id
[i
].getLength(),RTL_TEXTENCODING_UTF8
);
816 DBHelp
* pDBHelp
= pDb
->getDBHelp();
817 if( pDBHelp
!= NULL
)
820 bool bSuccess
= pDBHelp
->getValueForKey( idi
, aDBData
);
823 nSize
= aDBData
.getSize();
824 pData
= aDBData
.getData();
829 Dbt
key_( static_cast< void* >( const_cast< sal_Char
* >( idi
.getStr() ) ),
832 pDb
->get( 0,&key_
,&data
,0 );
833 nSize
= data
.get_size();
834 pData
= static_cast<sal_Char
*>( data
.get_data() );
838 DbtToStringConverter
converter( pData
, nSize
);
840 rtl::OUString title
= converter
.getTitle();
841 pDatabases
->replaceName( title
);
842 listTitle
[i
] = title
;
848 KeywordInfo::KeywordInfo( const std::vector
< KeywordElement
>& aVec
)
849 : listKey( aVec
.size() ),
850 listId( aVec
.size() ),
851 listAnchor( aVec
.size() ),
852 listTitle( aVec
.size() )
854 for( unsigned int i
= 0; i
< aVec
.size(); ++i
)
856 listKey
[i
] = aVec
[i
].key
;
857 listId
[i
] = aVec
[i
].listId
;
858 listAnchor
[i
] = aVec
[i
].listAnchor
;
859 listTitle
[i
] = aVec
[i
].listTitle
;
863 bool Databases::checkModuleMatchForExtension
864 ( const rtl::OUString
& Database
, const rtl::OUString
& doclist
)
866 bool bBelongsToDatabase
= true;
868 // Analyse doclist string to find module assignments
869 bool bFoundAtLeastOneModule
= false;
870 bool bModuleMatch
= false;
871 sal_Int32 nLen
= doclist
.getLength();
872 sal_Int32 nLastFound
= doclist
.lastIndexOf( sal_Unicode(';') );
873 if( nLastFound
== -1 )
875 const sal_Unicode
* pStr
= doclist
.getStr();
876 sal_Int32 nFound
= doclist
.lastIndexOf( sal_Unicode('_') );
877 while( nFound
!= -1 )
879 // Simple optimization, stop if '_' is followed by "id"
880 if( nLen
- nFound
> 2 )
882 if( pStr
[ nFound
+ 1 ] == sal_Unicode('i') &&
883 pStr
[ nFound
+ 2 ] == sal_Unicode('d') )
887 rtl::OUString aModule
= doclist
.copy( nFound
+ 1, nLastFound
- nFound
- 1 );
888 std::vector
< rtl::OUString
>::iterator result
= std::find( m_avModules
.begin(), m_avModules
.end(), aModule
);
889 if( result
!= m_avModules
.end() )
891 bFoundAtLeastOneModule
= true;
892 if( Database
== aModule
)
900 if( nLastFound
== 0 )
902 nFound
= doclist
.lastIndexOf( sal_Unicode('_'), nLastFound
- 1 );
905 if( bFoundAtLeastOneModule
&& !bModuleMatch
)
906 bBelongsToDatabase
= false;
908 return bBelongsToDatabase
;
912 KeywordInfo
* Databases::getKeyword( const rtl::OUString
& Database
,
913 const rtl::OUString
& Language
)
915 osl::MutexGuard
aGuard( m_aMutex
);
917 rtl::OUString key
= processLang(Language
) + rtl::OUString::createFromAscii( "/" ) + Database
;
919 std::pair
< KeywordInfoTable::iterator
,bool > aPair
=
920 m_aKeywordInfo
.insert( KeywordInfoTable::value_type( key
,0 ) );
922 KeywordInfoTable::iterator it
= aPair
.first
;
924 if( aPair
.second
&& ! it
->second
)
926 std::vector
<KeywordInfo::KeywordElement
> aVector
;
928 KeyDataBaseFileIterator
aDbFileIt( m_xContext
, *this, Database
, Language
);
929 rtl::OUString fileNameOU
;
930 bool bExtension
= false;
931 while( (fileNameOU
= aDbFileIt
.nextDbFile( bExtension
)).getLength() > 0 )
933 rtl::OString
fileName( fileNameOU
.getStr(),
934 fileNameOU
.getLength(),
935 osl_getThreadTextEncoding() );
939 rtl::OUString
fileNameDBHelp( fileNameOU
);
941 fileNameDBHelp
+= rtl::OUString::createFromAscii( "_" );
942 if( m_xSFA
->exists( fileNameDBHelp
) )
944 DBHelp
aDBHelp( fileNameDBHelp
, m_xSFA
);
948 if( aDBHelp
.startIteration() )
950 Db
* idmap
= getBerkeley( Database
,Language
);
952 DBHelp
* pDBHelp
= idmap
->getDBHelp();
953 if( pDBHelp
!= NULL
)
955 bool bOptimizeForPerformance
= true;
956 pDBHelp
->releaseHashMap();
957 pDBHelp
->createHashMap( bOptimizeForPerformance
);
960 while( aDBHelp
.getNextKeyAndValue( aKey
, aValue
) )
962 rtl::OUString
keyword( aKey
.getData(), aKey
.getSize(),
963 RTL_TEXTENCODING_UTF8
);
964 rtl::OUString
doclist( aValue
.getData(), aValue
.getSize(),
965 RTL_TEXTENCODING_UTF8
);
967 bool bBelongsToDatabase
= true;
969 bBelongsToDatabase
= checkModuleMatchForExtension( Database
, doclist
);
971 if( !bBelongsToDatabase
)
974 aVector
.push_back( KeywordInfo::KeywordElement( this,
979 aDBHelp
.stopIteration();
981 if( pDBHelp
!= NULL
)
982 pDBHelp
->releaseHashMap();
987 bool bOldDbAccess
= false;
988 bSuccess
= aDBHelp
.testAgainstDb( fileName
, bOldDbAccess
);
991 bSuccess
= aDBHelp
.testAgainstDb( fileName
, bOldDbAccess
);
997 else if( 0 == table
.open( 0,fileName
.getStr(),0,DB_BTREE
,DB_RDONLY
,0644 ) )
999 Db
* idmap
= getBerkeley( Database
,Language
);
1004 table
.cursor( 0,&cursor
,0 );
1006 key_
.set_flags( DB_DBT_MALLOC
); // Initially the cursor must allocate the necessary memory
1007 data
.set_flags( DB_DBT_MALLOC
);
1008 while( cursor
&& DB_NOTFOUND
!= cursor
->get( &key_
,&data
,DB_NEXT
) )
1010 rtl::OUString
keyword( static_cast<sal_Char
*>(key_
.get_data()),
1012 RTL_TEXTENCODING_UTF8
);
1013 rtl::OUString
doclist( static_cast<sal_Char
*>(data
.get_data()),
1015 RTL_TEXTENCODING_UTF8
);
1017 bool bBelongsToDatabase
= true;
1019 bBelongsToDatabase
= checkModuleMatchForExtension( Database
, doclist
);
1021 if( !bBelongsToDatabase
)
1024 aVector
.push_back( KeywordInfo::KeywordElement( this,
1030 key_
.set_flags( DB_DBT_REALLOC
);
1031 data
.set_flags( DB_DBT_REALLOC
);
1036 if( cursor
) cursor
->close();
1042 Reference
< XCollator
> xCollator
= getCollator( Language
,rtl::OUString());
1043 KeywordElementComparator
aComparator( xCollator
);
1044 std::sort(aVector
.begin(),aVector
.end(),aComparator
);
1046 KeywordInfo
* pInfo
= it
->second
= new KeywordInfo( aVector
);
1053 Reference
< XHierarchicalNameAccess
> Databases::jarFile( const rtl::OUString
& jar
,
1054 const rtl::OUString
& Language
)
1056 if( ! jar
.getLength() ||
1057 ! Language
.getLength() )
1059 return Reference
< XHierarchicalNameAccess
>( 0 );
1061 rtl::OUString key
= processLang(Language
) + aSlash
+ jar
;
1063 osl::MutexGuard
aGuard( m_aMutex
);
1065 ZipFileTable::iterator it
=
1066 m_aZipFileTable
.insert( ZipFileTable::value_type( key
,Reference
< XHierarchicalNameAccess
>(0) ) ).first
;
1068 if( ! it
->second
.is() )
1070 rtl::OUString zipFile
;
1073 // Extension jar file? Search for ?
1074 sal_Int32 nQuestionMark1
= jar
.indexOf( sal_Unicode('?') );
1075 sal_Int32 nQuestionMark2
= jar
.lastIndexOf( sal_Unicode('?') );
1076 if( nQuestionMark1
!= -1 && nQuestionMark2
!= -1 && nQuestionMark1
!= nQuestionMark2
)
1078 ::rtl::OUString aExtensionPath
= jar
.copy( nQuestionMark1
+ 1, nQuestionMark2
- nQuestionMark1
- 1 );
1079 ::rtl::OUString aPureJar
= jar
.copy( nQuestionMark2
+ 1 );
1081 rtl::OUStringBuffer aStrBuf
;
1082 aStrBuf
.append( aExtensionPath
);
1083 aStrBuf
.append( aSlash
);
1084 aStrBuf
.append( aPureJar
);
1086 zipFile
= expandURL( aStrBuf
.makeStringAndClear() );
1090 zipFile
= getInstallPathAsURL() + key
;
1093 Sequence
< Any
> aArguments( 2 );
1095 XInputStream_impl
* p
= new XInputStream_impl( zipFile
);
1096 if( p
->CtorSuccess() )
1098 Reference
< XInputStream
> xInputStream( p
);
1099 aArguments
[ 0 ] <<= xInputStream
;
1104 aArguments
[ 0 ] <<= zipFile
;
1107 // let ZipPackage be used ( no manifest.xml is required )
1108 beans::NamedValue aArg
;
1109 aArg
.Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StorageFormat" ) );
1110 aArg
.Value
<<= ZIP_STORAGE_FORMAT_STRING
;
1111 aArguments
[ 1 ] <<= aArg
;
1113 Reference
< XInterface
> xIfc
1114 = m_xSMgr
->createInstanceWithArgumentsAndContext(
1115 rtl::OUString::createFromAscii(
1116 "com.sun.star.packages.comp.ZipPackage" ),
1117 aArguments
, m_xContext
);
1121 it
->second
= Reference
< XHierarchicalNameAccess
>( xIfc
, UNO_QUERY
);
1123 VOS_ENSURE( it
->second
.is(),
1124 "ContentProvider::createPackage - "
1125 "Got no hierarchical name access!" );
1129 catch ( RuntimeException
& )
1132 catch ( Exception
& )
1140 Reference
< XHierarchicalNameAccess
> Databases::findJarFileForPath
1141 ( const rtl::OUString
& jar
, const rtl::OUString
& Language
,
1142 const rtl::OUString
& path
, rtl::OUString
* o_pExtensionPath
)
1144 Reference
< XHierarchicalNameAccess
> xNA
;
1145 if( ! jar
.getLength() ||
1146 ! Language
.getLength() )
1151 JarFileIterator
aJarFileIt( m_xContext
, *this, jar
, Language
);
1152 Reference
< XHierarchicalNameAccess
> xTestNA
;
1153 Reference
< deployment::XPackage
> xParentPackageBundle
;
1154 while( (xTestNA
= aJarFileIt
.nextJarFile( xParentPackageBundle
, o_pExtensionPath
)).is() )
1156 if( xTestNA
.is() && xTestNA
->hasByHierarchicalName( path
) )
1158 bool bSuccess
= true;
1159 if( xParentPackageBundle
.is() )
1161 rtl::OUString aIdentifierInPath
;
1162 sal_Int32 nFindSlash
= path
.indexOf( '/' );
1163 if( nFindSlash
!= -1 )
1164 aIdentifierInPath
= path
.copy( 0, nFindSlash
);
1166 beans::Optional
<rtl::OUString
> aIdentifierOptional
= xParentPackageBundle
->getIdentifier();
1167 if( aIdentifierInPath
.getLength() && aIdentifierOptional
.IsPresent
)
1169 rtl::OUString aUnencodedIdentifier
= aIdentifierOptional
.Value
;
1170 rtl::OUString aIdentifier
= rtl::Uri::encode( aUnencodedIdentifier
,
1171 rtl_UriCharClassPchar
, rtl_UriEncodeIgnoreEscapes
, RTL_TEXTENCODING_UTF8
);
1173 if( !aIdentifierInPath
.equals( aIdentifier
) )
1175 // path does not start with extension identifier -> ignore
1181 // No identifier -> ignore
1197 void Databases::popupDocument( URLParameter
* urlPar
,char **buffer
,int *byteCount
)
1202 " <help:css-file-link xmlns:help=\"http://openoffice.org/2000/help\"/> "
1205 " <help:popup-cut Id=\"";
1206 const sal_Int32 l1
= strlen( pop1
);
1208 const char* pop3
= "\" Eid=\"";
1209 const sal_Int32 l3
= strlen( pop3
);
1212 "\" xmlns:help=\"http://openoffice.org/2000/help\"></help:popup-cut> "
1215 const sal_Int32 l5
= strlen( pop5
);
1218 rtl::OUString val
= urlPar
->get_id();
1219 rtl::OString
pop2O( val
.getStr(),l2
= val
.getLength(),RTL_TEXTENCODING_UTF8
);
1220 const char* pop2
= pop2O
.getStr();
1222 val
= urlPar
->get_eid();
1223 rtl::OString
pop4O( val
.getStr(),l4
= val
.getLength(),RTL_TEXTENCODING_UTF8
);
1224 const char* pop4
= pop4O
.getStr();
1226 (*byteCount
) = l1
+ l2
+ l3
+ l4
+ l5
;
1228 *buffer
= new char[ 1+*byteCount
];
1230 rtl_copyMemory( *buffer
,pop1
,l1
);
1231 rtl_copyMemory( *buffer
+l1
,pop2
,l2
);
1232 rtl_copyMemory( *buffer
+(l1
+l2
),pop3
,l3
);
1233 rtl_copyMemory( *buffer
+(l1
+l2
+l3
),pop4
,l4
);
1234 rtl_copyMemory( *buffer
+(l1
+l2
+l3
+l4
),pop5
,l5
);
1235 (*buffer
)[*byteCount
] = 0;
1239 void Databases::changeCSS(const rtl::OUString
& newStyleSheet
)
1241 m_aCSS
= newStyleSheet
.toAsciiLowerCase();
1242 delete[] m_pCustomCSSDoc
, m_pCustomCSSDoc
= 0,m_nCustomCSSDocLength
= 0;
1247 void Databases::cascadingStylesheet( const rtl::OUString
& Language
,
1251 if( ! m_pCustomCSSDoc
)
1255 rtl::OUString fileURL
;
1257 while( error
&& retry
)
1261 getInstallPathAsURL() +
1262 processLang( Language
) +
1263 rtl::OUString::createFromAscii( "/" ) +
1265 rtl::OUString::createFromAscii( ".css" );
1266 else if( retry
== 1 )
1268 getInstallPathAsURL() +
1270 rtl::OUString::createFromAscii( ".css" );
1272 osl::DirectoryItem aDirItem
;
1273 osl::File
aFile( fileURL
);
1274 osl::FileStatus
aStatus( FileStatusMask_FileSize
);
1276 if( osl::FileBase::E_None
== osl::DirectoryItem::get( fileURL
,aDirItem
) &&
1277 osl::FileBase::E_None
== aFile
.open( OpenFlag_Read
) &&
1278 osl::FileBase::E_None
== aDirItem
.getFileStatus( aStatus
) )
1281 aFile
.getSize( nSize
);
1282 m_nCustomCSSDocLength
= (int)nSize
;
1283 m_pCustomCSSDoc
= new char[ 1 + m_nCustomCSSDocLength
];
1284 m_pCustomCSSDoc
[ m_nCustomCSSDocLength
] = 0;
1285 sal_uInt64 a
= m_nCustomCSSDocLength
,b
= m_nCustomCSSDocLength
;
1286 aFile
.read( m_pCustomCSSDoc
,a
,b
);
1296 m_nCustomCSSDocLength
= 0;
1297 m_pCustomCSSDoc
= new char[ 1 ]; // Initialize with 1 to avoid gcc compiler warning
1301 *byteCount
= m_nCustomCSSDocLength
;
1302 *buffer
= new char[ 1 + *byteCount
];
1303 (*buffer
)[*byteCount
] = 0;
1304 rtl_copyMemory( *buffer
,m_pCustomCSSDoc
,m_nCustomCSSDocLength
);
1309 void Databases::setActiveText( const rtl::OUString
& Module
,
1310 const rtl::OUString
& Language
,
1311 const rtl::OUString
& Id
,
1315 DataBaseIterator
aDbIt( m_xContext
, *this, Module
, Language
, true );
1317 // #i84550 Cache information about failed ids
1318 rtl::OString
id( Id
.getStr(),Id
.getLength(),RTL_TEXTENCODING_UTF8
);
1319 EmptyActiveTextSet::iterator it
= m_aEmptyActiveTextSet
.find( id
);
1320 bool bFoundAsEmpty
= ( it
!= m_aEmptyActiveTextSet
.end() );
1325 const sal_Char
* pData
= NULL
;
1327 bool bSuccess
= false;
1328 if( !bFoundAsEmpty
)
1331 Dbt
key( static_cast< void* >( const_cast< sal_Char
* >( id
.getStr() ) ),id
.getLength() );
1332 while( !bSuccess
&& (db
= aDbIt
.nextDb()) != NULL
)
1334 DBHelp
* pDBHelp
= db
->getDBHelp();
1335 if( pDBHelp
!= NULL
)
1337 bSuccess
= pDBHelp
->getValueForKey( id
, aDBData
);
1338 nSize
= aDBData
.getSize();
1339 pData
= aDBData
.getData();
1343 int err
= db
->get( 0, &key
, &data
, 0 );
1347 nSize
= data
.get_size();
1348 pData
= static_cast<sal_Char
*>( data
.get_data() );
1356 // ensure existence of tmp after for
1358 for( int i
= 0; i
< nSize
; ++i
)
1359 if( pData
[i
] == '%' || pData
[i
] == '$' )
1361 // need of replacement
1362 rtl::OUString temp
= rtl::OUString( pData
, nSize
, RTL_TEXTENCODING_UTF8
);
1363 replaceName( temp
);
1364 tmp
= rtl::OString( temp
.getStr(),
1366 RTL_TEXTENCODING_UTF8
);
1367 nSize
= tmp
.getLength();
1368 pData
= tmp
.getStr();
1373 *buffer
= new char[ 1 + nSize
];
1374 (*buffer
)[nSize
] = 0;
1375 rtl_copyMemory( *buffer
, pData
, nSize
);
1380 *buffer
= new char[1]; // Initialize with 1 to avoid compiler warnings
1381 if( !bFoundAsEmpty
)
1382 m_aEmptyActiveTextSet
.insert( id
);
1387 void Databases::setInstallPath( const rtl::OUString
& aInstDir
)
1389 osl::MutexGuard
aGuard( m_aMutex
);
1391 osl::FileBase::getFileURLFromSystemPath( aInstDir
,m_aInstallDirectory
);
1392 //TODO: check returned error code
1394 if( m_aInstallDirectory
.lastIndexOf( sal_Unicode( '/' ) ) != m_aInstallDirectory
.getLength() - 1 )
1395 m_aInstallDirectory
+= rtl::OUString::createFromAscii( "/" );
1397 m_aInstallDirectoryWithoutEncoding
= rtl::Uri::decode( m_aInstallDirectory
,
1398 rtl_UriDecodeWithCharset
,
1399 RTL_TEXTENCODING_UTF8
);
1403 //===================================================================
1404 // class ExtensionIteratorBase
1406 ExtensionHelpExistanceMap
ExtensionIteratorBase::aHelpExistanceMap
;
1408 ExtensionIteratorBase::ExtensionIteratorBase( Reference
< XComponentContext
> xContext
,
1409 Databases
& rDatabases
, const rtl::OUString
& aInitialModule
, const rtl::OUString
& aLanguage
)
1410 : m_xContext( xContext
)
1411 , m_rDatabases( rDatabases
)
1412 , m_eState( INITIAL_MODULE
)
1413 , m_aInitialModule( aInitialModule
)
1414 , m_aLanguage( aLanguage
)
1419 ExtensionIteratorBase::ExtensionIteratorBase( Databases
& rDatabases
,
1420 const rtl::OUString
& aInitialModule
, const rtl::OUString
& aLanguage
)
1421 : m_rDatabases( rDatabases
)
1422 , m_eState( INITIAL_MODULE
)
1423 , m_aInitialModule( aInitialModule
)
1424 , m_aLanguage( aLanguage
)
1429 void ExtensionIteratorBase::init()
1431 if( !m_xContext
.is() )
1433 Reference
< XMultiServiceFactory
> xFactory
= comphelper::getProcessServiceFactory();
1434 Reference
< XPropertySet
> xProps( xFactory
, UNO_QUERY
);
1435 OSL_ASSERT( xProps
.is() );
1438 xProps
->getPropertyValue(
1439 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= m_xContext
;
1440 OSL_ASSERT( m_xContext
.is() );
1443 if( !m_xContext
.is() )
1445 throw RuntimeException(
1446 ::rtl::OUString::createFromAscii( "ExtensionIteratorBase::init(), no XComponentContext" ),
1447 Reference
< XInterface
>() );
1450 Reference
< XMultiComponentFactory
> xSMgr( m_xContext
->getServiceManager(), UNO_QUERY
);
1451 m_xSFA
= Reference
< ucb::XSimpleFileAccess
>(
1452 xSMgr
->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ),
1453 m_xContext
), UNO_QUERY_THROW
);
1455 m_bUserPackagesLoaded
= false;
1456 m_bSharedPackagesLoaded
= false;
1458 m_iSharedPackage
= 0;
1461 Reference
< deployment::XPackage
> ExtensionIteratorBase::implGetHelpPackageFromPackage
1462 ( Reference
< deployment::XPackage
> xPackage
, Reference
< deployment::XPackage
>& o_xParentPackageBundle
)
1464 o_xParentPackageBundle
.clear();
1466 Reference
< deployment::XPackage
> xHelpPackage
;
1467 if( !xPackage
.is() )
1468 return xHelpPackage
;
1470 // #i84550 Cache information about help content in extension
1471 rtl::OUString aExtensionPath
= xPackage
->getURL();
1472 ExtensionHelpExistanceMap::iterator it
= aHelpExistanceMap
.find( aExtensionPath
);
1473 bool bFound
= ( it
!= aHelpExistanceMap
.end() );
1474 bool bHasHelp
= bFound
? it
->second
: false;
1475 if( bFound
&& !bHasHelp
)
1476 return xHelpPackage
;
1478 // Check if parent package is registered
1479 beans::Optional
< beans::Ambiguous
<sal_Bool
> > option( xPackage
->isRegistered
1480 ( Reference
<task::XAbortChannel
>(), Reference
<ucb::XCommandEnvironment
>() ) );
1481 bool bRegistered
= false;
1482 if( option
.IsPresent
)
1484 beans::Ambiguous
<sal_Bool
> const & reg
= option
.Value
;
1485 if( !reg
.IsAmbiguous
&& reg
.Value
)
1490 if( xPackage
->isBundle() )
1492 Sequence
< Reference
< deployment::XPackage
> > aPkgSeq
= xPackage
->getBundle
1493 ( Reference
<task::XAbortChannel
>(), Reference
<ucb::XCommandEnvironment
>() );
1494 sal_Int32 nPkgCount
= aPkgSeq
.getLength();
1495 const Reference
< deployment::XPackage
>* pSeq
= aPkgSeq
.getConstArray();
1496 for( sal_Int32 iPkg
= 0 ; iPkg
< nPkgCount
; ++iPkg
)
1498 const Reference
< deployment::XPackage
> xSubPkg
= pSeq
[ iPkg
];
1499 const Reference
< deployment::XPackageTypeInfo
> xPackageTypeInfo
= xSubPkg
->getPackageType();
1500 rtl::OUString aMediaType
= xPackageTypeInfo
->getMediaType();
1501 if( aMediaType
.equals( aHelpMediaType
) )
1503 xHelpPackage
= xSubPkg
;
1504 o_xParentPackageBundle
= xPackage
;
1511 const Reference
< deployment::XPackageTypeInfo
> xPackageTypeInfo
= xPackage
->getPackageType();
1512 rtl::OUString aMediaType
= xPackageTypeInfo
->getMediaType();
1513 if( aMediaType
.equals( aHelpMediaType
) )
1514 xHelpPackage
= xPackage
;
1519 aHelpExistanceMap
[ aExtensionPath
] = xHelpPackage
.is();
1521 return xHelpPackage
;
1524 Reference
< deployment::XPackage
> ExtensionIteratorBase::implGetNextUserHelpPackage
1525 ( Reference
< deployment::XPackage
>& o_xParentPackageBundle
)
1527 Reference
< deployment::XPackage
> xHelpPackage
;
1529 if( !m_bUserPackagesLoaded
)
1531 Reference
< XPackageManager
> xUserManager
=
1532 thePackageManagerFactory::get( m_xContext
)->getPackageManager( rtl::OUString::createFromAscii("user") );
1533 m_aUserPackagesSeq
= xUserManager
->getDeployedPackages
1534 ( Reference
< task::XAbortChannel
>(), Reference
< ucb::XCommandEnvironment
>() );
1536 m_bUserPackagesLoaded
= true;
1539 if( m_iUserPackage
== m_aUserPackagesSeq
.getLength() )
1541 m_eState
= SHARED_EXTENSIONS
; // Later: SHARED_MODULE
1545 const Reference
< deployment::XPackage
>* pUserPackages
= m_aUserPackagesSeq
.getConstArray();
1546 Reference
< deployment::XPackage
> xPackage
= pUserPackages
[ m_iUserPackage
++ ];
1547 VOS_ENSURE( xPackage
.is(), "ExtensionIteratorBase::implGetNextUserHelpPackage(): Invalid package" );
1548 xHelpPackage
= implGetHelpPackageFromPackage( xPackage
, o_xParentPackageBundle
);
1551 return xHelpPackage
;
1554 Reference
< deployment::XPackage
> ExtensionIteratorBase::implGetNextSharedHelpPackage
1555 ( Reference
< deployment::XPackage
>& o_xParentPackageBundle
)
1557 Reference
< deployment::XPackage
> xHelpPackage
;
1559 if( !m_bSharedPackagesLoaded
)
1561 Reference
< XPackageManager
> xSharedManager
=
1562 thePackageManagerFactory::get( m_xContext
)->getPackageManager( rtl::OUString::createFromAscii("shared") );
1563 m_aSharedPackagesSeq
= xSharedManager
->getDeployedPackages
1564 ( Reference
< task::XAbortChannel
>(), Reference
< ucb::XCommandEnvironment
>() );
1566 m_bSharedPackagesLoaded
= true;
1569 if( m_iSharedPackage
== m_aSharedPackagesSeq
.getLength() )
1571 m_eState
= END_REACHED
;
1575 const Reference
< deployment::XPackage
>* pSharedPackages
= m_aSharedPackagesSeq
.getConstArray();
1576 Reference
< deployment::XPackage
> xPackage
= pSharedPackages
[ m_iSharedPackage
++ ];
1577 VOS_ENSURE( xPackage
.is(), "ExtensionIteratorBase::implGetNextSharedHelpPackage(): Invalid package" );
1578 xHelpPackage
= implGetHelpPackageFromPackage( xPackage
, o_xParentPackageBundle
);
1581 return xHelpPackage
;
1584 rtl::OUString
ExtensionIteratorBase::implGetFileFromPackage(
1585 const rtl::OUString
& rFileExtension
, Reference
< deployment::XPackage
> xPackage
)
1587 // No extension -> search for pure language folder
1588 bool bLangFolderOnly
= (rFileExtension
.getLength() == 0);
1590 rtl::OUString aFile
;
1591 rtl::OUString aLanguage
= m_aLanguage
;
1592 for( sal_Int32 iPass
= 0 ; iPass
< 2 ; ++iPass
)
1594 rtl::OUStringBuffer aStrBuf
;
1595 aStrBuf
.append( xPackage
->getURL() );
1596 aStrBuf
.append( aSlash
);
1597 aStrBuf
.append( aLanguage
);
1598 if( !bLangFolderOnly
)
1600 aStrBuf
.append( aSlash
);
1601 aStrBuf
.append( aHelpFilesBaseName
);
1602 aStrBuf
.append( rFileExtension
);
1605 aFile
= m_rDatabases
.expandURL( aStrBuf
.makeStringAndClear() );
1608 if( m_xSFA
->exists( aFile
) )
1611 ::std::vector
< ::rtl::OUString
> av
;
1612 implGetLanguageVectorFromPackage( av
, xPackage
);
1613 ::std::vector
< ::rtl::OUString
>::const_iterator pFound
= av
.end();
1616 pFound
= ::comphelper::Locale::getFallback( av
, m_aLanguage
);
1618 catch( ::comphelper::Locale::MalFormedLocaleException
& )
1620 if( pFound
!= av
.end() )
1621 aLanguage
= *pFound
;
1627 inline bool isLetter( sal_Unicode c
)
1629 bool bLetter
= ((c
>= 'A' && c
<= 'Z') || (c
>= 'a' && c
<= 'z'));
1633 void ExtensionIteratorBase::implGetLanguageVectorFromPackage( ::std::vector
< ::rtl::OUString
> &rv
,
1634 com::sun::star::uno::Reference
< com::sun::star::deployment::XPackage
> xPackage
)
1637 rtl::OUString aExtensionPath
= xPackage
->getURL();
1638 Sequence
< rtl::OUString
> aEntrySeq
= m_xSFA
->getFolderContents( aExtensionPath
, true );
1640 const rtl::OUString
* pSeq
= aEntrySeq
.getConstArray();
1641 sal_Int32 nCount
= aEntrySeq
.getLength();
1642 for( sal_Int32 i
= 0 ; i
< nCount
; ++i
)
1644 rtl::OUString aEntry
= pSeq
[i
];
1645 if( m_xSFA
->isFolder( aEntry
) )
1647 sal_Int32 nLastSlash
= aEntry
.lastIndexOf( '/' );
1648 if( nLastSlash
!= -1 )
1650 rtl::OUString aPureEntry
= aEntry
.copy( nLastSlash
+ 1 );
1652 // Check language sceme
1653 int nLen
= aPureEntry
.getLength();
1654 const sal_Unicode
* pc
= aPureEntry
.getStr();
1655 bool bStartCanBeLanguage
= ( nLen
>= 2 && isLetter( pc
[0] ) && isLetter( pc
[1] ) );
1656 bool bIsLanguage
= bStartCanBeLanguage
&&
1657 ( nLen
== 2 || (nLen
== 5 && pc
[2] == '-' && isLetter( pc
[3] ) && isLetter( pc
[4] )) );
1659 rv
.push_back( aPureEntry
);
1666 //===================================================================
1667 // class DataBaseIterator
1669 Db
* DataBaseIterator::nextDb( rtl::OUString
* o_pExtensionPath
)
1673 while( !pRetDb
&& m_eState
!= END_REACHED
)
1677 case INITIAL_MODULE
:
1678 pRetDb
= m_rDatabases
.getBerkeley( m_aInitialModule
, m_aLanguage
, m_bHelpText
);
1679 m_eState
= USER_EXTENSIONS
; // Later: SHARED_MODULE
1683 //case SHARED_MODULE
1686 case USER_EXTENSIONS
:
1688 Reference
< deployment::XPackage
> xParentPackageBundle
;
1689 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextUserHelpPackage( xParentPackageBundle
);
1690 if( !xHelpPackage
.is() )
1692 pRetDb
= implGetDbFromPackage( xHelpPackage
, o_pExtensionPath
);
1696 case SHARED_EXTENSIONS
:
1698 Reference
< deployment::XPackage
> xParentPackageBundle
;
1699 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextSharedHelpPackage( xParentPackageBundle
);
1700 if( !xHelpPackage
.is() )
1703 pRetDb
= implGetDbFromPackage( xHelpPackage
, o_pExtensionPath
);
1707 VOS_ENSURE( false, "DataBaseIterator::nextDb(): Invalid case END_REACHED" );
1715 Db
* DataBaseIterator::implGetDbFromPackage( Reference
< deployment::XPackage
> xPackage
,
1716 rtl::OUString
* o_pExtensionPath
)
1718 rtl::OUString aExtensionPath
= xPackage
->getURL();
1719 //if( o_pExtensionPath )
1720 //*o_pExtensionPath = aExtensionPath;
1721 aExtensionPath
+= aSlash
;
1723 rtl::OUString aUsedLanguage
= m_aLanguage
;
1724 Db
* pRetDb
= m_rDatabases
.getBerkeley( aHelpFilesBaseName
, aUsedLanguage
,
1725 m_bHelpText
, &aExtensionPath
);
1727 // Language fallback
1730 ::std::vector
< ::rtl::OUString
> av
;
1731 implGetLanguageVectorFromPackage( av
, xPackage
);
1732 ::std::vector
< ::rtl::OUString
>::const_iterator pFound
= av
.end();
1735 pFound
= ::comphelper::Locale::getFallback( av
, m_aLanguage
);
1737 catch( ::comphelper::Locale::MalFormedLocaleException
& )
1739 if( pFound
!= av
.end() )
1741 aUsedLanguage
= *pFound
;
1742 pRetDb
= m_rDatabases
.getBerkeley( aHelpFilesBaseName
, aUsedLanguage
, m_bHelpText
, &aExtensionPath
);
1746 if( o_pExtensionPath
)
1747 *o_pExtensionPath
= aExtensionPath
+ aUsedLanguage
;
1753 //===================================================================
1754 // class KeyDataBaseFileIterator
1756 rtl::OUString
KeyDataBaseFileIterator::nextDbFile( bool& o_rbExtension
)
1758 rtl::OUString aRetFile
;
1760 while( !aRetFile
.getLength() && m_eState
!= END_REACHED
)
1764 case INITIAL_MODULE
:
1766 m_rDatabases
.getInstallPathAsSystemPath() +
1767 m_rDatabases
.processLang( m_aLanguage
) + aSlash
+ m_aInitialModule
+
1768 rtl::OUString::createFromAscii( ".key" );
1770 o_rbExtension
= false;
1772 m_eState
= USER_EXTENSIONS
; // Later: SHARED_MODULE
1776 //case SHARED_MODULE
1779 case USER_EXTENSIONS
:
1781 Reference
< deployment::XPackage
> xParentPackageBundle
;
1782 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextUserHelpPackage( xParentPackageBundle
);
1783 if( !xHelpPackage
.is() )
1786 aRetFile
= implGetDbFileFromPackage( xHelpPackage
);
1787 o_rbExtension
= true;
1791 case SHARED_EXTENSIONS
:
1793 Reference
< deployment::XPackage
> xParentPackageBundle
;
1794 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextSharedHelpPackage( xParentPackageBundle
);
1795 if( !xHelpPackage
.is() )
1798 aRetFile
= implGetDbFileFromPackage( xHelpPackage
);
1799 o_rbExtension
= true;
1803 VOS_ENSURE( false, "DataBaseIterator::nextDbFile(): Invalid case END_REACHED" );
1811 rtl::OUString
KeyDataBaseFileIterator::implGetDbFileFromPackage
1812 ( Reference
< deployment::XPackage
> xPackage
)
1814 rtl::OUString aExpandedURL
=
1815 implGetFileFromPackage( rtl::OUString::createFromAscii( ".key" ), xPackage
);
1817 rtl::OUString aRetFile
;
1818 osl::FileBase::getSystemPathFromFileURL( aExpandedURL
, aRetFile
);
1824 //===================================================================
1825 // class JarFileIterator
1827 Reference
< XHierarchicalNameAccess
> JarFileIterator::nextJarFile
1828 ( Reference
< deployment::XPackage
>& o_xParentPackageBundle
, rtl::OUString
* o_pExtensionPath
)
1830 Reference
< XHierarchicalNameAccess
> xNA
;
1832 while( !xNA
.is() && m_eState
!= END_REACHED
)
1836 case INITIAL_MODULE
:
1837 xNA
= m_rDatabases
.jarFile( m_aInitialModule
, m_aLanguage
);
1838 m_eState
= USER_EXTENSIONS
; // Later: SHARED_MODULE
1842 //case SHARED_MODULE
1845 case USER_EXTENSIONS
:
1847 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextUserHelpPackage( o_xParentPackageBundle
);
1848 if( !xHelpPackage
.is() )
1851 xNA
= implGetJarFromPackage( xHelpPackage
, o_pExtensionPath
);
1855 case SHARED_EXTENSIONS
:
1857 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextSharedHelpPackage( o_xParentPackageBundle
);
1858 if( !xHelpPackage
.is() )
1861 xNA
= implGetJarFromPackage( xHelpPackage
, o_pExtensionPath
);
1865 VOS_ENSURE( false, "JarFileIterator::nextJarFile(): Invalid case END_REACHED" );
1873 Reference
< XHierarchicalNameAccess
> JarFileIterator::implGetJarFromPackage
1874 ( Reference
< deployment::XPackage
> xPackage
, rtl::OUString
* o_pExtensionPath
)
1876 Reference
< XHierarchicalNameAccess
> xNA
;
1878 rtl::OUString zipFile
=
1879 implGetFileFromPackage( rtl::OUString::createFromAscii( ".jar" ), xPackage
);
1883 Sequence
< Any
> aArguments( 2 );
1884 aArguments
[ 0 ] <<= zipFile
;
1886 // let ZipPackage be used ( no manifest.xml is required )
1887 beans::NamedValue aArg
;
1888 aArg
.Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StorageFormat" ) );
1889 aArg
.Value
<<= ZIP_STORAGE_FORMAT_STRING
;
1890 aArguments
[ 1 ] <<= aArg
;
1892 Reference
< XMultiComponentFactory
>xSMgr( m_xContext
->getServiceManager(), UNO_QUERY
);
1893 Reference
< XInterface
> xIfc
1894 = xSMgr
->createInstanceWithArgumentsAndContext(
1895 rtl::OUString::createFromAscii(
1896 "com.sun.star.packages.comp.ZipPackage" ),
1897 aArguments
, m_xContext
);
1901 xNA
= Reference
< XHierarchicalNameAccess
>( xIfc
, UNO_QUERY
);
1903 VOS_ENSURE( xNA
.is(),
1904 "JarFileIterator::implGetJarFromPackage() - "
1905 "Got no hierarchical name access!" );
1908 catch ( RuntimeException
& )
1910 catch ( Exception
& )
1913 if( xNA
.is() && o_pExtensionPath
!= NULL
)
1915 // Extract path including language from file name
1916 sal_Int32 nLastSlash
= zipFile
.lastIndexOf( '/' );
1917 if( nLastSlash
!= -1 )
1918 *o_pExtensionPath
= zipFile
.copy( 0, nLastSlash
);
1925 //===================================================================
1926 // class IndexFolderIterator
1928 rtl::OUString
IndexFolderIterator::nextIndexFolder( bool& o_rbExtension
, bool& o_rbTemporary
)
1930 rtl::OUString aIndexFolder
;
1932 while( !aIndexFolder
.getLength() && m_eState
!= END_REACHED
)
1936 case INITIAL_MODULE
:
1938 m_rDatabases
.getInstallPathAsURL() +
1939 m_rDatabases
.processLang( m_aLanguage
) + aSlash
+ m_aInitialModule
+
1940 rtl::OUString::createFromAscii( ".idxl" );
1942 o_rbTemporary
= false;
1943 o_rbExtension
= false;
1945 m_eState
= USER_EXTENSIONS
; // Later: SHARED_MODULE
1949 //case SHARED_MODULE
1952 case USER_EXTENSIONS
:
1954 Reference
< deployment::XPackage
> xParentPackageBundle
;
1955 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextUserHelpPackage( xParentPackageBundle
);
1956 if( !xHelpPackage
.is() )
1959 aIndexFolder
= implGetIndexFolderFromPackage( o_rbTemporary
, xHelpPackage
);
1960 o_rbExtension
= true;
1964 case SHARED_EXTENSIONS
:
1966 Reference
< deployment::XPackage
> xParentPackageBundle
;
1967 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextSharedHelpPackage( xParentPackageBundle
);
1968 if( !xHelpPackage
.is() )
1971 aIndexFolder
= implGetIndexFolderFromPackage( o_rbTemporary
, xHelpPackage
);
1972 o_rbExtension
= true;
1976 VOS_ENSURE( false, "IndexFolderIterator::nextIndexFolder(): Invalid case END_REACHED" );
1981 return aIndexFolder
;
1984 rtl::OUString
IndexFolderIterator::implGetIndexFolderFromPackage( bool& o_rbTemporary
, Reference
< deployment::XPackage
> xPackage
)
1986 rtl::OUString aIndexFolder
=
1987 implGetFileFromPackage( rtl::OUString::createFromAscii( ".idxl" ), xPackage
);
1989 o_rbTemporary
= false;
1990 if( !m_xSFA
->isFolder( aIndexFolder
) )
1992 // i98680: Missing index? Try to generate now
1993 rtl::OUString aLangURL
= implGetFileFromPackage( rtl::OUString(), xPackage
);
1994 if( m_xSFA
->isFolder( aLangURL
) )
1996 // Test write access (shared extension may be read only)
1997 bool bIsWriteAccess
= false;
2000 rtl::OUString aCreateTestFolder
= aLangURL
+ rtl::OUString::createFromAscii( "CreateTestFolder" );
2001 m_xSFA
->createFolder( aCreateTestFolder
);
2002 if( m_xSFA
->isFolder( aCreateTestFolder
) )
2003 bIsWriteAccess
= true;
2005 m_xSFA
->kill( aCreateTestFolder
);
2011 //bIsWriteAccess = false;
2013 Reference
< script::XInvocation
> xInvocation
;
2014 Reference
< XMultiComponentFactory
>xSMgr( m_xContext
->getServiceManager(), UNO_QUERY
);
2017 xInvocation
= Reference
< script::XInvocation
>(
2018 m_xContext
->getServiceManager()->createInstanceWithContext( rtl::OUString::createFromAscii(
2019 "com.sun.star.help.HelpIndexer" ), m_xContext
) , UNO_QUERY
);
2021 if( xInvocation
.is() )
2023 Sequence
<uno::Any
> aParamsSeq( bIsWriteAccess
? 6 : 8 );
2025 aParamsSeq
[0] = uno::makeAny( rtl::OUString::createFromAscii( "-lang" ) );
2027 rtl::OUString aLang
;
2028 sal_Int32 nLastSlash
= aLangURL
.lastIndexOf( '/' );
2029 if( nLastSlash
!= -1 )
2030 aLang
= aLangURL
.copy( nLastSlash
+ 1 );
2032 aLang
= rtl::OUString::createFromAscii( "en" );
2033 aParamsSeq
[1] = uno::makeAny( aLang
);
2035 aParamsSeq
[2] = uno::makeAny( rtl::OUString::createFromAscii( "-mod" ) );
2036 aParamsSeq
[3] = uno::makeAny( rtl::OUString::createFromAscii( "help" ) );
2038 rtl::OUString aZipDir
= aLangURL
;
2039 if( !bIsWriteAccess
)
2041 rtl::OUString aTempFileURL
;
2042 ::osl::FileBase::RC eErr
= ::osl::File::createTempFile( 0, 0, &aTempFileURL
);
2043 if( eErr
== ::osl::FileBase::E_None
)
2045 rtl::OUString aTempDirURL
= aTempFileURL
;
2048 m_xSFA
->kill( aTempDirURL
);
2052 m_xSFA
->createFolder( aTempDirURL
);
2054 aZipDir
= aTempDirURL
;
2055 o_rbTemporary
= true;
2059 aParamsSeq
[4] = uno::makeAny( rtl::OUString::createFromAscii( "-zipdir" ) );
2060 rtl::OUString aSystemPath
;
2061 osl::FileBase::getSystemPathFromFileURL( aZipDir
, aSystemPath
);
2062 aParamsSeq
[5] = uno::makeAny( aSystemPath
);
2064 if( !bIsWriteAccess
)
2066 aParamsSeq
[6] = uno::makeAny( rtl::OUString::createFromAscii( "-srcdir" ) );
2067 rtl::OUString aSrcDirVal
;
2068 osl::FileBase::getSystemPathFromFileURL( aLangURL
, aSrcDirVal
);
2069 aParamsSeq
[7] = uno::makeAny( aSrcDirVal
);
2072 Sequence
< sal_Int16
> aOutParamIndex
;
2073 Sequence
< uno::Any
> aOutParam
;
2074 uno::Any aRet
= xInvocation
->invoke( rtl::OUString::createFromAscii( "createIndex" ),
2075 aParamsSeq
, aOutParamIndex
, aOutParam
);
2077 if( bIsWriteAccess
)
2078 aIndexFolder
= implGetFileFromPackage( rtl::OUString::createFromAscii( ".idxl" ), xPackage
);
2080 aIndexFolder
= aZipDir
+ rtl::OUString::createFromAscii( "/help.idxl" );
2088 return aIndexFolder
;
2091 void IndexFolderIterator::deleteTempIndexFolder( const rtl::OUString
& aIndexFolder
)
2093 sal_Int32 nLastSlash
= aIndexFolder
.lastIndexOf( '/' );
2094 if( nLastSlash
!= -1 )
2096 rtl::OUString aTmpFolder
= aIndexFolder
.copy( 0, nLastSlash
);
2099 m_xSFA
->kill( aTmpFolder
);