merge the formfield patch from ooo-build
[ooovba.git] / xmlhelp / source / cxxhelp / provider / databases.cxx
bloba8d08b65f2a572b60a3652b79b7d15bb17c5e784
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: databases.cxx,v $
10 * $Revision: 1.54 $
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"
33 #include "db.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"
44 #include <algorithm>
45 #include <string.h>
47 // Extensible help
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 );
88 return aRetURL;
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;
96 if( !xContext.is() )
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 );
106 if( !xFac.is() )
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" ) ),
116 UNO_QUERY_THROW );
119 rtl::OUString aRetURL = aURL;
120 if( xMacroExpander.is() )
122 Reference< uri::XUriReference > uriRef;
123 for (;;)
125 uriRef = Reference< uri::XUriReference >( xFac->parse( aRetURL ), UNO_QUERY );
126 if ( uriRef.is() )
128 Reference < uri::XVndSunStarExpandUrl > sxUri( uriRef, UNO_QUERY );
129 if( !sxUri.is() )
130 break;
132 aRetURL = sxUri->expand( xMacroExpander );
136 return aRetURL;
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 ),
152 m_pErrorDoc( 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 ),
164 m_nSymbolsStyle( 0 )
166 m_xSMgr = Reference< XMultiComponentFactory >( m_xContext->getServiceManager(), UNO_QUERY );
168 m_vAdd[0] = 12;
169 m_vAdd[1] = 15;
170 m_vAdd[2] = 11;
171 m_vAdd[3] = 14;
172 m_vAdd[4] = 12;
173 m_vAdd[5] = 13;
174 m_vAdd[6] = 16;
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
204 // DatabasesTable
205 DatabasesTable::iterator it = m_aDatabases.begin();
206 while( it != m_aDatabases.end() )
208 if( it->second )
209 it->second->close( 0 );
210 delete it->second;
211 ++it;
216 // ModInfoTable
218 ModInfoTable::iterator it = m_aModInfo.begin();
219 while( it != m_aModInfo.end() )
221 delete it->second;
222 ++it;
227 // KeywordInfoTable
229 KeywordInfoTable::iterator it = m_aKeywordInfo.begin();
230 while( it != m_aKeywordInfo.end() )
232 delete it->second;
233 ++it;
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 );
260 // test existence
261 osl::DirectoryItem aDirItem;
262 if ( osl::DirectoryItem::get( rFileName, aDirItem ) == osl::FileBase::E_None )
263 return true;
266 return false;
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();
278 bool bFound = false;
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 );
289 if ( ! bFound )
290 bFound = impl_getZipFile( m_aImagesZipPaths, rtl::OUString::createFromAscii( "images.zip" ), aImageZip );
292 if ( ! bFound )
293 aImageZip = rtl::OUString();
295 m_aImagesZipFileURL = rtl::OUStringToOString(
296 rtl::Uri::encode(
297 aImageZip,
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;
310 bool cap = false;
311 rtl::OUStringBuffer aStrBuf( 0 );
313 while( true )
315 ++idx;
316 idx1 = oustring.indexOf( sal_Unicode('%'),idx);
317 idx2 = oustring.indexOf( sal_Unicode('$'),idx);
319 if(idx1 == -1 && idx2 == -1)
320 break;
322 if(idx1 == -1)
323 idx = idx2;
324 else if(idx2 == -1)
325 idx = idx1;
326 else {
327 // no index is zero
328 if(idx1 < idx2)
329 idx = idx1;
330 else if(idx2 < idx1 )
331 idx = idx2;
334 if( oustring.indexOf( prodName,idx ) == idx )
335 off = PRODUCTNAME;
336 else if( oustring.indexOf( prodVersion,idx ) == idx )
337 off = PRODUCTVERSION;
338 else if( oustring.indexOf( vendName,idx ) == idx )
339 off = VENDORNAME;
340 else if( oustring.indexOf( vendVersion,idx ) == idx )
341 off = VENDORVERSION;
342 else if( oustring.indexOf( vendShort,idx ) == idx )
343 off = VENDORSHORT;
344 else if( oustring.indexOf( newProdName,idx ) == idx )
345 off = NEWPRODUCTNAME;
346 else if( oustring.indexOf( newProdVersion,idx ) == idx )
347 off = NEWPRODUCTVERSION;
348 else
349 off = -1;
351 if( off != -1 )
353 if( ! cap )
355 cap = true;
356 aStrBuf.ensureCapacity( 256 );
359 aStrBuf.append( &oustring.getStr()[k],idx - k );
360 aStrBuf.append( m_vReplacement[off] );
361 k = idx + m_vAdd[off];
365 if( cap )
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() )
382 #ifdef DBG_UTIL
383 bool bla =
384 osl::FileBase::E_None ==
385 osl::FileBase::getSystemPathFromFileURL( m_aInstallDirectory,m_aInstallDirectoryAsSystemPath );
386 VOS_ENSURE( bla,"HelpProvider, no installpath" );
387 #else
388 osl::FileBase::getSystemPathFromFileURL( m_aInstallDirectory,m_aInstallDirectoryAsSystemPath );
389 #endif
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 );
416 sal_Int32 idx;
418 if( osl::FileBase::E_None != dirFile.open() )
419 return m_avModules;
421 while( dirFile.getNextItem( aDirItem ) == osl::FileBase::E_None &&
422 aDirItem.getFileStatus( aStatus ) == osl::FileBase::E_None )
424 if( ! aStatus.isValid( FileStatusMask_FileName ) )
425 continue;
427 fileName = aStatus.getFileName();
429 // Check, whether fileName is of the form *.cfg
430 idx = fileName.lastIndexOf( sal_Unicode( '.' ) );
432 if( idx == -1 )
433 continue;
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 )
443 continue;
444 m_avModules.push_back( fileName );
448 return m_avModules;
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() +
468 key +
469 rtl::OUString::createFromAscii( ".cfg" ) );
471 if( osl::FileBase::E_None != cfgFile.open( OpenFlag_Read ) )
472 it->second = 0;
473 else
475 sal_uInt32 pos = 0;
476 sal_uInt64 nRead;
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 );
484 cfgFile.close();
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' ) )
495 if( pos )
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 );
528 pos = 0;
530 else
531 lineBuffer[ pos++ ] = ch;
533 replaceName( title );
534 it->second = new StaticModuleInformation( title,
535 startid,
536 program,
537 heading,
538 fulltext,
539 order );
543 return it->second;
549 rtl::OUString Databases::processLang( const rtl::OUString& Language )
551 osl::MutexGuard aGuard( m_aMutex );
553 rtl::OUString ret;
554 LangSetTable::iterator it = m_aLangSet.find( Language );
556 if( it == m_aLangSet.end() )
558 sal_Int32 idx;
559 osl::DirectoryItem aDirItem;
561 if( osl::FileBase::E_None == osl::DirectoryItem::get( getInstallPathAsURL() + Language,aDirItem ) )
563 ret = Language;
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 ),
569 aDirItem ) )
571 ret = Language.copy( 0,idx );
572 m_aLangSet[ Language ] = ret;
575 else
576 ret = it->second;
578 return ret;
582 rtl::OUString Databases::country( const rtl::OUString& Language )
584 sal_Int32 idx;
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() )
599 return 0;
601 osl::MutexGuard aGuard( m_aMutex );
604 rtl::OUString aFileExt( rtl::OUString::createFromAscii( helpText ? ".ht" : ".db" ) );
605 rtl::OUString dbFileName = aSlash + Database + aFileExt;
606 rtl::OUString key;
607 if( pExtensionPath == NULL )
608 key = processLang( Language ) + dbFileName;
609 else
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;
622 if( pExtensionPath )
624 rtl::OUString aExpandedURL = expandURL( *pExtensionPath );
625 aExpandedURL += Language + dbFileName;
626 osl::FileBase::getSystemPathFromFileURL( aExpandedURL, fileNameOU );
628 else
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 );
642 #ifdef TEST_DBHELP
643 bool bSuccess;
644 bool bOldDbAccess = false;
645 bSuccess = pDBHelp->testAgainstDb( fileName, bOldDbAccess );
647 bOldDbAccess = true;
648 bSuccess = pDBHelp->testAgainstDb( fileName, bOldDbAccess );
649 #endif
651 else if( table->open( 0,fileName.getStr(),0,DB_BTREE,DB_RDONLY,0644 ) )
653 table->close( 0 );
654 delete table;
655 table = 0;
658 it->second = table;
661 return it->second;
664 Reference< XCollator >
665 Databases::getCollator( const rtl::OUString& Language,
666 const rtl::OUString& System )
668 (void)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() )
679 it->second =
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,
705 countryStr,
706 rtl::OUString() ),
707 0 );
710 return it->second;
715 namespace chelp {
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;
729 bool ret;
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 );
741 if( c1 == +1 )
742 ret = false;
743 else if( c1 == 0 )
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 );
749 else
750 ret = true;
752 else
753 ret = bool( l < r );
755 return ret;
758 Reference< XCollator > m_xCollator;
759 }; // end struct KeywordElementComparator
765 KeywordInfo::KeywordElement::KeywordElement( Databases *pDatabases,
766 Db* pDb,
767 rtl::OUString& ky,
768 rtl::OUString& data )
769 : key( ky )
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;
781 int idx = -1,k;
782 while( ( idx = ids.indexOf( ';',k = ++idx ) ) != -1 )
784 int h = ids.indexOf( sal_Unicode( '#' ),k );
785 if( h < idx )
787 // found an anchor
788 id.push_back( rtl::OUString( &idstr[k],h-k ) );
789 anchor.push_back( rtl::OUString( &idstr[h+1],idx-h-1 ) );
791 else
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() );
802 int nSize = 0;
803 const sal_Char* pData = NULL;
804 const sal_Char pEmpty[] = "";
806 for( sal_uInt32 i = 0; i < id.size(); ++i )
808 listId[i] = id[i];
809 listAnchor[i] = anchor[i];
811 nSize = 0;
812 pData = pEmpty;
813 if( pDb )
815 rtl::OString idi( id[i].getStr(),id[i].getLength(),RTL_TEXTENCODING_UTF8 );
816 DBHelp* pDBHelp = pDb->getDBHelp();
817 if( pDBHelp != NULL )
819 DBData aDBData;
820 bool bSuccess = pDBHelp->getValueForKey( idi, aDBData );
821 if( bSuccess )
823 nSize = aDBData.getSize();
824 pData = aDBData.getData();
827 else
829 Dbt key_( static_cast< void* >( const_cast< sal_Char* >( idi.getStr() ) ),
830 idi.getLength() );
831 Dbt data;
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 )
874 nLastFound = nLen;
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') )
884 break;
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 )
894 bModuleMatch = true;
895 break;
899 nLastFound = nFound;
900 if( nLastFound == 0 )
901 break;
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() );
937 Db table;
939 rtl::OUString fileNameDBHelp( fileNameOU );
940 if( bExtension )
941 fileNameDBHelp += rtl::OUString::createFromAscii( "_" );
942 if( m_xSFA->exists( fileNameDBHelp ) )
944 DBHelp aDBHelp( fileNameDBHelp, m_xSFA );
946 DBData aKey;
947 DBData aValue;
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;
968 if( bExtension )
969 bBelongsToDatabase = checkModuleMatchForExtension( Database, doclist );
971 if( !bBelongsToDatabase )
972 continue;
974 aVector.push_back( KeywordInfo::KeywordElement( this,
975 idmap,
976 keyword,
977 doclist ) );
979 aDBHelp.stopIteration();
981 if( pDBHelp != NULL )
982 pDBHelp->releaseHashMap();
985 #ifdef TEST_DBHELP
986 bool bSuccess;
987 bool bOldDbAccess = false;
988 bSuccess = aDBHelp.testAgainstDb( fileName, bOldDbAccess );
990 bOldDbAccess = true;
991 bSuccess = aDBHelp.testAgainstDb( fileName, bOldDbAccess );
993 int nDummy = 0;
994 #endif
997 else if( 0 == table.open( 0,fileName.getStr(),0,DB_BTREE,DB_RDONLY,0644 ) )
999 Db* idmap = getBerkeley( Database,Language );
1001 bool first = true;
1003 Dbc* cursor = 0;
1004 table.cursor( 0,&cursor,0 );
1005 Dbt key_,data;
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()),
1011 key_.get_size(),
1012 RTL_TEXTENCODING_UTF8 );
1013 rtl::OUString doclist( static_cast<sal_Char*>(data.get_data()),
1014 data.get_size(),
1015 RTL_TEXTENCODING_UTF8 );
1017 bool bBelongsToDatabase = true;
1018 if( bExtension )
1019 bBelongsToDatabase = checkModuleMatchForExtension( Database, doclist );
1021 if( !bBelongsToDatabase )
1022 continue;
1024 aVector.push_back( KeywordInfo::KeywordElement( this,
1025 idmap,
1026 keyword,
1027 doclist ) );
1028 if( first )
1030 key_.set_flags( DB_DBT_REALLOC );
1031 data.set_flags( DB_DBT_REALLOC );
1032 first = false;
1036 if( cursor ) cursor->close();
1038 table.close( 0 );
1041 // sorting
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 );
1047 (void)pInfo;
1050 return it->second;
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() );
1088 else
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;
1101 else
1103 delete p;
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 );
1119 if ( xIfc.is() )
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 & )
1137 return it->second;
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() )
1148 return xNA;
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
1176 bSuccess = false;
1179 else
1181 // No identifier -> ignore
1182 bSuccess = false;
1186 if( bSuccess )
1188 xNA = xTestNA;
1189 break;
1194 return xNA;
1197 void Databases::popupDocument( URLParameter* urlPar,char **buffer,int *byteCount )
1199 const char* pop1 =
1200 " <html> "
1201 " <head> "
1202 " <help:css-file-link xmlns:help=\"http://openoffice.org/2000/help\"/> "
1203 " </head> "
1204 " <body> "
1205 " <help:popup-cut Id=\"";
1206 const sal_Int32 l1 = strlen( pop1 );
1208 const char* pop3 = "\" Eid=\"";
1209 const sal_Int32 l3 = strlen( pop3 );
1211 const char* pop5 =
1212 "\" xmlns:help=\"http://openoffice.org/2000/help\"></help:popup-cut> "
1213 " </body> "
1214 " </html>";
1215 const sal_Int32 l5 = strlen( pop5 );
1216 sal_Int32 l2,l4;
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,
1248 char** buffer,
1249 int* byteCount )
1251 if( ! m_pCustomCSSDoc )
1253 int retry = 2;
1254 bool error = true;
1255 rtl::OUString fileURL;
1257 while( error && retry )
1259 if( retry == 2 )
1260 fileURL =
1261 getInstallPathAsURL() +
1262 processLang( Language ) +
1263 rtl::OUString::createFromAscii( "/" ) +
1264 m_aCSS +
1265 rtl::OUString::createFromAscii( ".css" );
1266 else if( retry == 1 )
1267 fileURL =
1268 getInstallPathAsURL() +
1269 m_aCSS +
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 ) )
1280 sal_uInt64 nSize;
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 );
1287 aFile.close();
1288 error = false;
1291 --retry;
1294 if( error )
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,
1312 char** buffer,
1313 int* byteCount )
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() );
1321 Dbt data;
1322 DBData aDBData;
1324 int nSize = 0;
1325 const sal_Char* pData = NULL;
1327 bool bSuccess = false;
1328 if( !bFoundAsEmpty )
1330 Db* db;
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();
1341 else
1343 int err = db->get( 0, &key, &data, 0 );
1344 if( err == 0 )
1346 bSuccess = true;
1347 nSize = data.get_size();
1348 pData = static_cast<sal_Char*>( data.get_data() );
1354 if( bSuccess )
1356 // ensure existence of tmp after for
1357 rtl::OString tmp;
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(),
1365 temp.getLength(),
1366 RTL_TEXTENCODING_UTF8 );
1367 nSize = tmp.getLength();
1368 pData = tmp.getStr();
1369 break;
1372 *byteCount = nSize;
1373 *buffer = new char[ 1 + nSize ];
1374 (*buffer)[nSize] = 0;
1375 rtl_copyMemory( *buffer, pData, nSize );
1377 else
1379 *byteCount = 0;
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 )
1416 init();
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 )
1426 init();
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() );
1436 if (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;
1457 m_iUserPackage = 0;
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 )
1486 bRegistered = true;
1488 if( bRegistered )
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;
1505 break;
1509 else
1511 const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xPackage->getPackageType();
1512 rtl::OUString aMediaType = xPackageTypeInfo->getMediaType();
1513 if( aMediaType.equals( aHelpMediaType ) )
1514 xHelpPackage = xPackage;
1518 if( !bFound )
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
1543 else
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;
1573 else
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() );
1606 if( iPass == 0 )
1608 if( m_xSFA->exists( aFile ) )
1609 break;
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;
1624 return aFile;
1627 inline bool isLetter( sal_Unicode c )
1629 bool bLetter = ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
1630 return bLetter;
1633 void ExtensionIteratorBase::implGetLanguageVectorFromPackage( ::std::vector< ::rtl::OUString > &rv,
1634 com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage )
1636 rv.clear();
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] )) );
1658 if( bIsLanguage )
1659 rv.push_back( aPureEntry );
1666 //===================================================================
1667 // class DataBaseIterator
1669 Db* DataBaseIterator::nextDb( rtl::OUString* o_pExtensionPath )
1671 Db* pRetDb = NULL;
1673 while( !pRetDb && m_eState != END_REACHED )
1675 switch( m_eState )
1677 case INITIAL_MODULE:
1678 pRetDb = m_rDatabases.getBerkeley( m_aInitialModule, m_aLanguage, m_bHelpText );
1679 m_eState = USER_EXTENSIONS; // Later: SHARED_MODULE
1680 break;
1682 // Later:
1683 //case SHARED_MODULE
1684 //...
1686 case USER_EXTENSIONS:
1688 Reference< deployment::XPackage > xParentPackageBundle;
1689 Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( xParentPackageBundle );
1690 if( !xHelpPackage.is() )
1691 break;
1692 pRetDb = implGetDbFromPackage( xHelpPackage, o_pExtensionPath );
1693 break;
1696 case SHARED_EXTENSIONS:
1698 Reference< deployment::XPackage > xParentPackageBundle;
1699 Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( xParentPackageBundle );
1700 if( !xHelpPackage.is() )
1701 break;
1703 pRetDb = implGetDbFromPackage( xHelpPackage, o_pExtensionPath );
1704 break;
1706 case END_REACHED:
1707 VOS_ENSURE( false, "DataBaseIterator::nextDb(): Invalid case END_REACHED" );
1708 break;
1712 return pRetDb;
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
1728 if( !pRetDb )
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;
1749 return pRetDb;
1753 //===================================================================
1754 // class KeyDataBaseFileIterator
1756 rtl::OUString KeyDataBaseFileIterator::nextDbFile( bool& o_rbExtension )
1758 rtl::OUString aRetFile;
1760 while( !aRetFile.getLength() && m_eState != END_REACHED )
1762 switch( m_eState )
1764 case INITIAL_MODULE:
1765 aRetFile =
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
1773 break;
1775 // Later:
1776 //case SHARED_MODULE
1777 //...
1779 case USER_EXTENSIONS:
1781 Reference< deployment::XPackage > xParentPackageBundle;
1782 Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( xParentPackageBundle );
1783 if( !xHelpPackage.is() )
1784 break;
1786 aRetFile = implGetDbFileFromPackage( xHelpPackage );
1787 o_rbExtension = true;
1788 break;
1791 case SHARED_EXTENSIONS:
1793 Reference< deployment::XPackage > xParentPackageBundle;
1794 Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( xParentPackageBundle );
1795 if( !xHelpPackage.is() )
1796 break;
1798 aRetFile = implGetDbFileFromPackage( xHelpPackage );
1799 o_rbExtension = true;
1800 break;
1802 case END_REACHED:
1803 VOS_ENSURE( false, "DataBaseIterator::nextDbFile(): Invalid case END_REACHED" );
1804 break;
1808 return aRetFile;
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 );
1820 return 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 )
1834 switch( m_eState )
1836 case INITIAL_MODULE:
1837 xNA = m_rDatabases.jarFile( m_aInitialModule, m_aLanguage );
1838 m_eState = USER_EXTENSIONS; // Later: SHARED_MODULE
1839 break;
1841 // Later:
1842 //case SHARED_MODULE
1843 //...
1845 case USER_EXTENSIONS:
1847 Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( o_xParentPackageBundle );
1848 if( !xHelpPackage.is() )
1849 break;
1851 xNA = implGetJarFromPackage( xHelpPackage, o_pExtensionPath );
1852 break;
1855 case SHARED_EXTENSIONS:
1857 Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( o_xParentPackageBundle );
1858 if( !xHelpPackage.is() )
1859 break;
1861 xNA = implGetJarFromPackage( xHelpPackage, o_pExtensionPath );
1862 break;
1864 case END_REACHED:
1865 VOS_ENSURE( false, "JarFileIterator::nextJarFile(): Invalid case END_REACHED" );
1866 break;
1870 return xNA;
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 );
1899 if ( xIfc.is() )
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 );
1921 return xNA;
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 )
1934 switch( m_eState )
1936 case INITIAL_MODULE:
1937 aIndexFolder =
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
1946 break;
1948 // Later:
1949 //case SHARED_MODULE
1950 //...
1952 case USER_EXTENSIONS:
1954 Reference< deployment::XPackage > xParentPackageBundle;
1955 Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( xParentPackageBundle );
1956 if( !xHelpPackage.is() )
1957 break;
1959 aIndexFolder = implGetIndexFolderFromPackage( o_rbTemporary, xHelpPackage );
1960 o_rbExtension = true;
1961 break;
1964 case SHARED_EXTENSIONS:
1966 Reference< deployment::XPackage > xParentPackageBundle;
1967 Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( xParentPackageBundle );
1968 if( !xHelpPackage.is() )
1969 break;
1971 aIndexFolder = implGetIndexFolderFromPackage( o_rbTemporary, xHelpPackage );
1972 o_rbExtension = true;
1973 break;
1975 case END_REACHED:
1976 VOS_ENSURE( false, "IndexFolderIterator::nextIndexFolder(): Invalid case END_REACHED" );
1977 break;
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 );
2007 catch (Exception &)
2010 // TEST
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 );
2031 else
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 );
2050 catch (Exception &)
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 );
2079 else
2080 aIndexFolder = aZipDir + rtl::OUString::createFromAscii( "/help.idxl" );
2083 catch (Exception &)
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 );
2101 catch (Exception &)