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/frame/XConfigManager.hpp>
55 #include <com/sun/star/util/XMacroExpander.hpp>
56 #include <com/sun/star/uri/XUriReferenceFactory.hpp>
57 #include <com/sun/star/uri/XVndSunStarExpandUrl.hpp>
58 #include <com/sun/star/script/XInvocation.hpp>
59 #include <comphelper/locale.hxx>
61 #include <xmlhelp/compilehelp.hxx>
63 #include "databases.hxx"
64 #include "urlparameter.hxx"
66 using namespace chelp
;
67 using namespace berkeleydbproxy
;
68 using namespace com::sun::star
;
69 using namespace com::sun::star::uno
;
70 using namespace com::sun::star::io
;
71 using namespace com::sun::star::container
;
72 using namespace com::sun::star::i18n
;
73 using namespace com::sun::star::lang
;
74 using namespace com::sun::star::deployment
;
75 using namespace com::sun::star::beans
;
78 static rtl::OUString
aSlash( rtl::OUString::createFromAscii( "/" ) );
79 static rtl::OUString
aHelpFilesBaseName( rtl::OUString::createFromAscii( "help" ) );
80 static rtl::OUString
aHelpMediaType( rtl::OUString::createFromAscii( "application/vnd.sun.star.help" ) );
82 rtl::OUString
Databases::expandURL( const rtl::OUString
& aURL
)
84 osl::MutexGuard
aGuard( m_aMutex
);
85 rtl::OUString aRetURL
= expandURL( aURL
, m_xContext
);
89 rtl::OUString
Databases::expandURL( const rtl::OUString
& aURL
, Reference
< uno::XComponentContext
> xContext
)
91 static Reference
< util::XMacroExpander
> xMacroExpander
;
92 static Reference
< uri::XUriReferenceFactory
> xFac
;
95 return rtl::OUString();
97 if( !xMacroExpander
.is() || !xFac
.is() )
99 Reference
< XMultiComponentFactory
> xSMgr( xContext
->getServiceManager(), UNO_QUERY
);
101 xFac
= Reference
< uri::XUriReferenceFactory
>(
102 xSMgr
->createInstanceWithContext( rtl::OUString::createFromAscii(
103 "com.sun.star.uri.UriReferenceFactory"), xContext
) , UNO_QUERY
);
106 throw RuntimeException(
107 ::rtl::OUString::createFromAscii( "Databases::expand(), could not instatiate UriReferenceFactory." ),
108 Reference
< XInterface
>() );
111 xMacroExpander
= Reference
< util::XMacroExpander
>(
112 xContext
->getValueByName(
113 ::rtl::OUString::createFromAscii( "/singletons/com.sun.star.util.theMacroExpander" ) ),
117 rtl::OUString aRetURL
= aURL
;
118 if( xMacroExpander
.is() )
120 Reference
< uri::XUriReference
> uriRef
;
123 uriRef
= Reference
< uri::XUriReference
>( xFac
->parse( aRetURL
), UNO_QUERY
);
126 Reference
< uri::XVndSunStarExpandUrl
> sxUri( uriRef
, UNO_QUERY
);
130 aRetURL
= sxUri
->expand( xMacroExpander
);
137 Databases::Databases( sal_Bool showBasic
,
138 const rtl::OUString
& instPath
,
139 const com::sun::star::uno::Sequence
< rtl::OUString
>& imagesZipPaths
,
140 const rtl::OUString
& productName
,
141 const rtl::OUString
& productVersion
,
142 const rtl::OUString
& vendorName
,
143 const rtl::OUString
& vendorVersion
,
144 const rtl::OUString
& vendorShort
,
145 const rtl::OUString
& styleSheet
,
146 Reference
< uno::XComponentContext
> xContext
)
147 : m_xContext( xContext
),
148 m_bShowBasic(showBasic
),
149 m_nErrorDocLength( 0 ),
151 m_nCustomCSSDocLength( 0 ),
152 m_pCustomCSSDoc( 0 ),
153 m_aCSS(styleSheet
.toAsciiLowerCase()),
154 newProdName(rtl::OUString::createFromAscii( "$[officename]" ) ),
155 newProdVersion(rtl::OUString::createFromAscii( "$[officeversion]" ) ),
156 prodName( rtl::OUString::createFromAscii( "%PRODUCTNAME" ) ),
157 prodVersion( rtl::OUString::createFromAscii( "%PRODUCTVERSION" ) ),
158 vendName( rtl::OUString::createFromAscii( "%VENDORNAME" ) ),
159 vendVersion( rtl::OUString::createFromAscii( "%VENDORVERSION" ) ),
160 vendShort( rtl::OUString::createFromAscii( "%VENDORSHORT" ) ),
161 m_aImagesZipPaths( imagesZipPaths
),
164 m_xSMgr
= Reference
< XMultiComponentFactory
>( m_xContext
->getServiceManager(), UNO_QUERY
);
174 m_vReplacement
[0] = productName
;
175 m_vReplacement
[1] = productVersion
;
176 m_vReplacement
[2] = vendorName
;
177 m_vReplacement
[3] = vendorVersion
;
178 m_vReplacement
[4] = vendorShort
;
179 m_vReplacement
[5] = productName
;
180 m_vReplacement
[6] = productVersion
;
182 setInstallPath( instPath
);
184 m_xSFA
= Reference
< ucb::XSimpleFileAccess
>(
185 m_xSMgr
->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ),
186 m_xContext
), UNO_QUERY_THROW
);
189 Databases::~Databases()
191 // release stylesheet
193 delete[] m_pCustomCSSDoc
;
195 // release errorDocument
197 delete[] m_pErrorDoc
;
199 // unload the databases
203 DatabasesTable::iterator it
= m_aDatabases
.begin();
204 while( it
!= m_aDatabases
.end() )
207 it
->second
->close( 0 );
216 ModInfoTable::iterator it
= m_aModInfo
.begin();
217 while( it
!= m_aModInfo
.end() )
227 KeywordInfoTable::iterator it
= m_aKeywordInfo
.begin();
228 while( it
!= m_aKeywordInfo
.end() )
237 static bool impl_getZipFile(
238 Sequence
< rtl::OUString
> & rImagesZipPaths
,
239 const rtl::OUString
& rZipName
,
240 rtl::OUString
& rFileName
)
242 rtl::OUString aWorkingDir
;
243 osl_getProcessWorkingDir( &aWorkingDir
.pData
);
244 const rtl::OUString
*pPathArray
= rImagesZipPaths
.getArray();
245 for ( int i
= 0; i
< rImagesZipPaths
.getLength(); ++i
)
247 rtl::OUString aFileName
= pPathArray
[ i
];
248 if ( aFileName
.getLength() )
250 if ( 1 + aFileName
.lastIndexOf( '/' ) != aFileName
.getLength() )
252 aFileName
+= rtl::OUString::createFromAscii( "/" );
254 aFileName
+= rZipName
;
255 // the icons are not read when the URL is a symlink
256 osl::File::getAbsoluteFileURL( aWorkingDir
, aFileName
, rFileName
);
259 osl::DirectoryItem aDirItem
;
260 if ( osl::DirectoryItem::get( rFileName
, aDirItem
) == osl::FileBase::E_None
)
267 rtl::OString
Databases::getImagesZipFileURL()
269 sal_Int16 nSymbolsStyle
= SvtMiscOptions().GetCurrentSymbolsStyle();
270 if ( !m_aImagesZipFileURL
.getLength() || ( m_nSymbolsStyle
!= nSymbolsStyle
) )
272 m_nSymbolsStyle
= nSymbolsStyle
;
274 rtl::OUString aImageZip
;
275 rtl::OUString aSymbolsStyleName
= SvtMiscOptions().GetCurrentSymbolsStyleName();
278 if ( aSymbolsStyleName
.getLength() != 0 )
280 rtl::OUString aZipName
= rtl::OUString::createFromAscii( "images_" );
281 aZipName
+= aSymbolsStyleName
;
282 aZipName
+= rtl::OUString::createFromAscii( ".zip" );
284 bFound
= impl_getZipFile( m_aImagesZipPaths
, aZipName
, aImageZip
);
288 bFound
= impl_getZipFile( m_aImagesZipPaths
, rtl::OUString::createFromAscii( "images.zip" ), aImageZip
);
291 aImageZip
= rtl::OUString();
293 m_aImagesZipFileURL
= rtl::OUStringToOString(
296 rtl_UriCharClassPchar
,
297 rtl_UriEncodeIgnoreEscapes
,
298 RTL_TEXTENCODING_UTF8
), RTL_TEXTENCODING_UTF8
);
301 return m_aImagesZipFileURL
;
305 void Databases::replaceName( rtl::OUString
& oustring
) const
307 sal_Int32 idx
= -1,idx1
= -1,idx2
= -1,k
= 0,off
;
309 rtl::OUStringBuffer
aStrBuf( 0 );
314 idx1
= oustring
.indexOf( sal_Unicode('%'),idx
);
315 idx2
= oustring
.indexOf( sal_Unicode('$'),idx
);
317 if(idx1
== -1 && idx2
== -1)
328 else if(idx2
< idx1
)
332 if( oustring
.indexOf( prodName
,idx
) == idx
)
334 else if( oustring
.indexOf( prodVersion
,idx
) == idx
)
335 off
= PRODUCTVERSION
;
336 else if( oustring
.indexOf( vendName
,idx
) == idx
)
338 else if( oustring
.indexOf( vendVersion
,idx
) == idx
)
340 else if( oustring
.indexOf( vendShort
,idx
) == idx
)
342 else if( oustring
.indexOf( newProdName
,idx
) == idx
)
343 off
= NEWPRODUCTNAME
;
344 else if( oustring
.indexOf( newProdVersion
,idx
) == idx
)
345 off
= NEWPRODUCTVERSION
;
354 aStrBuf
.ensureCapacity( 256 );
357 aStrBuf
.append( &oustring
.getStr()[k
],idx
- k
);
358 aStrBuf
.append( m_vReplacement
[off
] );
359 k
= idx
+ m_vAdd
[off
];
365 if( k
< oustring
.getLength() )
366 aStrBuf
.append( &oustring
.getStr()[k
],oustring
.getLength()-k
);
367 oustring
= aStrBuf
.makeStringAndClear();
374 rtl::OUString
Databases::getInstallPathAsSystemPath()
376 osl::MutexGuard
aGuard( m_aMutex
);
378 if( ! m_aInstallDirectoryAsSystemPath
.getLength() )
382 osl::FileBase::E_None
==
383 osl::FileBase::getSystemPathFromFileURL( m_aInstallDirectory
,m_aInstallDirectoryAsSystemPath
);
384 VOS_ENSURE( bla
,"HelpProvider, no installpath" );
386 osl::FileBase::getSystemPathFromFileURL( m_aInstallDirectory
,m_aInstallDirectoryAsSystemPath
);
390 return m_aInstallDirectoryAsSystemPath
;
396 rtl::OUString
Databases::getInstallPathAsURL()
398 osl::MutexGuard
aGuard( m_aMutex
);
400 return m_aInstallDirectory
;
404 const std::vector
< rtl::OUString
>& Databases::getModuleList( const rtl::OUString
& Language
)
406 if( m_avModules
.size() == 0 )
408 rtl::OUString fileName
,dirName
= getInstallPathAsURL() + processLang( Language
);
409 osl::Directory
dirFile( dirName
);
411 osl::DirectoryItem aDirItem
;
412 osl::FileStatus
aStatus( FileStatusMask_FileName
);
416 if( osl::FileBase::E_None
!= dirFile
.open() )
419 while( dirFile
.getNextItem( aDirItem
) == osl::FileBase::E_None
&&
420 aDirItem
.getFileStatus( aStatus
) == osl::FileBase::E_None
)
422 if( ! aStatus
.isValid( FileStatusMask_FileName
) )
425 fileName
= aStatus
.getFileName();
427 // Check, whether fileName is of the form *.cfg
428 idx
= fileName
.lastIndexOf( sal_Unicode( '.' ) );
433 const sal_Unicode
* str
= fileName
.getStr();
435 if( fileName
.getLength() == idx
+ 4 &&
436 ( str
[idx
+ 1] == 'c' || str
[idx
+ 1] == 'C' ) &&
437 ( str
[idx
+ 2] == 'f' || str
[idx
+ 2] == 'F' ) &&
438 ( str
[idx
+ 3] == 'g' || str
[idx
+ 3] == 'G' ) &&
439 ( fileName
= fileName
.copy(0,idx
).toAsciiLowerCase() ).compareToAscii( "picture" ) != 0 ) {
440 if(! m_bShowBasic
&& fileName
.compareToAscii("sbasic") == 0 )
442 m_avModules
.push_back( fileName
);
451 StaticModuleInformation
* Databases::getStaticInformationForModule( const rtl::OUString
& Module
,
452 const rtl::OUString
& Language
)
454 osl::MutexGuard
aGuard( m_aMutex
);
456 rtl::OUString key
= processLang(Language
) + rtl::OUString::createFromAscii( "/" ) + Module
;
458 std::pair
< ModInfoTable::iterator
,bool > aPair
=
459 m_aModInfo
.insert( ModInfoTable::value_type( key
,0 ) );
461 ModInfoTable::iterator it
= aPair
.first
;
463 if( aPair
.second
&& ! it
->second
)
465 osl::File
cfgFile( getInstallPathAsURL() +
467 rtl::OUString::createFromAscii( ".cfg" ) );
469 if( osl::FileBase::E_None
!= cfgFile
.open( OpenFlag_Read
) )
475 sal_Char buffer
[2048];
476 sal_Unicode lineBuffer
[1028];
477 rtl::OUString fileContent
;
479 while( osl::FileBase::E_None
== cfgFile
.read( &buffer
,2048,nRead
) && nRead
)
480 fileContent
+= rtl::OUString( buffer
,sal_Int32( nRead
),RTL_TEXTENCODING_UTF8
);
484 const sal_Unicode
* str
= fileContent
.getStr();
485 rtl::OUString current
,lang_
,program
,startid
,title
,heading
,fulltext
;
486 rtl::OUString order
= rtl::OUString::createFromAscii( "1" );
488 for( sal_Int32 i
= 0;i
< fileContent
.getLength();i
++ )
490 sal_Unicode ch
= str
[ i
];
491 if( ch
== sal_Unicode( '\n' ) || ch
== sal_Unicode( '\r' ) )
495 current
= rtl::OUString( lineBuffer
,pos
);
497 if( current
.compareToAscii( "Title",5 ) == 0 )
499 title
= current
.copy( current
.indexOf(sal_Unicode( '=' ) ) + 1 );
501 else if( current
.compareToAscii( "Start",5 ) == 0 )
503 startid
= current
.copy( current
.indexOf('=') + 1 );
505 else if( current
.compareToAscii( "Language",8 ) == 0 )
507 lang_
= current
.copy( current
.indexOf('=') + 1 );
509 else if( current
.compareToAscii( "Program",7 ) == 0 )
511 program
= current
.copy( current
.indexOf('=') + 1 );
513 else if( current
.compareToAscii( "Heading",7 ) == 0 )
515 heading
= current
.copy( current
.indexOf('=') + 1 );
517 else if( current
.compareToAscii( "FullText",8 ) == 0 )
519 fulltext
= current
.copy( current
.indexOf('=') + 1 );
521 else if( current
.compareToAscii( "Order",5 ) == 0 )
523 order
= current
.copy( current
.indexOf('=') + 1 );
529 lineBuffer
[ pos
++ ] = ch
;
531 replaceName( title
);
532 it
->second
= new StaticModuleInformation( title
,
547 rtl::OUString
Databases::processLang( const rtl::OUString
& Language
)
549 osl::MutexGuard
aGuard( m_aMutex
);
552 LangSetTable::iterator it
= m_aLangSet
.find( Language
);
554 if( it
== m_aLangSet
.end() )
557 osl::DirectoryItem aDirItem
;
559 if( osl::FileBase::E_None
== osl::DirectoryItem::get( getInstallPathAsURL() + Language
,aDirItem
) )
562 m_aLangSet
[ Language
] = ret
;
564 else if( ( ( idx
= Language
.indexOf( '-' ) ) != -1 ||
565 ( idx
= Language
.indexOf( '_' ) ) != -1 ) &&
566 osl::FileBase::E_None
== osl::DirectoryItem::get( getInstallPathAsURL() + Language
.copy( 0,idx
),
569 ret
= Language
.copy( 0,idx
);
570 m_aLangSet
[ Language
] = ret
;
580 rtl::OUString
Databases::country( const rtl::OUString
& Language
)
583 if( ( idx
= Language
.indexOf( '-' ) ) != -1 ||
584 ( idx
= Language
.indexOf( '_' ) ) != -1 )
585 return Language
.copy( 1+idx
);
587 return rtl::OUString();
592 Db
* Databases::getBerkeley( const rtl::OUString
& Database
,
593 const rtl::OUString
& Language
, bool helpText
,
594 const rtl::OUString
* pExtensionPath
)
596 if( ! Database
.getLength() || ! Language
.getLength() )
599 osl::MutexGuard
aGuard( m_aMutex
);
602 rtl::OUString
aFileExt( rtl::OUString::createFromAscii( helpText
? ".ht" : ".db" ) );
603 rtl::OUString dbFileName
= aSlash
+ Database
+ aFileExt
;
605 if( pExtensionPath
== NULL
)
606 key
= processLang( Language
) + dbFileName
;
608 key
= *pExtensionPath
+ Language
+ dbFileName
; // make unique, don't change language
610 std::pair
< DatabasesTable::iterator
,bool > aPair
=
611 m_aDatabases
.insert( DatabasesTable::value_type( key
,0 ) );
613 DatabasesTable::iterator it
= aPair
.first
;
615 if( aPair
.second
&& ! it
->second
)
617 Db
* table
= new Db();
619 rtl::OUString fileNameOU
;
622 rtl::OUString aExpandedURL
= expandURL( *pExtensionPath
);
623 aExpandedURL
+= Language
+ dbFileName
;
624 osl::FileBase::getSystemPathFromFileURL( aExpandedURL
, fileNameOU
);
627 fileNameOU
= getInstallPathAsSystemPath() + key
;
630 rtl::OString
fileName( fileNameOU
.getStr(),fileNameOU
.getLength(),osl_getThreadTextEncoding() );
632 rtl::OUString
fileNameDBHelp( fileNameOU
);
633 if( pExtensionPath
!= NULL
)
634 fileNameDBHelp
+= rtl::OUString::createFromAscii( "_" );
635 if( m_xSFA
->exists( fileNameDBHelp
) )
637 DBHelp
* pDBHelp
= new DBHelp( fileNameDBHelp
, m_xSFA
);
638 table
->setDBHelp( pDBHelp
);
642 bool bOldDbAccess
= false;
643 bSuccess
= pDBHelp
->testAgainstDb( fileName
, bOldDbAccess
);
646 bSuccess
= pDBHelp
->testAgainstDb( fileName
, bOldDbAccess
);
649 else if( table
->open( 0,fileName
.getStr(),0,DB_BTREE
,DB_RDONLY
,0644 ) )
662 Reference
< XCollator
>
663 Databases::getCollator( const rtl::OUString
& Language
,
664 const rtl::OUString
& System
)
668 rtl::OUString key
= Language
;
670 osl::MutexGuard
aGuard( m_aMutex
);
672 CollatorTable::iterator it
=
673 m_aCollatorTable
.insert( CollatorTable::value_type( key
,0 ) ).first
;
675 if( ! it
->second
.is() )
678 Reference
< XCollator
> (
679 m_xSMgr
->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.i18n.Collator" ),
680 m_xContext
), UNO_QUERY
);
681 rtl::OUString langStr
= processLang(Language
);
682 rtl::OUString countryStr
= country(Language
);
683 if( !countryStr
.getLength() )
685 if( langStr
.compareToAscii("de") == 0 )
686 countryStr
= rtl::OUString::createFromAscii("DE");
687 else if( langStr
.compareToAscii("en") == 0 )
688 countryStr
= rtl::OUString::createFromAscii("US");
689 else if( langStr
.compareToAscii("es") == 0 )
690 countryStr
= rtl::OUString::createFromAscii("ES");
691 else if( langStr
.compareToAscii("it") == 0 )
692 countryStr
= rtl::OUString::createFromAscii("IT");
693 else if( langStr
.compareToAscii("fr") == 0 )
694 countryStr
= rtl::OUString::createFromAscii("FR");
695 else if( langStr
.compareToAscii("sv") == 0 )
696 countryStr
= rtl::OUString::createFromAscii("SE");
697 else if( langStr
.compareToAscii("ja") == 0 )
698 countryStr
= rtl::OUString::createFromAscii("JP");
699 else if( langStr
.compareToAscii("ko") == 0 )
700 countryStr
= rtl::OUString::createFromAscii("KR");
702 it
->second
->loadDefaultCollator( Locale( langStr
,
715 struct KeywordElementComparator
717 KeywordElementComparator( const Reference
< XCollator
>& xCollator
)
718 : m_xCollator( xCollator
)
721 bool operator()( const KeywordInfo::KeywordElement
& la
,
722 const KeywordInfo::KeywordElement
& ra
) const
724 const rtl::OUString
& l
= la
.key
;
725 const rtl::OUString
& r
= ra
.key
;
729 if( m_xCollator
.is() )
731 sal_Int32 l1
= l
.indexOf( sal_Unicode( ';' ) );
732 sal_Int32 l3
= ( l1
== -1 ? l
.getLength() : l1
);
734 sal_Int32 r1
= r
.indexOf( sal_Unicode( ';' ) );
735 sal_Int32 r3
= ( r1
== -1 ? r
.getLength() : r1
);
737 sal_Int32 c1
= m_xCollator
->compareSubstring( l
,0,l3
,r
,0,r3
);
743 sal_Int32 l2
= l
.getLength() - l1
- 1;
744 sal_Int32 r2
= r
.getLength() - r1
- 1;
745 ret
= ( m_xCollator
->compareSubstring( l
,1+l1
,l2
,r
,1+r1
,r2
) < 0 );
756 Reference
< XCollator
> m_xCollator
;
757 }; // end struct KeywordElementComparator
763 KeywordInfo::KeywordElement::KeywordElement( Databases
*pDatabases
,
766 rtl::OUString
& data
)
769 pDatabases
->replaceName( key
);
770 init( pDatabases
,pDb
,data
);
775 void KeywordInfo::KeywordElement::init( Databases
*pDatabases
,Db
* pDb
,const rtl::OUString
& ids
)
777 const sal_Unicode
* idstr
= ids
.getStr();
778 std::vector
< rtl::OUString
> id
,anchor
;
780 while( ( idx
= ids
.indexOf( ';',k
= ++idx
) ) != -1 )
782 int h
= ids
.indexOf( sal_Unicode( '#' ),k
);
786 id
.push_back( rtl::OUString( &idstr
[k
],h
-k
) );
787 anchor
.push_back( rtl::OUString( &idstr
[h
+1],idx
-h
-1 ) );
791 id
.push_back( rtl::OUString( &idstr
[k
],idx
-k
) );
792 anchor
.push_back( rtl::OUString() );
796 listId
.realloc( id
.size() );
797 listAnchor
.realloc( id
.size() );
798 listTitle
.realloc( id
.size() );
801 const sal_Char
* pData
= NULL
;
802 const sal_Char pEmpty
[] = "";
804 for( sal_uInt32 i
= 0; i
< id
.size(); ++i
)
807 listAnchor
[i
] = anchor
[i
];
813 rtl::OString
idi( id
[i
].getStr(),id
[i
].getLength(),RTL_TEXTENCODING_UTF8
);
814 DBHelp
* pDBHelp
= pDb
->getDBHelp();
815 if( pDBHelp
!= NULL
)
818 bool bSuccess
= pDBHelp
->getValueForKey( idi
, aDBData
);
821 nSize
= aDBData
.getSize();
822 pData
= aDBData
.getData();
827 Dbt
key_( static_cast< void* >( const_cast< sal_Char
* >( idi
.getStr() ) ),
830 pDb
->get( 0,&key_
,&data
,0 );
831 nSize
= data
.get_size();
832 pData
= static_cast<sal_Char
*>( data
.get_data() );
836 DbtToStringConverter
converter( pData
, nSize
);
838 rtl::OUString title
= converter
.getTitle();
839 pDatabases
->replaceName( title
);
840 listTitle
[i
] = title
;
846 KeywordInfo::KeywordInfo( const std::vector
< KeywordElement
>& aVec
)
847 : listKey( aVec
.size() ),
848 listId( aVec
.size() ),
849 listAnchor( aVec
.size() ),
850 listTitle( aVec
.size() )
852 for( unsigned int i
= 0; i
< aVec
.size(); ++i
)
854 listKey
[i
] = aVec
[i
].key
;
855 listId
[i
] = aVec
[i
].listId
;
856 listAnchor
[i
] = aVec
[i
].listAnchor
;
857 listTitle
[i
] = aVec
[i
].listTitle
;
861 bool Databases::checkModuleMatchForExtension
862 ( const rtl::OUString
& Database
, const rtl::OUString
& doclist
)
864 bool bBelongsToDatabase
= true;
866 // Analyse doclist string to find module assignments
867 bool bFoundAtLeastOneModule
= false;
868 bool bModuleMatch
= false;
869 sal_Int32 nLen
= doclist
.getLength();
870 sal_Int32 nLastFound
= doclist
.lastIndexOf( sal_Unicode(';') );
871 if( nLastFound
== -1 )
873 const sal_Unicode
* pStr
= doclist
.getStr();
874 sal_Int32 nFound
= doclist
.lastIndexOf( sal_Unicode('_') );
875 while( nFound
!= -1 )
877 // Simple optimization, stop if '_' is followed by "id"
878 if( nLen
- nFound
> 2 )
880 if( pStr
[ nFound
+ 1 ] == sal_Unicode('i') &&
881 pStr
[ nFound
+ 2 ] == sal_Unicode('d') )
885 rtl::OUString aModule
= doclist
.copy( nFound
+ 1, nLastFound
- nFound
- 1 );
886 std::vector
< rtl::OUString
>::iterator result
= std::find( m_avModules
.begin(), m_avModules
.end(), aModule
);
887 if( result
!= m_avModules
.end() )
889 bFoundAtLeastOneModule
= true;
890 if( Database
== aModule
)
898 if( nLastFound
== 0 )
900 nFound
= doclist
.lastIndexOf( sal_Unicode('_'), nLastFound
- 1 );
903 if( bFoundAtLeastOneModule
&& !bModuleMatch
)
904 bBelongsToDatabase
= false;
906 return bBelongsToDatabase
;
910 KeywordInfo
* Databases::getKeyword( const rtl::OUString
& Database
,
911 const rtl::OUString
& Language
)
913 osl::MutexGuard
aGuard( m_aMutex
);
915 rtl::OUString key
= processLang(Language
) + rtl::OUString::createFromAscii( "/" ) + Database
;
917 std::pair
< KeywordInfoTable::iterator
,bool > aPair
=
918 m_aKeywordInfo
.insert( KeywordInfoTable::value_type( key
,0 ) );
920 KeywordInfoTable::iterator it
= aPair
.first
;
922 if( aPair
.second
&& ! it
->second
)
924 std::vector
<KeywordInfo::KeywordElement
> aVector
;
926 KeyDataBaseFileIterator
aDbFileIt( m_xContext
, *this, Database
, Language
);
927 rtl::OUString fileNameOU
;
928 bool bExtension
= false;
929 while( (fileNameOU
= aDbFileIt
.nextDbFile( bExtension
)).getLength() > 0 )
931 rtl::OString
fileName( fileNameOU
.getStr(),
932 fileNameOU
.getLength(),
933 osl_getThreadTextEncoding() );
937 rtl::OUString
fileNameDBHelp( fileNameOU
);
939 fileNameDBHelp
+= rtl::OUString::createFromAscii( "_" );
940 if( m_xSFA
->exists( fileNameDBHelp
) )
942 DBHelp
aDBHelp( fileNameDBHelp
, m_xSFA
);
946 if( aDBHelp
.startIteration() )
948 Db
* idmap
= getBerkeley( Database
,Language
);
950 DBHelp
* pDBHelp
= idmap
->getDBHelp();
951 if( pDBHelp
!= NULL
)
953 bool bOptimizeForPerformance
= true;
954 pDBHelp
->releaseHashMap();
955 pDBHelp
->createHashMap( bOptimizeForPerformance
);
958 while( aDBHelp
.getNextKeyAndValue( aKey
, aValue
) )
960 rtl::OUString
keyword( aKey
.getData(), aKey
.getSize(),
961 RTL_TEXTENCODING_UTF8
);
962 rtl::OUString
doclist( aValue
.getData(), aValue
.getSize(),
963 RTL_TEXTENCODING_UTF8
);
965 bool bBelongsToDatabase
= true;
967 bBelongsToDatabase
= checkModuleMatchForExtension( Database
, doclist
);
969 if( !bBelongsToDatabase
)
972 aVector
.push_back( KeywordInfo::KeywordElement( this,
977 aDBHelp
.stopIteration();
979 if( pDBHelp
!= NULL
)
980 pDBHelp
->releaseHashMap();
985 bool bOldDbAccess
= false;
986 bSuccess
= aDBHelp
.testAgainstDb( fileName
, bOldDbAccess
);
989 bSuccess
= aDBHelp
.testAgainstDb( fileName
, bOldDbAccess
);
995 else if( 0 == table
.open( 0,fileName
.getStr(),0,DB_BTREE
,DB_RDONLY
,0644 ) )
997 Db
* idmap
= getBerkeley( Database
,Language
);
1002 table
.cursor( 0,&cursor
,0 );
1004 key_
.set_flags( DB_DBT_MALLOC
); // Initially the cursor must allocate the necessary memory
1005 data
.set_flags( DB_DBT_MALLOC
);
1006 while( cursor
&& DB_NOTFOUND
!= cursor
->get( &key_
,&data
,DB_NEXT
) )
1008 rtl::OUString
keyword( static_cast<sal_Char
*>(key_
.get_data()),
1010 RTL_TEXTENCODING_UTF8
);
1011 rtl::OUString
doclist( static_cast<sal_Char
*>(data
.get_data()),
1013 RTL_TEXTENCODING_UTF8
);
1015 bool bBelongsToDatabase
= true;
1017 bBelongsToDatabase
= checkModuleMatchForExtension( Database
, doclist
);
1019 if( !bBelongsToDatabase
)
1022 aVector
.push_back( KeywordInfo::KeywordElement( this,
1028 key_
.set_flags( DB_DBT_REALLOC
);
1029 data
.set_flags( DB_DBT_REALLOC
);
1034 if( cursor
) cursor
->close();
1040 Reference
< XCollator
> xCollator
= getCollator( Language
,rtl::OUString());
1041 KeywordElementComparator
aComparator( xCollator
);
1042 std::sort(aVector
.begin(),aVector
.end(),aComparator
);
1044 KeywordInfo
* pInfo
= it
->second
= new KeywordInfo( aVector
);
1051 Reference
< XHierarchicalNameAccess
> Databases::jarFile( const rtl::OUString
& jar
,
1052 const rtl::OUString
& Language
)
1054 if( ! jar
.getLength() ||
1055 ! Language
.getLength() )
1057 return Reference
< XHierarchicalNameAccess
>( 0 );
1059 rtl::OUString key
= processLang(Language
) + aSlash
+ jar
;
1061 osl::MutexGuard
aGuard( m_aMutex
);
1063 ZipFileTable::iterator it
=
1064 m_aZipFileTable
.insert( ZipFileTable::value_type( key
,Reference
< XHierarchicalNameAccess
>(0) ) ).first
;
1066 if( ! it
->second
.is() )
1068 rtl::OUString zipFile
;
1071 // Extension jar file? Search for ?
1072 sal_Int32 nQuestionMark1
= jar
.indexOf( sal_Unicode('?') );
1073 sal_Int32 nQuestionMark2
= jar
.lastIndexOf( sal_Unicode('?') );
1074 if( nQuestionMark1
!= -1 && nQuestionMark2
!= -1 && nQuestionMark1
!= nQuestionMark2
)
1076 ::rtl::OUString aExtensionPath
= jar
.copy( nQuestionMark1
+ 1, nQuestionMark2
- nQuestionMark1
- 1 );
1077 ::rtl::OUString aPureJar
= jar
.copy( nQuestionMark2
+ 1 );
1079 rtl::OUStringBuffer aStrBuf
;
1080 aStrBuf
.append( aExtensionPath
);
1081 aStrBuf
.append( aSlash
);
1082 aStrBuf
.append( aPureJar
);
1084 zipFile
= expandURL( aStrBuf
.makeStringAndClear() );
1088 zipFile
= getInstallPathAsURL() + key
;
1091 Sequence
< Any
> aArguments( 1 );
1093 XInputStream_impl
* p
= new XInputStream_impl( zipFile
);
1094 if( p
->CtorSuccess() )
1096 Reference
< XInputStream
> xInputStream( p
);
1097 aArguments
[ 0 ] <<= xInputStream
;
1102 aArguments
[ 0 ] <<= zipFile
;
1105 Reference
< XInterface
> xIfc
1106 = m_xSMgr
->createInstanceWithArgumentsAndContext(
1107 rtl::OUString::createFromAscii(
1108 "com.sun.star.packages.comp.ZipPackage" ),
1109 aArguments
, m_xContext
);
1113 it
->second
= Reference
< XHierarchicalNameAccess
>( xIfc
, UNO_QUERY
);
1115 VOS_ENSURE( it
->second
.is(),
1116 "ContentProvider::createPackage - "
1117 "Got no hierarchical name access!" );
1121 catch ( RuntimeException
& )
1124 catch ( Exception
& )
1132 Reference
< XHierarchicalNameAccess
> Databases::findJarFileForPath
1133 ( const rtl::OUString
& jar
, const rtl::OUString
& Language
,
1134 const rtl::OUString
& path
, rtl::OUString
* o_pExtensionPath
)
1136 Reference
< XHierarchicalNameAccess
> xNA
;
1137 if( ! jar
.getLength() ||
1138 ! Language
.getLength() )
1143 JarFileIterator
aJarFileIt( m_xContext
, *this, jar
, Language
);
1144 Reference
< XHierarchicalNameAccess
> xTestNA
;
1145 Reference
< deployment::XPackage
> xParentPackageBundle
;
1146 while( (xTestNA
= aJarFileIt
.nextJarFile( xParentPackageBundle
, o_pExtensionPath
)).is() )
1148 if( xTestNA
.is() && xTestNA
->hasByHierarchicalName( path
) )
1150 bool bSuccess
= true;
1151 if( xParentPackageBundle
.is() )
1153 rtl::OUString aIdentifierInPath
;
1154 sal_Int32 nFindSlash
= path
.indexOf( '/' );
1155 if( nFindSlash
!= -1 )
1156 aIdentifierInPath
= path
.copy( 0, nFindSlash
);
1158 beans::Optional
<rtl::OUString
> aIdentifierOptional
= xParentPackageBundle
->getIdentifier();
1159 if( aIdentifierInPath
.getLength() && aIdentifierOptional
.IsPresent
)
1161 rtl::OUString aUnencodedIdentifier
= aIdentifierOptional
.Value
;
1162 rtl::OUString aIdentifier
= rtl::Uri::encode( aUnencodedIdentifier
,
1163 rtl_UriCharClassPchar
, rtl_UriEncodeIgnoreEscapes
, RTL_TEXTENCODING_UTF8
);
1165 if( !aIdentifierInPath
.equals( aIdentifier
) )
1167 // path does not start with extension identifier -> ignore
1173 // No identifier -> ignore
1189 void Databases::popupDocument( URLParameter
* urlPar
,char **buffer
,int *byteCount
)
1194 " <help:css-file-link xmlns:help=\"http://openoffice.org/2000/help\"/> "
1197 " <help:popup-cut Id=\"";
1198 const sal_Int32 l1
= strlen( pop1
);
1200 const char* pop3
= "\" Eid=\"";
1201 const sal_Int32 l3
= strlen( pop3
);
1204 "\" xmlns:help=\"http://openoffice.org/2000/help\"></help:popup-cut> "
1207 const sal_Int32 l5
= strlen( pop5
);
1210 rtl::OUString val
= urlPar
->get_id();
1211 rtl::OString
pop2O( val
.getStr(),l2
= val
.getLength(),RTL_TEXTENCODING_UTF8
);
1212 const char* pop2
= pop2O
.getStr();
1214 val
= urlPar
->get_eid();
1215 rtl::OString
pop4O( val
.getStr(),l4
= val
.getLength(),RTL_TEXTENCODING_UTF8
);
1216 const char* pop4
= pop4O
.getStr();
1218 (*byteCount
) = l1
+ l2
+ l3
+ l4
+ l5
;
1220 *buffer
= new char[ 1+*byteCount
];
1222 rtl_copyMemory( *buffer
,pop1
,l1
);
1223 rtl_copyMemory( *buffer
+l1
,pop2
,l2
);
1224 rtl_copyMemory( *buffer
+(l1
+l2
),pop3
,l3
);
1225 rtl_copyMemory( *buffer
+(l1
+l2
+l3
),pop4
,l4
);
1226 rtl_copyMemory( *buffer
+(l1
+l2
+l3
+l4
),pop5
,l5
);
1227 (*buffer
)[*byteCount
] = 0;
1231 void Databases::changeCSS(const rtl::OUString
& newStyleSheet
)
1233 m_aCSS
= newStyleSheet
.toAsciiLowerCase();
1234 delete[] m_pCustomCSSDoc
, m_pCustomCSSDoc
= 0,m_nCustomCSSDocLength
= 0;
1239 void Databases::cascadingStylesheet( const rtl::OUString
& Language
,
1243 if( ! m_pCustomCSSDoc
)
1247 rtl::OUString fileURL
;
1249 while( error
&& retry
)
1253 getInstallPathAsURL() +
1254 processLang( Language
) +
1255 rtl::OUString::createFromAscii( "/" ) +
1257 rtl::OUString::createFromAscii( ".css" );
1258 else if( retry
== 1 )
1260 getInstallPathAsURL() +
1262 rtl::OUString::createFromAscii( ".css" );
1264 osl::DirectoryItem aDirItem
;
1265 osl::File
aFile( fileURL
);
1266 osl::FileStatus
aStatus( FileStatusMask_FileSize
);
1268 if( osl::FileBase::E_None
== osl::DirectoryItem::get( fileURL
,aDirItem
) &&
1269 osl::FileBase::E_None
== aFile
.open( OpenFlag_Read
) &&
1270 osl::FileBase::E_None
== aDirItem
.getFileStatus( aStatus
) )
1273 aFile
.getSize( nSize
);
1274 m_nCustomCSSDocLength
= (int)nSize
;
1275 m_pCustomCSSDoc
= new char[ 1 + m_nCustomCSSDocLength
];
1276 m_pCustomCSSDoc
[ m_nCustomCSSDocLength
] = 0;
1277 sal_uInt64 a
= m_nCustomCSSDocLength
,b
= m_nCustomCSSDocLength
;
1278 aFile
.read( m_pCustomCSSDoc
,a
,b
);
1288 m_nCustomCSSDocLength
= 0;
1289 m_pCustomCSSDoc
= new char[ 1 ]; // Initialize with 1 to avoid gcc compiler warning
1293 *byteCount
= m_nCustomCSSDocLength
;
1294 *buffer
= new char[ 1 + *byteCount
];
1295 (*buffer
)[*byteCount
] = 0;
1296 rtl_copyMemory( *buffer
,m_pCustomCSSDoc
,m_nCustomCSSDocLength
);
1301 void Databases::setActiveText( const rtl::OUString
& Module
,
1302 const rtl::OUString
& Language
,
1303 const rtl::OUString
& Id
,
1307 DataBaseIterator
aDbIt( m_xContext
, *this, Module
, Language
, true );
1309 // #i84550 Cache information about failed ids
1310 rtl::OString
id( Id
.getStr(),Id
.getLength(),RTL_TEXTENCODING_UTF8
);
1311 EmptyActiveTextSet::iterator it
= m_aEmptyActiveTextSet
.find( id
);
1312 bool bFoundAsEmpty
= ( it
!= m_aEmptyActiveTextSet
.end() );
1317 const sal_Char
* pData
= NULL
;
1319 bool bSuccess
= false;
1320 if( !bFoundAsEmpty
)
1323 Dbt
key( static_cast< void* >( const_cast< sal_Char
* >( id
.getStr() ) ),id
.getLength() );
1324 while( !bSuccess
&& (db
= aDbIt
.nextDb()) != NULL
)
1326 DBHelp
* pDBHelp
= db
->getDBHelp();
1327 if( pDBHelp
!= NULL
)
1329 bSuccess
= pDBHelp
->getValueForKey( id
, aDBData
);
1330 nSize
= aDBData
.getSize();
1331 pData
= aDBData
.getData();
1335 int err
= db
->get( 0, &key
, &data
, 0 );
1339 nSize
= data
.get_size();
1340 pData
= static_cast<sal_Char
*>( data
.get_data() );
1348 // ensure existence of tmp after for
1350 for( int i
= 0; i
< nSize
; ++i
)
1351 if( pData
[i
] == '%' || pData
[i
] == '$' )
1353 // need of replacement
1354 rtl::OUString temp
= rtl::OUString( pData
, nSize
, RTL_TEXTENCODING_UTF8
);
1355 replaceName( temp
);
1356 tmp
= rtl::OString( temp
.getStr(),
1358 RTL_TEXTENCODING_UTF8
);
1359 nSize
= tmp
.getLength();
1360 pData
= tmp
.getStr();
1365 *buffer
= new char[ 1 + nSize
];
1366 (*buffer
)[nSize
] = 0;
1367 rtl_copyMemory( *buffer
, pData
, nSize
);
1372 *buffer
= new char[1]; // Initialize with 1 to avoid compiler warnings
1373 if( !bFoundAsEmpty
)
1374 m_aEmptyActiveTextSet
.insert( id
);
1379 void Databases::setInstallPath( const rtl::OUString
& aInstDir
)
1381 osl::MutexGuard
aGuard( m_aMutex
);
1383 osl::FileBase::getFileURLFromSystemPath( aInstDir
,m_aInstallDirectory
);
1384 //TODO: check returned error code
1386 if( m_aInstallDirectory
.lastIndexOf( sal_Unicode( '/' ) ) != m_aInstallDirectory
.getLength() - 1 )
1387 m_aInstallDirectory
+= rtl::OUString::createFromAscii( "/" );
1389 m_aInstallDirectoryWithoutEncoding
= rtl::Uri::decode( m_aInstallDirectory
,
1390 rtl_UriDecodeWithCharset
,
1391 RTL_TEXTENCODING_UTF8
);
1395 //===================================================================
1396 // class ExtensionIteratorBase
1398 ExtensionHelpExistanceMap
ExtensionIteratorBase::aHelpExistanceMap
;
1400 ExtensionIteratorBase::ExtensionIteratorBase( Reference
< XComponentContext
> xContext
,
1401 Databases
& rDatabases
, const rtl::OUString
& aInitialModule
, const rtl::OUString
& aLanguage
)
1402 : m_xContext( xContext
)
1403 , m_rDatabases( rDatabases
)
1404 , m_eState( INITIAL_MODULE
)
1405 , m_aInitialModule( aInitialModule
)
1406 , m_aLanguage( aLanguage
)
1411 ExtensionIteratorBase::ExtensionIteratorBase( Databases
& rDatabases
,
1412 const rtl::OUString
& aInitialModule
, const rtl::OUString
& aLanguage
)
1413 : m_rDatabases( rDatabases
)
1414 , m_eState( INITIAL_MODULE
)
1415 , m_aInitialModule( aInitialModule
)
1416 , m_aLanguage( aLanguage
)
1421 void ExtensionIteratorBase::init()
1423 if( !m_xContext
.is() )
1425 Reference
< XMultiServiceFactory
> xFactory
= comphelper::getProcessServiceFactory();
1426 Reference
< XPropertySet
> xProps( xFactory
, UNO_QUERY
);
1427 OSL_ASSERT( xProps
.is() );
1430 xProps
->getPropertyValue(
1431 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= m_xContext
;
1432 OSL_ASSERT( m_xContext
.is() );
1435 if( !m_xContext
.is() )
1437 throw RuntimeException(
1438 ::rtl::OUString::createFromAscii( "ExtensionIteratorBase::init(), no XComponentContext" ),
1439 Reference
< XInterface
>() );
1442 Reference
< XMultiComponentFactory
> xSMgr( m_xContext
->getServiceManager(), UNO_QUERY
);
1443 m_xSFA
= Reference
< ucb::XSimpleFileAccess
>(
1444 xSMgr
->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ),
1445 m_xContext
), UNO_QUERY_THROW
);
1447 m_bUserPackagesLoaded
= false;
1448 m_bSharedPackagesLoaded
= false;
1450 m_iSharedPackage
= 0;
1453 Reference
< deployment::XPackage
> ExtensionIteratorBase::implGetHelpPackageFromPackage
1454 ( Reference
< deployment::XPackage
> xPackage
, Reference
< deployment::XPackage
>& o_xParentPackageBundle
)
1456 o_xParentPackageBundle
.clear();
1458 Reference
< deployment::XPackage
> xHelpPackage
;
1459 if( !xPackage
.is() )
1460 return xHelpPackage
;
1462 // #i84550 Cache information about help content in extension
1463 rtl::OUString aExtensionPath
= xPackage
->getURL();
1464 ExtensionHelpExistanceMap::iterator it
= aHelpExistanceMap
.find( aExtensionPath
);
1465 bool bFound
= ( it
!= aHelpExistanceMap
.end() );
1466 bool bHasHelp
= bFound
? it
->second
: false;
1467 if( bFound
&& !bHasHelp
)
1468 return xHelpPackage
;
1470 // Check if parent package is registered
1471 beans::Optional
< beans::Ambiguous
<sal_Bool
> > option( xPackage
->isRegistered
1472 ( Reference
<task::XAbortChannel
>(), Reference
<ucb::XCommandEnvironment
>() ) );
1473 bool bRegistered
= false;
1474 if( option
.IsPresent
)
1476 beans::Ambiguous
<sal_Bool
> const & reg
= option
.Value
;
1477 if( !reg
.IsAmbiguous
&& reg
.Value
)
1482 if( xPackage
->isBundle() )
1484 Sequence
< Reference
< deployment::XPackage
> > aPkgSeq
= xPackage
->getBundle
1485 ( Reference
<task::XAbortChannel
>(), Reference
<ucb::XCommandEnvironment
>() );
1486 sal_Int32 nPkgCount
= aPkgSeq
.getLength();
1487 const Reference
< deployment::XPackage
>* pSeq
= aPkgSeq
.getConstArray();
1488 for( sal_Int32 iPkg
= 0 ; iPkg
< nPkgCount
; ++iPkg
)
1490 const Reference
< deployment::XPackage
> xSubPkg
= pSeq
[ iPkg
];
1491 const Reference
< deployment::XPackageTypeInfo
> xPackageTypeInfo
= xSubPkg
->getPackageType();
1492 rtl::OUString aMediaType
= xPackageTypeInfo
->getMediaType();
1493 if( aMediaType
.equals( aHelpMediaType
) )
1495 xHelpPackage
= xSubPkg
;
1496 o_xParentPackageBundle
= xPackage
;
1503 const Reference
< deployment::XPackageTypeInfo
> xPackageTypeInfo
= xPackage
->getPackageType();
1504 rtl::OUString aMediaType
= xPackageTypeInfo
->getMediaType();
1505 if( aMediaType
.equals( aHelpMediaType
) )
1506 xHelpPackage
= xPackage
;
1511 aHelpExistanceMap
[ aExtensionPath
] = xHelpPackage
.is();
1513 return xHelpPackage
;
1516 Reference
< deployment::XPackage
> ExtensionIteratorBase::implGetNextUserHelpPackage
1517 ( Reference
< deployment::XPackage
>& o_xParentPackageBundle
)
1519 Reference
< deployment::XPackage
> xHelpPackage
;
1521 if( !m_bUserPackagesLoaded
)
1523 Reference
< XPackageManager
> xUserManager
=
1524 thePackageManagerFactory::get( m_xContext
)->getPackageManager( rtl::OUString::createFromAscii("user") );
1525 m_aUserPackagesSeq
= xUserManager
->getDeployedPackages
1526 ( Reference
< task::XAbortChannel
>(), Reference
< ucb::XCommandEnvironment
>() );
1528 m_bUserPackagesLoaded
= true;
1531 if( m_iUserPackage
== m_aUserPackagesSeq
.getLength() )
1533 m_eState
= SHARED_EXTENSIONS
; // Later: SHARED_MODULE
1537 const Reference
< deployment::XPackage
>* pUserPackages
= m_aUserPackagesSeq
.getConstArray();
1538 Reference
< deployment::XPackage
> xPackage
= pUserPackages
[ m_iUserPackage
++ ];
1539 VOS_ENSURE( xPackage
.is(), "ExtensionIteratorBase::implGetNextUserHelpPackage(): Invalid package" );
1540 xHelpPackage
= implGetHelpPackageFromPackage( xPackage
, o_xParentPackageBundle
);
1543 return xHelpPackage
;
1546 Reference
< deployment::XPackage
> ExtensionIteratorBase::implGetNextSharedHelpPackage
1547 ( Reference
< deployment::XPackage
>& o_xParentPackageBundle
)
1549 Reference
< deployment::XPackage
> xHelpPackage
;
1551 if( !m_bSharedPackagesLoaded
)
1553 Reference
< XPackageManager
> xSharedManager
=
1554 thePackageManagerFactory::get( m_xContext
)->getPackageManager( rtl::OUString::createFromAscii("shared") );
1555 m_aSharedPackagesSeq
= xSharedManager
->getDeployedPackages
1556 ( Reference
< task::XAbortChannel
>(), Reference
< ucb::XCommandEnvironment
>() );
1558 m_bSharedPackagesLoaded
= true;
1561 if( m_iSharedPackage
== m_aSharedPackagesSeq
.getLength() )
1563 m_eState
= END_REACHED
;
1567 const Reference
< deployment::XPackage
>* pSharedPackages
= m_aSharedPackagesSeq
.getConstArray();
1568 Reference
< deployment::XPackage
> xPackage
= pSharedPackages
[ m_iSharedPackage
++ ];
1569 VOS_ENSURE( xPackage
.is(), "ExtensionIteratorBase::implGetNextSharedHelpPackage(): Invalid package" );
1570 xHelpPackage
= implGetHelpPackageFromPackage( xPackage
, o_xParentPackageBundle
);
1573 return xHelpPackage
;
1576 rtl::OUString
ExtensionIteratorBase::implGetFileFromPackage(
1577 const rtl::OUString
& rFileExtension
, Reference
< deployment::XPackage
> xPackage
)
1579 // No extension -> search for pure language folder
1580 bool bLangFolderOnly
= (rFileExtension
.getLength() == 0);
1582 rtl::OUString aFile
;
1583 rtl::OUString aLanguage
= m_aLanguage
;
1584 for( sal_Int32 iPass
= 0 ; iPass
< 2 ; ++iPass
)
1586 rtl::OUStringBuffer aStrBuf
;
1587 aStrBuf
.append( xPackage
->getURL() );
1588 aStrBuf
.append( aSlash
);
1589 aStrBuf
.append( aLanguage
);
1590 if( !bLangFolderOnly
)
1592 aStrBuf
.append( aSlash
);
1593 aStrBuf
.append( aHelpFilesBaseName
);
1594 aStrBuf
.append( rFileExtension
);
1597 aFile
= m_rDatabases
.expandURL( aStrBuf
.makeStringAndClear() );
1600 if( m_xSFA
->exists( aFile
) )
1603 ::std::vector
< ::rtl::OUString
> av
;
1604 implGetLanguageVectorFromPackage( av
, xPackage
);
1605 ::std::vector
< ::rtl::OUString
>::const_iterator pFound
= av
.end();
1608 pFound
= ::comphelper::Locale::getFallback( av
, m_aLanguage
);
1610 catch( ::comphelper::Locale::MalFormedLocaleException
& )
1612 if( pFound
!= av
.end() )
1613 aLanguage
= *pFound
;
1619 inline bool isLetter( sal_Unicode c
)
1621 bool bLetter
= ((c
>= 'A' && c
<= 'Z') || (c
>= 'a' && c
<= 'z'));
1625 void ExtensionIteratorBase::implGetLanguageVectorFromPackage( ::std::vector
< ::rtl::OUString
> &rv
,
1626 com::sun::star::uno::Reference
< com::sun::star::deployment::XPackage
> xPackage
)
1629 rtl::OUString aExtensionPath
= xPackage
->getURL();
1630 Sequence
< rtl::OUString
> aEntrySeq
= m_xSFA
->getFolderContents( aExtensionPath
, true );
1632 const rtl::OUString
* pSeq
= aEntrySeq
.getConstArray();
1633 sal_Int32 nCount
= aEntrySeq
.getLength();
1634 for( sal_Int32 i
= 0 ; i
< nCount
; ++i
)
1636 rtl::OUString aEntry
= pSeq
[i
];
1637 if( m_xSFA
->isFolder( aEntry
) )
1639 sal_Int32 nLastSlash
= aEntry
.lastIndexOf( '/' );
1640 if( nLastSlash
!= -1 )
1642 rtl::OUString aPureEntry
= aEntry
.copy( nLastSlash
+ 1 );
1644 // Check language sceme
1645 int nLen
= aPureEntry
.getLength();
1646 const sal_Unicode
* pc
= aPureEntry
.getStr();
1647 bool bStartCanBeLanguage
= ( nLen
>= 2 && isLetter( pc
[0] ) && isLetter( pc
[1] ) );
1648 bool bIsLanguage
= bStartCanBeLanguage
&&
1649 ( nLen
== 2 || (nLen
== 5 && pc
[2] == '-' && isLetter( pc
[3] ) && isLetter( pc
[4] )) );
1651 rv
.push_back( aPureEntry
);
1658 //===================================================================
1659 // class DataBaseIterator
1661 Db
* DataBaseIterator::nextDb( rtl::OUString
* o_pExtensionPath
)
1665 while( !pRetDb
&& m_eState
!= END_REACHED
)
1669 case INITIAL_MODULE
:
1670 pRetDb
= m_rDatabases
.getBerkeley( m_aInitialModule
, m_aLanguage
, m_bHelpText
);
1671 m_eState
= USER_EXTENSIONS
; // Later: SHARED_MODULE
1675 //case SHARED_MODULE
1678 case USER_EXTENSIONS
:
1680 Reference
< deployment::XPackage
> xParentPackageBundle
;
1681 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextUserHelpPackage( xParentPackageBundle
);
1682 if( !xHelpPackage
.is() )
1684 pRetDb
= implGetDbFromPackage( xHelpPackage
, o_pExtensionPath
);
1688 case SHARED_EXTENSIONS
:
1690 Reference
< deployment::XPackage
> xParentPackageBundle
;
1691 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextSharedHelpPackage( xParentPackageBundle
);
1692 if( !xHelpPackage
.is() )
1695 pRetDb
= implGetDbFromPackage( xHelpPackage
, o_pExtensionPath
);
1699 VOS_ENSURE( false, "DataBaseIterator::nextDb(): Invalid case END_REACHED" );
1707 Db
* DataBaseIterator::implGetDbFromPackage( Reference
< deployment::XPackage
> xPackage
,
1708 rtl::OUString
* o_pExtensionPath
)
1710 rtl::OUString aExtensionPath
= xPackage
->getURL();
1711 //if( o_pExtensionPath )
1712 //*o_pExtensionPath = aExtensionPath;
1713 aExtensionPath
+= aSlash
;
1715 rtl::OUString aUsedLanguage
= m_aLanguage
;
1716 Db
* pRetDb
= m_rDatabases
.getBerkeley( aHelpFilesBaseName
, aUsedLanguage
,
1717 m_bHelpText
, &aExtensionPath
);
1719 // Language fallback
1722 ::std::vector
< ::rtl::OUString
> av
;
1723 implGetLanguageVectorFromPackage( av
, xPackage
);
1724 ::std::vector
< ::rtl::OUString
>::const_iterator pFound
= av
.end();
1727 pFound
= ::comphelper::Locale::getFallback( av
, m_aLanguage
);
1729 catch( ::comphelper::Locale::MalFormedLocaleException
& )
1731 if( pFound
!= av
.end() )
1733 aUsedLanguage
= *pFound
;
1734 pRetDb
= m_rDatabases
.getBerkeley( aHelpFilesBaseName
, aUsedLanguage
, m_bHelpText
, &aExtensionPath
);
1738 if( o_pExtensionPath
)
1739 *o_pExtensionPath
= aExtensionPath
+ aUsedLanguage
;
1745 //===================================================================
1746 // class KeyDataBaseFileIterator
1748 rtl::OUString
KeyDataBaseFileIterator::nextDbFile( bool& o_rbExtension
)
1750 rtl::OUString aRetFile
;
1752 while( !aRetFile
.getLength() && m_eState
!= END_REACHED
)
1756 case INITIAL_MODULE
:
1758 m_rDatabases
.getInstallPathAsSystemPath() +
1759 m_rDatabases
.processLang( m_aLanguage
) + aSlash
+ m_aInitialModule
+
1760 rtl::OUString::createFromAscii( ".key" );
1762 o_rbExtension
= false;
1764 m_eState
= USER_EXTENSIONS
; // Later: SHARED_MODULE
1768 //case SHARED_MODULE
1771 case USER_EXTENSIONS
:
1773 Reference
< deployment::XPackage
> xParentPackageBundle
;
1774 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextUserHelpPackage( xParentPackageBundle
);
1775 if( !xHelpPackage
.is() )
1778 aRetFile
= implGetDbFileFromPackage( xHelpPackage
);
1779 o_rbExtension
= true;
1783 case SHARED_EXTENSIONS
:
1785 Reference
< deployment::XPackage
> xParentPackageBundle
;
1786 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextSharedHelpPackage( xParentPackageBundle
);
1787 if( !xHelpPackage
.is() )
1790 aRetFile
= implGetDbFileFromPackage( xHelpPackage
);
1791 o_rbExtension
= true;
1795 VOS_ENSURE( false, "DataBaseIterator::nextDbFile(): Invalid case END_REACHED" );
1803 rtl::OUString
KeyDataBaseFileIterator::implGetDbFileFromPackage
1804 ( Reference
< deployment::XPackage
> xPackage
)
1806 rtl::OUString aExpandedURL
=
1807 implGetFileFromPackage( rtl::OUString::createFromAscii( ".key" ), xPackage
);
1809 rtl::OUString aRetFile
;
1810 osl::FileBase::getSystemPathFromFileURL( aExpandedURL
, aRetFile
);
1816 //===================================================================
1817 // class JarFileIterator
1819 Reference
< XHierarchicalNameAccess
> JarFileIterator::nextJarFile
1820 ( Reference
< deployment::XPackage
>& o_xParentPackageBundle
, rtl::OUString
* o_pExtensionPath
)
1822 Reference
< XHierarchicalNameAccess
> xNA
;
1824 while( !xNA
.is() && m_eState
!= END_REACHED
)
1828 case INITIAL_MODULE
:
1829 xNA
= m_rDatabases
.jarFile( m_aInitialModule
, m_aLanguage
);
1830 m_eState
= USER_EXTENSIONS
; // Later: SHARED_MODULE
1834 //case SHARED_MODULE
1837 case USER_EXTENSIONS
:
1839 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextUserHelpPackage( o_xParentPackageBundle
);
1840 if( !xHelpPackage
.is() )
1843 xNA
= implGetJarFromPackage( xHelpPackage
, o_pExtensionPath
);
1847 case SHARED_EXTENSIONS
:
1849 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextSharedHelpPackage( o_xParentPackageBundle
);
1850 if( !xHelpPackage
.is() )
1853 xNA
= implGetJarFromPackage( xHelpPackage
, o_pExtensionPath
);
1857 VOS_ENSURE( false, "JarFileIterator::nextJarFile(): Invalid case END_REACHED" );
1865 Reference
< XHierarchicalNameAccess
> JarFileIterator::implGetJarFromPackage
1866 ( Reference
< deployment::XPackage
> xPackage
, rtl::OUString
* o_pExtensionPath
)
1868 Reference
< XHierarchicalNameAccess
> xNA
;
1870 rtl::OUString zipFile
=
1871 implGetFileFromPackage( rtl::OUString::createFromAscii( ".jar" ), xPackage
);
1875 Sequence
< Any
> aArguments( 1 );
1876 aArguments
[ 0 ] <<= zipFile
;
1878 Reference
< XMultiComponentFactory
>xSMgr( m_xContext
->getServiceManager(), UNO_QUERY
);
1879 Reference
< XInterface
> xIfc
1880 = xSMgr
->createInstanceWithArgumentsAndContext(
1881 rtl::OUString::createFromAscii(
1882 "com.sun.star.packages.comp.ZipPackage" ),
1883 aArguments
, m_xContext
);
1887 xNA
= Reference
< XHierarchicalNameAccess
>( xIfc
, UNO_QUERY
);
1889 VOS_ENSURE( xNA
.is(),
1890 "JarFileIterator::implGetJarFromPackage() - "
1891 "Got no hierarchical name access!" );
1894 catch ( RuntimeException
& )
1896 catch ( Exception
& )
1899 if( xNA
.is() && o_pExtensionPath
!= NULL
)
1901 // Extract path including language from file name
1902 sal_Int32 nLastSlash
= zipFile
.lastIndexOf( '/' );
1903 if( nLastSlash
!= -1 )
1904 *o_pExtensionPath
= zipFile
.copy( 0, nLastSlash
);
1911 //===================================================================
1912 // class IndexFolderIterator
1914 rtl::OUString
IndexFolderIterator::nextIndexFolder( bool& o_rbExtension
, bool& o_rbTemporary
)
1916 rtl::OUString aIndexFolder
;
1918 while( !aIndexFolder
.getLength() && m_eState
!= END_REACHED
)
1922 case INITIAL_MODULE
:
1924 m_rDatabases
.getInstallPathAsURL() +
1925 m_rDatabases
.processLang( m_aLanguage
) + aSlash
+ m_aInitialModule
+
1926 rtl::OUString::createFromAscii( ".idxl" );
1928 o_rbTemporary
= false;
1929 o_rbExtension
= false;
1931 m_eState
= USER_EXTENSIONS
; // Later: SHARED_MODULE
1935 //case SHARED_MODULE
1938 case USER_EXTENSIONS
:
1940 Reference
< deployment::XPackage
> xParentPackageBundle
;
1941 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextUserHelpPackage( xParentPackageBundle
);
1942 if( !xHelpPackage
.is() )
1945 aIndexFolder
= implGetIndexFolderFromPackage( o_rbTemporary
, xHelpPackage
);
1946 o_rbExtension
= true;
1950 case SHARED_EXTENSIONS
:
1952 Reference
< deployment::XPackage
> xParentPackageBundle
;
1953 Reference
< deployment::XPackage
> xHelpPackage
= implGetNextSharedHelpPackage( xParentPackageBundle
);
1954 if( !xHelpPackage
.is() )
1957 aIndexFolder
= implGetIndexFolderFromPackage( o_rbTemporary
, xHelpPackage
);
1958 o_rbExtension
= true;
1962 VOS_ENSURE( false, "IndexFolderIterator::nextIndexFolder(): Invalid case END_REACHED" );
1967 return aIndexFolder
;
1970 rtl::OUString
IndexFolderIterator::implGetIndexFolderFromPackage( bool& o_rbTemporary
, Reference
< deployment::XPackage
> xPackage
)
1972 rtl::OUString aIndexFolder
=
1973 implGetFileFromPackage( rtl::OUString::createFromAscii( ".idxl" ), xPackage
);
1975 o_rbTemporary
= false;
1976 if( !m_xSFA
->isFolder( aIndexFolder
) )
1978 // i98680: Missing index? Try to generate now
1979 rtl::OUString aLangURL
= implGetFileFromPackage( rtl::OUString(), xPackage
);
1980 if( m_xSFA
->isFolder( aLangURL
) )
1982 // Test write access (shared extension may be read only)
1983 bool bIsWriteAccess
= false;
1986 rtl::OUString aCreateTestFolder
= aLangURL
+ rtl::OUString::createFromAscii( "CreateTestFolder" );
1987 m_xSFA
->createFolder( aCreateTestFolder
);
1988 if( m_xSFA
->isFolder( aCreateTestFolder
) )
1989 bIsWriteAccess
= true;
1991 m_xSFA
->kill( aCreateTestFolder
);
1997 //bIsWriteAccess = false;
1999 Reference
< script::XInvocation
> xInvocation
;
2000 Reference
< XMultiComponentFactory
>xSMgr( m_xContext
->getServiceManager(), UNO_QUERY
);
2003 xInvocation
= Reference
< script::XInvocation
>(
2004 m_xContext
->getServiceManager()->createInstanceWithContext( rtl::OUString::createFromAscii(
2005 "com.sun.star.help.HelpIndexer" ), m_xContext
) , UNO_QUERY
);
2007 if( xInvocation
.is() )
2009 Sequence
<uno::Any
> aParamsSeq( bIsWriteAccess
? 6 : 8 );
2011 aParamsSeq
[0] = uno::makeAny( rtl::OUString::createFromAscii( "-lang" ) );
2013 rtl::OUString aLang
;
2014 sal_Int32 nLastSlash
= aLangURL
.lastIndexOf( '/' );
2015 if( nLastSlash
!= -1 )
2016 aLang
= aLangURL
.copy( nLastSlash
+ 1 );
2018 aLang
= rtl::OUString::createFromAscii( "en" );
2019 aParamsSeq
[1] = uno::makeAny( aLang
);
2021 aParamsSeq
[2] = uno::makeAny( rtl::OUString::createFromAscii( "-mod" ) );
2022 aParamsSeq
[3] = uno::makeAny( rtl::OUString::createFromAscii( "help" ) );
2024 rtl::OUString aZipDir
= aLangURL
;
2025 if( !bIsWriteAccess
)
2027 rtl::OUString aTempFileURL
;
2028 ::osl::FileBase::RC eErr
= ::osl::File::createTempFile( 0, 0, &aTempFileURL
);
2029 if( eErr
== ::osl::FileBase::E_None
)
2031 rtl::OUString aTempDirURL
= aTempFileURL
;
2034 m_xSFA
->kill( aTempDirURL
);
2038 m_xSFA
->createFolder( aTempDirURL
);
2040 aZipDir
= aTempDirURL
;
2041 o_rbTemporary
= true;
2045 aParamsSeq
[4] = uno::makeAny( rtl::OUString::createFromAscii( "-zipdir" ) );
2046 rtl::OUString aSystemPath
;
2047 osl::FileBase::getSystemPathFromFileURL( aZipDir
, aSystemPath
);
2048 aParamsSeq
[5] = uno::makeAny( aSystemPath
);
2050 if( !bIsWriteAccess
)
2052 aParamsSeq
[6] = uno::makeAny( rtl::OUString::createFromAscii( "-srcdir" ) );
2053 rtl::OUString aSrcDirVal
;
2054 osl::FileBase::getSystemPathFromFileURL( aLangURL
, aSrcDirVal
);
2055 aParamsSeq
[7] = uno::makeAny( aSrcDirVal
);
2058 Sequence
< sal_Int16
> aOutParamIndex
;
2059 Sequence
< uno::Any
> aOutParam
;
2060 uno::Any aRet
= xInvocation
->invoke( rtl::OUString::createFromAscii( "createIndex" ),
2061 aParamsSeq
, aOutParamIndex
, aOutParam
);
2063 if( bIsWriteAccess
)
2064 aIndexFolder
= implGetFileFromPackage( rtl::OUString::createFromAscii( ".idxl" ), xPackage
);
2066 aIndexFolder
= aZipDir
+ rtl::OUString::createFromAscii( "/help.idxl" );
2074 return aIndexFolder
;
2077 void IndexFolderIterator::deleteTempIndexFolder( const rtl::OUString
& aIndexFolder
)
2079 sal_Int32 nLastSlash
= aIndexFolder
.lastIndexOf( '/' );
2080 if( nLastSlash
!= -1 )
2082 rtl::OUString aTmpFolder
= aIndexFolder
.copy( 0, nLastSlash
);
2085 m_xSFA
->kill( aTmpFolder
);