Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "db.hxx"
21 : #include <osl/diagnose.h>
22 : #include <osl/thread.h>
23 : #include <osl/process.h>
24 : #include <rtl/uri.hxx>
25 : #include <osl/file.hxx>
26 : #include <com/sun/star/lang/Locale.hpp>
27 : #include <com/sun/star/awt/Toolkit.hpp>
28 : #include <com/sun/star/i18n/Collator.hpp>
29 : #include <rtl/ustrbuf.hxx>
30 : #include "inputstream.hxx"
31 : #include <algorithm>
32 : #include <cassert>
33 : #include <string.h>
34 :
35 : #include <helpcompiler/HelpIndexer.hxx>
36 :
37 : // Extensible help
38 : #include <com/sun/star/deployment/ExtensionManager.hpp>
39 : #include <com/sun/star/deployment/thePackageManagerFactory.hpp>
40 : #include <comphelper/processfactory.hxx>
41 : #include <com/sun/star/uno/XComponentContext.hpp>
42 : #include <com/sun/star/ucb/XCommandEnvironment.hpp>
43 : #include <com/sun/star/beans/Optional.hpp>
44 : #include <com/sun/star/beans/PropertyValue.hpp>
45 : #include <com/sun/star/beans/NamedValue.hpp>
46 : #include <com/sun/star/configuration/theDefaultProvider.hpp>
47 : #include <com/sun/star/frame/XConfigManager.hpp>
48 : #include <com/sun/star/ucb/SimpleFileAccess.hpp>
49 : #include <com/sun/star/util/theMacroExpander.hpp>
50 : #include <com/sun/star/uri/UriReferenceFactory.hpp>
51 : #include <com/sun/star/uri/XVndSunStarExpandUrl.hpp>
52 : #include <com/sun/star/script/XInvocation.hpp>
53 : #include <i18nlangtag/languagetag.hxx>
54 :
55 : #include <com/sun/star/awt/XToolkit.hpp>
56 : #include <com/sun/star/awt/XExtendedToolkit.hpp>
57 : #include <com/sun/star/awt/XWindowPeer.hpp>
58 : #include <com/sun/star/awt/XVclWindowPeer.hpp>
59 : #include <com/sun/star/awt/XTopWindow.hpp>
60 :
61 : #include <comphelper/storagehelper.hxx>
62 : #include <comphelper/string.hxx>
63 :
64 : #include <vcl/svapp.hxx>
65 :
66 : #include "databases.hxx"
67 : #include "urlparameter.hxx"
68 :
69 : #ifdef WNT
70 : #include <windows.h>
71 : #endif
72 :
73 : using namespace chelp;
74 : using namespace com::sun::star;
75 : using namespace com::sun::star::uno;
76 : using namespace com::sun::star::io;
77 : using namespace com::sun::star::container;
78 : using namespace com::sun::star::i18n;
79 : using namespace com::sun::star::lang;
80 : using namespace com::sun::star::deployment;
81 : using namespace com::sun::star::beans;
82 :
83 0 : OUString Databases::expandURL( const OUString& aURL )
84 : {
85 0 : osl::MutexGuard aGuard( m_aMutex );
86 0 : OUString aRetURL = expandURL( aURL, m_xContext );
87 0 : return aRetURL;
88 : }
89 :
90 0 : OUString Databases::expandURL( const OUString& aURL, Reference< uno::XComponentContext > xContext )
91 : {
92 0 : static Reference< util::XMacroExpander > xMacroExpander;
93 0 : static Reference< uri::XUriReferenceFactory > xFac;
94 :
95 0 : if( !xMacroExpander.is() || !xFac.is() )
96 : {
97 0 : xFac = uri::UriReferenceFactory::create( xContext );
98 :
99 0 : xMacroExpander = util::theMacroExpander::get(xContext);
100 : }
101 :
102 0 : OUString aRetURL = aURL;
103 0 : if( xMacroExpander.is() )
104 : {
105 0 : Reference< uri::XUriReference > uriRef;
106 : for (;;)
107 : {
108 0 : uriRef = Reference< uri::XUriReference >( xFac->parse( aRetURL ), UNO_QUERY );
109 0 : if ( uriRef.is() )
110 : {
111 0 : Reference < uri::XVndSunStarExpandUrl > sxUri( uriRef, UNO_QUERY );
112 0 : if( !sxUri.is() )
113 0 : break;
114 :
115 0 : aRetURL = sxUri->expand( xMacroExpander );
116 : }
117 0 : }
118 : }
119 0 : return aRetURL;
120 : }
121 :
122 39 : Databases::Databases( bool showBasic,
123 : const OUString& instPath,
124 : const com::sun::star::uno::Sequence< OUString >& imagesZipPaths,
125 : const OUString& productName,
126 : const OUString& productVersion,
127 : const OUString& styleSheet,
128 : Reference< uno::XComponentContext > xContext )
129 : : m_xContext( xContext ),
130 : m_bShowBasic(showBasic),
131 : m_pErrorDoc( 0 ),
132 : m_nCustomCSSDocLength( 0 ),
133 : m_pCustomCSSDoc( 0 ),
134 : m_aCSS(styleSheet.toAsciiLowerCase()),
135 : newProdName( "$[officename]" ),
136 : newProdVersion( "$[officeversion]" ),
137 : prodName( "%PRODUCTNAME" ),
138 : prodVersion( "%PRODUCTVERSION" ),
139 : vendName( "%VENDORNAME" ),
140 : vendVersion( "%VENDORVERSION" ),
141 : vendShort( "%VENDORSHORT" ),
142 : m_aImagesZipPaths( imagesZipPaths ),
143 39 : m_aSymbolsStyleName( "" )
144 : {
145 39 : m_xSMgr = Reference< XMultiComponentFactory >( m_xContext->getServiceManager(), UNO_QUERY );
146 :
147 39 : m_vAdd[0] = 12;
148 39 : m_vAdd[1] = 15;
149 39 : m_vAdd[2] = 11;
150 39 : m_vAdd[3] = 14;
151 39 : m_vAdd[4] = 12;
152 39 : m_vAdd[5] = 13;
153 39 : m_vAdd[6] = 16;
154 :
155 39 : m_vReplacement[0] = productName;
156 39 : m_vReplacement[1] = productVersion;
157 : // m_vReplacement[2...4] (vendorName/-Version/-Short) are empty strings
158 39 : m_vReplacement[5] = productName;
159 39 : m_vReplacement[6] = productVersion;
160 :
161 39 : setInstallPath( instPath );
162 :
163 39 : m_xSFA = ucb::SimpleFileAccess::create(m_xContext);
164 39 : }
165 :
166 78 : Databases::~Databases()
167 : {
168 : // release stylesheet
169 :
170 39 : delete[] m_pCustomCSSDoc;
171 :
172 : // release errorDocument
173 :
174 39 : delete[] m_pErrorDoc;
175 :
176 : // unload the databases
177 :
178 : {
179 : // DatabasesTable
180 39 : DatabasesTable::iterator it = m_aDatabases.begin();
181 162 : while( it != m_aDatabases.end() )
182 : {
183 84 : delete it->second;
184 84 : ++it;
185 : }
186 : }
187 :
188 : {
189 : // ModInfoTable
190 :
191 39 : ModInfoTable::iterator it = m_aModInfo.begin();
192 81 : while( it != m_aModInfo.end() )
193 : {
194 3 : delete it->second;
195 3 : ++it;
196 : }
197 : }
198 :
199 : {
200 : // KeywordInfoTable
201 :
202 39 : KeywordInfoTable::iterator it = m_aKeywordInfo.begin();
203 78 : while( it != m_aKeywordInfo.end() )
204 : {
205 0 : delete it->second;
206 0 : ++it;
207 : }
208 : }
209 39 : }
210 :
211 0 : static bool impl_getZipFile(
212 : Sequence< OUString > & rImagesZipPaths,
213 : const OUString & rZipName,
214 : OUString & rFileName )
215 : {
216 0 : OUString aWorkingDir;
217 0 : osl_getProcessWorkingDir( &aWorkingDir.pData );
218 0 : const OUString *pPathArray = rImagesZipPaths.getArray();
219 0 : for ( int i = 0; i < rImagesZipPaths.getLength(); ++i )
220 : {
221 0 : OUString aFileName = pPathArray[ i ];
222 0 : if ( !aFileName.isEmpty() )
223 : {
224 0 : if ( !aFileName.endsWith("/") )
225 : {
226 0 : aFileName += "/";
227 : }
228 0 : aFileName += rZipName;
229 : // the icons are not read when the URL is a symlink
230 0 : osl::File::getAbsoluteFileURL( aWorkingDir, aFileName, rFileName );
231 :
232 : // test existence
233 0 : osl::DirectoryItem aDirItem;
234 0 : if ( osl::DirectoryItem::get( rFileName, aDirItem ) == osl::FileBase::E_None )
235 0 : return true;
236 : }
237 0 : }
238 0 : return false;
239 : }
240 :
241 0 : OString Databases::getImagesZipFileURL()
242 : {
243 0 : OUString aSymbolsStyleName;
244 : try
245 : {
246 : uno::Reference< lang::XMultiServiceFactory > xConfigProvider =
247 0 : configuration::theDefaultProvider::get(m_xContext);
248 :
249 : // set root path
250 0 : uno::Sequence < uno::Any > lParams(1);
251 0 : beans::PropertyValue aParam ;
252 0 : aParam.Name = "nodepath";
253 0 : aParam.Value <<= OUString("org.openoffice.Office.Common");
254 0 : lParams[0] = uno::makeAny(aParam);
255 :
256 : // open it
257 0 : uno::Reference< uno::XInterface > xCFG( xConfigProvider->createInstanceWithArguments(
258 : OUString("com.sun.star.configuration.ConfigurationAccess"),
259 0 : lParams) );
260 :
261 0 : bool bChanged = false;
262 0 : uno::Reference< container::XHierarchicalNameAccess > xAccess(xCFG, uno::UNO_QUERY_THROW);
263 0 : uno::Any aResult = xAccess->getByHierarchicalName(OUString("Misc/SymbolStyle"));
264 0 : if ( (aResult >>= aSymbolsStyleName) && m_aSymbolsStyleName != aSymbolsStyleName )
265 : {
266 0 : m_aSymbolsStyleName = aSymbolsStyleName;
267 0 : bChanged = true;
268 : }
269 :
270 0 : if ( m_aImagesZipFileURL.isEmpty() || bChanged )
271 : {
272 0 : OUString aImageZip;
273 0 : bool bFound = false;
274 :
275 0 : if ( !aSymbolsStyleName.isEmpty() )
276 : {
277 0 : if ( aSymbolsStyleName == "auto" )
278 : {
279 : // with the layered images*.zip, tango is the most
280 : // complete theme, so show that one
281 : // FIXME instead of using a general vnd.sun.star.zip://
282 : // for imgrepos, we should have some vnd.sun.star.image://
283 : // so that we don't have to re-open the stream for every
284 : // image in the help
285 0 : aSymbolsStyleName = "tango";
286 : }
287 0 : OUString aZipName = "images_" + aSymbolsStyleName + ".zip";
288 :
289 0 : bFound = impl_getZipFile( m_aImagesZipPaths, aZipName, aImageZip );
290 : }
291 :
292 0 : if ( ! bFound )
293 0 : bFound = impl_getZipFile( m_aImagesZipPaths, OUString( "images.zip" ), aImageZip );
294 :
295 0 : if ( ! bFound )
296 0 : aImageZip.clear();
297 :
298 0 : m_aImagesZipFileURL = OUStringToOString(
299 : rtl::Uri::encode(
300 : aImageZip,
301 : rtl_UriCharClassPchar,
302 : rtl_UriEncodeIgnoreEscapes,
303 0 : RTL_TEXTENCODING_UTF8 ), RTL_TEXTENCODING_UTF8 );
304 0 : }
305 : }
306 0 : catch ( NoSuchElementException const & )
307 : {
308 : }
309 :
310 0 : return m_aImagesZipFileURL;
311 : }
312 :
313 0 : void Databases::replaceName( OUString& oustring ) const
314 : {
315 0 : sal_Int32 idx = -1,idx1 = -1,idx2 = -1,k = 0,off;
316 0 : bool cap = false;
317 0 : OUStringBuffer aStrBuf( 0 );
318 :
319 : while( true )
320 : {
321 0 : ++idx;
322 0 : idx1 = oustring.indexOf( '%', idx);
323 0 : idx2 = oustring.indexOf( '$', idx);
324 :
325 0 : if(idx1 == -1 && idx2 == -1)
326 0 : break;
327 :
328 0 : if(idx1 == -1)
329 0 : idx = idx2;
330 0 : else if(idx2 == -1)
331 0 : idx = idx1;
332 : else {
333 : // no index is zero
334 0 : if(idx1 < idx2)
335 0 : idx = idx1;
336 0 : else if(idx2 < idx1 )
337 0 : idx = idx2;
338 : }
339 :
340 0 : if( oustring.indexOf( prodName,idx ) == idx )
341 0 : off = PRODUCTNAME;
342 0 : else if( oustring.indexOf( prodVersion,idx ) == idx )
343 0 : off = PRODUCTVERSION;
344 0 : else if( oustring.indexOf( vendName,idx ) == idx )
345 0 : off = VENDORNAME;
346 0 : else if( oustring.indexOf( vendVersion,idx ) == idx )
347 0 : off = VENDORVERSION;
348 0 : else if( oustring.indexOf( vendShort,idx ) == idx )
349 0 : off = VENDORSHORT;
350 0 : else if( oustring.indexOf( newProdName,idx ) == idx )
351 0 : off = NEWPRODUCTNAME;
352 0 : else if( oustring.indexOf( newProdVersion,idx ) == idx )
353 0 : off = NEWPRODUCTVERSION;
354 : else
355 0 : off = -1;
356 :
357 0 : if( off != -1 )
358 : {
359 0 : if( ! cap )
360 : {
361 0 : cap = true;
362 0 : aStrBuf.ensureCapacity( 256 );
363 : }
364 :
365 0 : aStrBuf.append( &oustring.getStr()[k],idx - k );
366 0 : aStrBuf.append( m_vReplacement[off] );
367 0 : k = idx + m_vAdd[off];
368 : }
369 : }
370 :
371 0 : if( cap )
372 : {
373 0 : if( k < oustring.getLength() )
374 0 : aStrBuf.append( &oustring.getStr()[k],oustring.getLength()-k );
375 0 : oustring = aStrBuf.makeStringAndClear();
376 0 : }
377 0 : }
378 :
379 3495 : OUString Databases::getInstallPathAsURL()
380 : {
381 3495 : osl::MutexGuard aGuard( m_aMutex );
382 :
383 3495 : return m_aInstallDirectory;
384 : }
385 :
386 38 : const std::vector< OUString >& Databases::getModuleList( const OUString& Language )
387 : {
388 38 : if( m_avModules.empty() )
389 : {
390 76 : OUString fileName,dirName = getInstallPathAsURL() + processLang( Language );
391 76 : osl::Directory dirFile( dirName );
392 :
393 76 : osl::DirectoryItem aDirItem;
394 76 : osl::FileStatus aStatus( osl_FileStatus_Mask_FileName );
395 :
396 : sal_Int32 idx;
397 :
398 38 : if( osl::FileBase::E_None != dirFile.open() )
399 0 : return m_avModules;
400 :
401 304 : while( dirFile.getNextItem( aDirItem ) == osl::FileBase::E_None &&
402 114 : aDirItem.getFileStatus( aStatus ) == osl::FileBase::E_None )
403 : {
404 114 : if( ! aStatus.isValid( osl_FileStatus_Mask_FileName ) )
405 0 : continue;
406 :
407 114 : fileName = aStatus.getFileName();
408 :
409 : // Check, whether fileName is of the form *.cfg
410 114 : idx = fileName.lastIndexOf( '.' );
411 :
412 114 : if( idx == -1 )
413 0 : continue;
414 :
415 114 : const sal_Unicode* str = fileName.getStr();
416 :
417 570 : if( fileName.getLength() == idx + 4 &&
418 228 : ( str[idx + 1] == 'c' || str[idx + 1] == 'C' ) &&
419 0 : ( str[idx + 2] == 'f' || str[idx + 2] == 'F' ) &&
420 228 : ( str[idx + 3] == 'g' || str[idx + 3] == 'G' ) &&
421 114 : ( fileName = fileName.copy(0,idx).toAsciiLowerCase() ) != "picture" ) {
422 0 : if(! m_bShowBasic && fileName == "sbasic" )
423 0 : continue;
424 0 : m_avModules.push_back( fileName );
425 : }
426 38 : }
427 : }
428 38 : return m_avModules;
429 : }
430 :
431 200 : StaticModuleInformation* Databases::getStaticInformationForModule( const OUString& Module,
432 : const OUString& Language )
433 : {
434 200 : osl::MutexGuard aGuard( m_aMutex );
435 :
436 400 : OUString key = processLang(Language) + "/" + Module;
437 :
438 : std::pair< ModInfoTable::iterator,bool > aPair =
439 200 : m_aModInfo.insert( ModInfoTable::value_type( key,nullptr ) );
440 :
441 200 : ModInfoTable::iterator it = aPair.first;
442 :
443 200 : if( aPair.second && ! it->second )
444 : {
445 3 : osl::File cfgFile( getInstallPathAsURL() + key + ".cfg" );
446 :
447 3 : if( osl::FileBase::E_None != cfgFile.open( osl_File_OpenFlag_Read ) )
448 3 : it->second = 0;
449 : else
450 : {
451 0 : sal_uInt32 pos = 0;
452 : sal_uInt64 nRead;
453 : sal_Char buffer[2048];
454 : sal_Unicode lineBuffer[1028];
455 0 : OUString fileContent;
456 :
457 0 : while( osl::FileBase::E_None == cfgFile.read( &buffer,2048,nRead ) && nRead )
458 0 : fileContent += OUString( buffer,sal_Int32( nRead ),RTL_TEXTENCODING_UTF8 );
459 :
460 0 : cfgFile.close();
461 :
462 0 : const sal_Unicode* str = fileContent.getStr();
463 0 : OUString current,lang_,program,startid,title,heading,fulltext;
464 0 : OUString order( "1" );
465 :
466 0 : for( sal_Int32 i = 0;i < fileContent.getLength();i++ )
467 : {
468 0 : sal_Unicode ch = str[ i ];
469 0 : if( ch == '\n' || ch == '\r' )
470 : {
471 0 : if( pos )
472 : {
473 0 : current = OUString( lineBuffer,pos );
474 :
475 0 : if( current.startsWith("Title") )
476 : {
477 0 : title = current.copy( current.indexOf( '=' ) + 1 );
478 : }
479 0 : else if( current.startsWith("Start") )
480 : {
481 0 : startid = current.copy( current.indexOf('=') + 1 );
482 : }
483 0 : else if( current.startsWith("Language") )
484 : {
485 0 : lang_ = current.copy( current.indexOf('=') + 1 );
486 : }
487 0 : else if( current.startsWith("Program") )
488 : {
489 0 : program = current.copy( current.indexOf('=') + 1 );
490 : }
491 0 : else if( current.startsWith("Heading") )
492 : {
493 0 : heading = current.copy( current.indexOf('=') + 1 );
494 : }
495 0 : else if( current.startsWith("FullText") )
496 : {
497 0 : fulltext = current.copy( current.indexOf('=') + 1 );
498 : }
499 0 : else if( current.startsWith("Order") )
500 : {
501 0 : order = current.copy( current.indexOf('=') + 1 );
502 : }
503 : }
504 0 : pos = 0;
505 : }
506 : else
507 0 : lineBuffer[ pos++ ] = ch;
508 : }
509 0 : replaceName( title );
510 0 : it->second = new StaticModuleInformation( title,
511 : startid,
512 : program,
513 : heading,
514 : fulltext,
515 0 : order );
516 3 : }
517 : }
518 :
519 400 : return it->second;
520 : }
521 :
522 1704 : OUString Databases::processLang( const OUString& Language )
523 : {
524 1704 : osl::MutexGuard aGuard( m_aMutex );
525 :
526 1704 : OUString ret;
527 1704 : LangSetTable::iterator it = m_aLangSet.find( Language );
528 :
529 1704 : if( it == m_aLangSet.end() )
530 : {
531 : sal_Int32 idx;
532 1704 : osl::DirectoryItem aDirItem;
533 :
534 1704 : if( osl::FileBase::E_None == osl::DirectoryItem::get( getInstallPathAsURL() + Language,aDirItem ) )
535 : {
536 0 : ret = Language;
537 0 : m_aLangSet[ Language ] = ret;
538 : }
539 3484 : else if( ( ( idx = Language.indexOf( '-' ) ) != -1 ||
540 5036 : ( idx = Language.indexOf( '_' ) ) != -1 ) &&
541 5036 : osl::FileBase::E_None == osl::DirectoryItem::get( getInstallPathAsURL() + Language.copy( 0,idx ),
542 5036 : aDirItem ) )
543 : {
544 0 : ret = Language.copy( 0,idx );
545 0 : m_aLangSet[ Language ] = ret;
546 1704 : }
547 : }
548 : else
549 0 : ret = it->second;
550 :
551 1704 : return ret;
552 : }
553 :
554 0 : OUString Databases::country( const OUString& Language )
555 : {
556 : sal_Int32 idx;
557 0 : if( ( idx = Language.indexOf( '-' ) ) != -1 ||
558 : ( idx = Language.indexOf( '_' ) ) != -1 )
559 0 : return Language.copy( 1+idx );
560 :
561 0 : return OUString();
562 : }
563 :
564 1466 : helpdatafileproxy::Hdf* Databases::getHelpDataFile( const OUString& Database,
565 : const OUString& Language, bool helpText,
566 : const OUString* pExtensionPath )
567 : {
568 1466 : if( Database.isEmpty() || Language.isEmpty() )
569 0 : return 0;
570 :
571 1466 : osl::MutexGuard aGuard( m_aMutex );
572 :
573 2932 : OUString aFileExt( helpText ? OUString(".ht") : OUString(".db") );
574 2932 : OUString dbFileName = "/" + Database + aFileExt;
575 2932 : OUString key;
576 1466 : if( pExtensionPath == NULL )
577 1466 : key = processLang( Language ) + dbFileName;
578 : else
579 0 : key = *pExtensionPath + Language + dbFileName; // make unique, don't change language
580 :
581 : std::pair< DatabasesTable::iterator,bool > aPair =
582 1466 : m_aDatabases.insert( DatabasesTable::value_type( key, reinterpret_cast<helpdatafileproxy::Hdf *>(0) ) );
583 :
584 1466 : DatabasesTable::iterator it = aPair.first;
585 :
586 1466 : if( aPair.second && ! it->second )
587 : {
588 84 : helpdatafileproxy::Hdf* pHdf = 0;
589 :
590 84 : OUString fileURL;
591 84 : if( pExtensionPath )
592 0 : fileURL = expandURL(*pExtensionPath) + Language + dbFileName;
593 : else
594 84 : fileURL = getInstallPathAsURL() + key;
595 :
596 168 : OUString fileNameHDFHelp( fileURL );
597 : //Extensions always use the new format
598 84 : if( pExtensionPath != NULL )
599 0 : fileNameHDFHelp += "_";
600 : //SimpleFileAccess takes file URLs as arguments!!! Using filenames works accidentally but
601 : //fails for example when using long path names on Windows (starting with \\?\)
602 84 : if( m_xSFA->exists( fileNameHDFHelp ) )
603 : {
604 0 : pHdf = new helpdatafileproxy::Hdf( fileNameHDFHelp, m_xSFA );
605 : }
606 :
607 168 : it->second = pHdf;
608 : }
609 :
610 2932 : return it->second;
611 : }
612 :
613 : Reference< XCollator >
614 0 : Databases::getCollator( const OUString& Language,
615 : const OUString& System )
616 : {
617 : (void)System;
618 :
619 0 : OUString key = Language;
620 :
621 0 : osl::MutexGuard aGuard( m_aMutex );
622 :
623 : CollatorTable::iterator it =
624 0 : m_aCollatorTable.insert( CollatorTable::value_type( key, Reference< XCollator >() ) ).first;
625 :
626 0 : if( ! it->second.is() )
627 : {
628 0 : it->second = Collator::create(m_xContext);
629 0 : OUString langStr = processLang(Language);
630 0 : OUString countryStr = country(Language);
631 0 : if( countryStr.isEmpty() )
632 : {
633 0 : if( langStr == "de" )
634 0 : countryStr = "DE";
635 0 : else if( langStr == "en" )
636 0 : countryStr = "US";
637 0 : else if( langStr == "es" )
638 0 : countryStr = "ES";
639 0 : else if( langStr == "it" )
640 0 : countryStr = "IT";
641 0 : else if( langStr == "fr" )
642 0 : countryStr = "FR";
643 0 : else if( langStr == "sv" )
644 0 : countryStr = "SE";
645 0 : else if( langStr == "ja" )
646 0 : countryStr = "JP";
647 0 : else if( langStr == "ko" )
648 0 : countryStr = "KR";
649 : }
650 : /* FIXME-BCP47: all this does not look right for language tag context,
651 : * also check processLang() and country() methods */
652 0 : it->second->loadDefaultCollator( Locale( langStr,
653 : countryStr,
654 : OUString() ),
655 0 : 0 );
656 : }
657 :
658 0 : return it->second;
659 : }
660 :
661 : namespace chelp {
662 :
663 0 : struct KeywordElementComparator
664 : {
665 0 : explicit KeywordElementComparator( const Reference< XCollator >& xCollator )
666 0 : : m_xCollator( xCollator )
667 0 : { }
668 :
669 0 : bool operator()( const KeywordInfo::KeywordElement& la,
670 : const KeywordInfo::KeywordElement& ra ) const
671 : {
672 0 : const OUString& l = la.key;
673 0 : const OUString& r = ra.key;
674 :
675 : bool ret;
676 :
677 0 : if( m_xCollator.is() )
678 : {
679 0 : sal_Int32 l1 = l.indexOf( ';' );
680 0 : sal_Int32 l3 = ( l1 == -1 ? l.getLength() : l1 );
681 :
682 0 : sal_Int32 r1 = r.indexOf( ';' );
683 0 : sal_Int32 r3 = ( r1 == -1 ? r.getLength() : r1 );
684 :
685 0 : sal_Int32 c1 = m_xCollator->compareSubstring( l,0,l3,r,0,r3 );
686 :
687 0 : if( c1 == +1 )
688 0 : ret = false;
689 0 : else if( c1 == 0 )
690 : {
691 0 : sal_Int32 l2 = l.getLength() - l1 - 1;
692 0 : sal_Int32 r2 = r.getLength() - r1 - 1;
693 0 : ret = ( m_xCollator->compareSubstring( l,1+l1,l2,r,1+r1,r2 ) < 0 );
694 : }
695 : else
696 0 : ret = true;
697 : }
698 : else
699 0 : ret = bool( l < r );
700 :
701 0 : return ret;
702 : }
703 :
704 : Reference< XCollator > m_xCollator;
705 : }; // end struct KeywordElementComparator
706 :
707 : }
708 :
709 0 : KeywordInfo::KeywordElement::KeywordElement( Databases *pDatabases,
710 : helpdatafileproxy::Hdf* pHdf,
711 : OUString& ky,
712 : OUString& data )
713 0 : : key( ky )
714 : {
715 0 : pDatabases->replaceName( key );
716 0 : init( pDatabases,pHdf,data );
717 0 : }
718 :
719 0 : void KeywordInfo::KeywordElement::init( Databases *pDatabases,helpdatafileproxy::Hdf* pHdf,const OUString& ids )
720 : {
721 0 : const sal_Unicode* idstr = ids.getStr();
722 0 : std::vector< OUString > id,anchor;
723 0 : int idx = -1,k;
724 0 : while( ( idx = ids.indexOf( ';',k = ++idx ) ) != -1 )
725 : {
726 0 : int h = ids.indexOf( '#', k );
727 0 : if( h < idx )
728 : {
729 : // found an anchor
730 0 : id.push_back( OUString( &idstr[k],h-k ) );
731 0 : anchor.push_back( OUString( &idstr[h+1],idx-h-1 ) );
732 : }
733 : else
734 : {
735 0 : id.push_back( OUString( &idstr[k],idx-k ) );
736 0 : anchor.push_back( OUString() );
737 : }
738 : }
739 :
740 0 : listId.realloc( id.size() );
741 0 : listAnchor.realloc( id.size() );
742 0 : listTitle.realloc( id.size() );
743 :
744 0 : for( size_t i = 0; i < id.size(); ++i )
745 : {
746 0 : listId[i] = id[i];
747 0 : listAnchor[i] = anchor[i];
748 :
749 0 : helpdatafileproxy::HDFData aHDFData;
750 0 : const sal_Char* pData = NULL;
751 :
752 0 : if( pHdf )
753 : {
754 0 : OString idi( id[i].getStr(),id[i].getLength(),RTL_TEXTENCODING_UTF8 );
755 0 : bool bSuccess = pHdf->getValueForKey( idi, aHDFData );
756 0 : if( bSuccess )
757 0 : pData = aHDFData.getData();
758 : }
759 :
760 0 : DbtToStringConverter converter( pData );
761 :
762 0 : OUString title = converter.getTitle();
763 0 : pDatabases->replaceName( title );
764 0 : listTitle[i] = title;
765 0 : }
766 0 : }
767 :
768 0 : KeywordInfo::KeywordInfo( const std::vector< KeywordElement >& aVec )
769 0 : : listKey( aVec.size() ),
770 0 : listId( aVec.size() ),
771 0 : listAnchor( aVec.size() ),
772 0 : listTitle( aVec.size() )
773 : {
774 0 : for( size_t i = 0; i < aVec.size(); ++i )
775 : {
776 0 : listKey[i] = aVec[i].key;
777 0 : listId[i] = aVec[i].listId;
778 0 : listAnchor[i] = aVec[i].listAnchor;
779 0 : listTitle[i] = aVec[i].listTitle;
780 : }
781 0 : }
782 :
783 0 : bool Databases::checkModuleMatchForExtension
784 : ( const OUString& Database, const OUString& doclist )
785 : {
786 0 : bool bBelongsToDatabase = true;
787 :
788 : // Analyse doclist string to find module assignments
789 0 : bool bFoundAtLeastOneModule = false;
790 0 : bool bModuleMatch = false;
791 0 : sal_Int32 nLen = doclist.getLength();
792 0 : sal_Int32 nLastFound = doclist.lastIndexOf( ';' );
793 0 : if( nLastFound == -1 )
794 0 : nLastFound = nLen;
795 0 : const sal_Unicode* pStr = doclist.getStr();
796 0 : sal_Int32 nFound = doclist.lastIndexOf( '_' );
797 0 : while( nFound != -1 )
798 : {
799 : // Simple optimization, stop if '_' is followed by "id"
800 0 : if( nLen - nFound > 2 )
801 : {
802 0 : if( pStr[ nFound + 1 ] == 'i' &&
803 0 : pStr[ nFound + 2 ] == 'd' )
804 0 : break;
805 : }
806 :
807 0 : OUString aModule = doclist.copy( nFound + 1, nLastFound - nFound - 1 );
808 0 : std::vector< OUString >::iterator result = std::find( m_avModules.begin(), m_avModules.end(), aModule );
809 0 : if( result != m_avModules.end() )
810 : {
811 0 : bFoundAtLeastOneModule = true;
812 0 : if( Database == aModule )
813 : {
814 0 : bModuleMatch = true;
815 0 : break;
816 : }
817 : }
818 :
819 0 : nLastFound = nFound;
820 0 : if( nLastFound == 0 )
821 0 : break;
822 0 : nFound = doclist.lastIndexOf( '_', nLastFound - 1 );
823 0 : }
824 :
825 0 : if( bFoundAtLeastOneModule && !bModuleMatch )
826 0 : bBelongsToDatabase = false;
827 :
828 0 : return bBelongsToDatabase;
829 : }
830 :
831 0 : KeywordInfo* Databases::getKeyword( const OUString& Database,
832 : const OUString& Language )
833 : {
834 0 : osl::MutexGuard aGuard( m_aMutex );
835 :
836 0 : OUString key = processLang(Language) + "/" + Database;
837 :
838 : std::pair< KeywordInfoTable::iterator,bool > aPair =
839 0 : m_aKeywordInfo.insert( KeywordInfoTable::value_type( key,nullptr ) );
840 :
841 0 : KeywordInfoTable::iterator it = aPair.first;
842 :
843 0 : if( aPair.second && ! it->second )
844 : {
845 0 : std::vector<KeywordInfo::KeywordElement> aVector;
846 :
847 0 : KeyDataBaseFileIterator aDbFileIt( m_xContext, *this, Database, Language );
848 0 : OUString fileURL;
849 0 : bool bExtension = false;
850 0 : while( !(fileURL = aDbFileIt.nextDbFile( bExtension )).isEmpty() )
851 : {
852 0 : OUString fileNameHDFHelp( fileURL );
853 0 : if( bExtension )
854 0 : fileNameHDFHelp += "_";
855 0 : if( m_xSFA->exists( fileNameHDFHelp ) )
856 : {
857 0 : helpdatafileproxy::Hdf aHdf( fileNameHDFHelp, m_xSFA );
858 0 : helpdatafileproxy::HDFData aKey;
859 0 : helpdatafileproxy::HDFData aValue;
860 0 : if( aHdf.startIteration() )
861 : {
862 0 : helpdatafileproxy::Hdf* pHdf = getHelpDataFile( Database,Language );
863 0 : if( pHdf != NULL )
864 : {
865 0 : bool bOptimizeForPerformance = true;
866 0 : pHdf->releaseHashMap();
867 0 : pHdf->createHashMap( bOptimizeForPerformance );
868 : }
869 :
870 0 : while( aHdf.getNextKeyAndValue( aKey, aValue ) )
871 : {
872 : OUString keyword( aKey.getData(), aKey.getSize(),
873 0 : RTL_TEXTENCODING_UTF8 );
874 : OUString doclist( aValue.getData(), aValue.getSize(),
875 0 : RTL_TEXTENCODING_UTF8 );
876 :
877 0 : bool bBelongsToDatabase = true;
878 0 : if( bExtension )
879 0 : bBelongsToDatabase = checkModuleMatchForExtension( Database, doclist );
880 :
881 0 : if( !bBelongsToDatabase )
882 0 : continue;
883 :
884 : aVector.push_back( KeywordInfo::KeywordElement( this,
885 : pHdf,
886 : keyword,
887 0 : doclist ) );
888 0 : }
889 0 : aHdf.stopIteration();
890 :
891 0 : if( pHdf != NULL )
892 0 : pHdf->releaseHashMap();
893 0 : }
894 : }
895 0 : }
896 :
897 : // sorting
898 0 : Reference< XCollator > xCollator = getCollator( Language,OUString());
899 0 : KeywordElementComparator aComparator( xCollator );
900 0 : std::sort(aVector.begin(),aVector.end(),aComparator);
901 :
902 0 : KeywordInfo* pInfo = it->second = new KeywordInfo( aVector );
903 0 : (void)pInfo;
904 : }
905 :
906 0 : return it->second;
907 : }
908 :
909 0 : Reference< XHierarchicalNameAccess > Databases::jarFile( const OUString& jar,
910 : const OUString& Language )
911 : {
912 0 : if( jar.isEmpty() || Language.isEmpty() )
913 : {
914 0 : return Reference< XHierarchicalNameAccess >( 0 );
915 : }
916 0 : OUString key = processLang(Language) + "/" + jar;
917 :
918 0 : osl::MutexGuard aGuard( m_aMutex );
919 :
920 : ZipFileTable::iterator it =
921 0 : m_aZipFileTable.insert( ZipFileTable::value_type( key,Reference< XHierarchicalNameAccess >(0) ) ).first;
922 :
923 0 : if( ! it->second.is() )
924 : {
925 0 : OUString zipFile;
926 : try
927 : {
928 : // Extension jar file? Search for ?
929 0 : sal_Int32 nQuestionMark1 = jar.indexOf( '?' );
930 0 : sal_Int32 nQuestionMark2 = jar.lastIndexOf( '?' );
931 0 : if( nQuestionMark1 != -1 && nQuestionMark2 != -1 && nQuestionMark1 != nQuestionMark2 )
932 : {
933 0 : OUString aExtensionPath = jar.copy( nQuestionMark1 + 1, nQuestionMark2 - nQuestionMark1 - 1 );
934 0 : OUString aPureJar = jar.copy( nQuestionMark2 + 1 );
935 :
936 0 : zipFile = expandURL( aExtensionPath + "/" + aPureJar );
937 : }
938 : else
939 : {
940 0 : zipFile = getInstallPathAsURL() + key;
941 : }
942 :
943 0 : Sequence< Any > aArguments( 2 );
944 :
945 0 : XInputStream_impl* p = new XInputStream_impl( zipFile );
946 0 : if( p->CtorSuccess() )
947 : {
948 0 : Reference< XInputStream > xInputStream( p );
949 0 : aArguments[ 0 ] <<= xInputStream;
950 : }
951 : else
952 : {
953 0 : delete p;
954 0 : aArguments[ 0 ] <<= zipFile;
955 : }
956 :
957 : // let ZipPackage be used ( no manifest.xml is required )
958 0 : beans::NamedValue aArg;
959 0 : aArg.Name = "StorageFormat";
960 0 : aArg.Value <<= OUString(ZIP_STORAGE_FORMAT_STRING);
961 0 : aArguments[ 1 ] <<= aArg;
962 :
963 : Reference< XInterface > xIfc
964 0 : = m_xSMgr->createInstanceWithArgumentsAndContext(
965 : OUString(
966 : "com.sun.star.packages.comp.ZipPackage" ),
967 0 : aArguments, m_xContext );
968 :
969 0 : if ( xIfc.is() )
970 : {
971 0 : it->second = Reference< XHierarchicalNameAccess >( xIfc, UNO_QUERY );
972 :
973 : OSL_ENSURE( it->second.is(),
974 : "ContentProvider::createPackage - "
975 : "Got no hierarchical name access!" );
976 :
977 0 : }
978 : }
979 0 : catch ( RuntimeException & )
980 : {
981 : }
982 0 : catch ( Exception & )
983 : {
984 0 : }
985 : }
986 :
987 0 : return it->second;
988 : }
989 :
990 0 : Reference< XHierarchicalNameAccess > Databases::findJarFileForPath
991 : ( const OUString& jar, const OUString& Language,
992 : const OUString& path, OUString* o_pExtensionPath,
993 : OUString* o_pExtensionRegistryPath )
994 : {
995 0 : Reference< XHierarchicalNameAccess > xNA;
996 0 : if( jar.isEmpty() || Language.isEmpty() )
997 : {
998 0 : return xNA;
999 : }
1000 :
1001 0 : JarFileIterator aJarFileIt( m_xContext, *this, jar, Language );
1002 0 : Reference< XHierarchicalNameAccess > xTestNA;
1003 0 : Reference< deployment::XPackage > xParentPackageBundle;
1004 0 : while( (xTestNA = aJarFileIt.nextJarFile( xParentPackageBundle, o_pExtensionPath, o_pExtensionRegistryPath )).is() )
1005 : {
1006 0 : if( xTestNA.is() && xTestNA->hasByHierarchicalName( path ) )
1007 : {
1008 0 : bool bSuccess = true;
1009 0 : if( xParentPackageBundle.is() )
1010 : {
1011 0 : OUString aIdentifierInPath;
1012 0 : sal_Int32 nFindSlash = path.indexOf( '/' );
1013 0 : if( nFindSlash != -1 )
1014 0 : aIdentifierInPath = path.copy( 0, nFindSlash );
1015 :
1016 0 : beans::Optional<OUString> aIdentifierOptional = xParentPackageBundle->getIdentifier();
1017 0 : if( !aIdentifierInPath.isEmpty() && aIdentifierOptional.IsPresent )
1018 : {
1019 0 : OUString aUnencodedIdentifier = aIdentifierOptional.Value;
1020 : OUString aIdentifier = rtl::Uri::encode( aUnencodedIdentifier,
1021 0 : rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8 );
1022 :
1023 0 : if( !aIdentifierInPath.equals( aIdentifier ) )
1024 : {
1025 : // path does not start with extension identifier -> ignore
1026 0 : bSuccess = false;
1027 0 : }
1028 : }
1029 : else
1030 : {
1031 : // No identifier -> ignore
1032 0 : bSuccess = false;
1033 0 : }
1034 : }
1035 :
1036 0 : if( bSuccess )
1037 : {
1038 0 : xNA = xTestNA;
1039 0 : break;
1040 : }
1041 : }
1042 : }
1043 :
1044 0 : return xNA;
1045 : }
1046 :
1047 0 : void Databases::changeCSS(const OUString& newStyleSheet)
1048 : {
1049 0 : m_aCSS = newStyleSheet.toAsciiLowerCase();
1050 0 : delete[] m_pCustomCSSDoc, m_pCustomCSSDoc = 0,m_nCustomCSSDocLength = 0;
1051 0 : }
1052 :
1053 0 : void Databases::cascadingStylesheet( const OUString& Language,
1054 : char** buffer,
1055 : int* byteCount )
1056 : {
1057 0 : if( ! m_pCustomCSSDoc )
1058 : {
1059 0 : int retry = 2;
1060 0 : bool error = true;
1061 0 : OUString fileURL;
1062 :
1063 0 : bool bHighContrastMode = false;
1064 0 : OUString aCSS( m_aCSS );
1065 0 : if ( aCSS == "default" )
1066 : {
1067 : // #i50760: "default" needs to adapt HC mode
1068 : uno::Reference< awt::XToolkit2 > xToolkit =
1069 0 : awt::Toolkit::create( ::comphelper::getProcessComponentContext() );
1070 0 : uno::Reference< awt::XTopWindow > xTopWindow = xToolkit->getActiveTopWindow();
1071 0 : if ( xTopWindow.is() )
1072 : {
1073 0 : uno::Reference< awt::XVclWindowPeer > xVclWindowPeer( xTopWindow, uno::UNO_QUERY );
1074 0 : if ( xVclWindowPeer.is() )
1075 : {
1076 0 : uno::Any aHCMode = xVclWindowPeer->getProperty( OUString( "HighContrastMode" ) );
1077 0 : if ( ( aHCMode >>= bHighContrastMode ) && bHighContrastMode )
1078 : {
1079 0 : aCSS = "highcontrastblack";
1080 : #ifdef WNT
1081 : HKEY hKey = NULL;
1082 : LONG lResult = RegOpenKeyExA( HKEY_CURRENT_USER, "Control Panel\\Accessibility\\HighContrast", 0, KEY_QUERY_VALUE, &hKey );
1083 : if ( ERROR_SUCCESS == lResult )
1084 : {
1085 : CHAR szBuffer[1024];
1086 : DWORD nSize = sizeof( szBuffer );
1087 : lResult = RegQueryValueExA( hKey, "High Contrast Scheme", NULL, NULL, (LPBYTE)szBuffer, &nSize );
1088 : if ( ERROR_SUCCESS == lResult && nSize > 0 )
1089 : {
1090 : szBuffer[nSize] = '\0';
1091 : if ( strncmp( szBuffer, "High Contrast #1", strlen("High Contrast #1") ) == 0 )
1092 : aCSS = "highcontrast1";
1093 : if ( strncmp( szBuffer, "High Contrast #2", strlen("High Contrast #2") ) == 0 )
1094 : aCSS = "highcontrast2";
1095 : if ( strncmp( szBuffer, "High Contrast White", strlen("High Contrast White") ) == 0 )
1096 : aCSS = "highcontrastwhite";
1097 : }
1098 : RegCloseKey( hKey );
1099 : }
1100 : #endif
1101 0 : }
1102 0 : }
1103 0 : }
1104 : }
1105 :
1106 0 : while( error && retry )
1107 : {
1108 :
1109 0 : if( retry == 2 )
1110 0 : fileURL =
1111 0 : getInstallPathAsURL() +
1112 0 : processLang( Language ) +
1113 0 : "/" +
1114 0 : aCSS +
1115 0 : ".css";
1116 0 : else if( retry == 1 )
1117 0 : fileURL =
1118 0 : getInstallPathAsURL() +
1119 0 : aCSS +
1120 0 : ".css";
1121 :
1122 0 : osl::DirectoryItem aDirItem;
1123 0 : osl::File aFile( fileURL );
1124 0 : osl::FileStatus aStatus( osl_FileStatus_Mask_FileSize );
1125 :
1126 0 : if( osl::FileBase::E_None == osl::DirectoryItem::get( fileURL,aDirItem ) &&
1127 0 : osl::FileBase::E_None == aFile.open( osl_File_OpenFlag_Read ) &&
1128 0 : osl::FileBase::E_None == aDirItem.getFileStatus( aStatus ) )
1129 : {
1130 : sal_uInt64 nSize;
1131 0 : aFile.getSize( nSize );
1132 0 : m_nCustomCSSDocLength = (int)nSize;
1133 0 : m_pCustomCSSDoc = new char[ 1 + m_nCustomCSSDocLength ];
1134 0 : m_pCustomCSSDoc[ m_nCustomCSSDocLength ] = 0;
1135 0 : sal_uInt64 a = m_nCustomCSSDocLength,b = m_nCustomCSSDocLength;
1136 0 : aFile.read( m_pCustomCSSDoc,a,b );
1137 0 : aFile.close();
1138 0 : error = false;
1139 : }
1140 :
1141 0 : --retry;
1142 0 : if ( !retry && error && bHighContrastMode )
1143 : {
1144 : // fall back to default css
1145 0 : aCSS = "default";
1146 0 : retry = 2;
1147 0 : bHighContrastMode = false;
1148 : }
1149 0 : }
1150 :
1151 0 : if( error )
1152 : {
1153 0 : m_nCustomCSSDocLength = 0;
1154 0 : m_pCustomCSSDoc = new char[ 1 ]; // Initialize with 1 to avoid gcc compiler warning
1155 0 : }
1156 : }
1157 :
1158 0 : *byteCount = m_nCustomCSSDocLength;
1159 0 : *buffer = new char[ 1 + *byteCount ];
1160 0 : (*buffer)[*byteCount] = 0;
1161 0 : memcpy( *buffer,m_pCustomCSSDoc,m_nCustomCSSDocLength );
1162 :
1163 0 : }
1164 :
1165 1550 : void Databases::setActiveText( const OUString& Module,
1166 : const OUString& Language,
1167 : const OUString& Id,
1168 : char** buffer,
1169 : int* byteCount )
1170 : {
1171 1550 : DataBaseIterator aDbIt( m_xContext, *this, Module, Language, true );
1172 :
1173 : // #i84550 Cache information about failed ids
1174 3100 : OString id( Id.getStr(),Id.getLength(),RTL_TEXTENCODING_UTF8 );
1175 1550 : EmptyActiveTextSet::iterator it = m_aEmptyActiveTextSet.find( id );
1176 1550 : bool bFoundAsEmpty = ( it != m_aEmptyActiveTextSet.end() );
1177 3100 : helpdatafileproxy::HDFData aHDFData;
1178 :
1179 1550 : int nSize = 0;
1180 1550 : const sal_Char* pData = NULL;
1181 :
1182 1550 : bool bSuccess = false;
1183 1550 : if( !bFoundAsEmpty )
1184 : {
1185 116 : helpdatafileproxy::Hdf* pHdf = 0;
1186 232 : while( !bSuccess && (pHdf = aDbIt.nextHdf()) != NULL )
1187 : {
1188 0 : bSuccess = pHdf->getValueForKey( id, aHDFData );
1189 0 : nSize = aHDFData.getSize();
1190 0 : pData = aHDFData.getData();
1191 : }
1192 : }
1193 :
1194 1550 : if( bSuccess )
1195 : {
1196 : // ensure existence of tmp after for
1197 0 : OString tmp;
1198 0 : for( int i = 0; i < nSize; ++i )
1199 0 : if( pData[i] == '%' || pData[i] == '$' )
1200 : {
1201 : // need of replacement
1202 0 : OUString temp = OUString( pData, nSize, RTL_TEXTENCODING_UTF8 );
1203 0 : replaceName( temp );
1204 0 : tmp = OString( temp.getStr(),
1205 : temp.getLength(),
1206 0 : RTL_TEXTENCODING_UTF8 );
1207 0 : nSize = tmp.getLength();
1208 0 : pData = tmp.getStr();
1209 0 : break;
1210 : }
1211 :
1212 0 : *byteCount = nSize;
1213 0 : *buffer = new char[ 1 + nSize ];
1214 0 : (*buffer)[nSize] = 0;
1215 0 : memcpy( *buffer, pData, nSize );
1216 : }
1217 : else
1218 : {
1219 1550 : *byteCount = 0;
1220 1550 : *buffer = new char[1]; // Initialize with 1 to avoid compiler warnings
1221 1550 : if( !bFoundAsEmpty )
1222 116 : m_aEmptyActiveTextSet.insert( id );
1223 1550 : }
1224 1550 : }
1225 :
1226 39 : void Databases::setInstallPath( const OUString& aInstDir )
1227 : {
1228 39 : osl::MutexGuard aGuard( m_aMutex );
1229 :
1230 39 : osl::FileBase::getFileURLFromSystemPath( aInstDir,m_aInstallDirectory );
1231 : //TODO: check returned error code
1232 :
1233 39 : if( !m_aInstallDirectory.endsWith( "/" ) )
1234 39 : m_aInstallDirectory += "/";
1235 39 : }
1236 :
1237 : // class ExtensionIteratorBase
1238 :
1239 40 : ExtensionHelpExistanceMap ExtensionIteratorBase::aHelpExistanceMap;
1240 :
1241 1550 : ExtensionIteratorBase::ExtensionIteratorBase( Reference< XComponentContext > xContext,
1242 : Databases& rDatabases, const OUString& aInitialModule, const OUString& aLanguage )
1243 : : m_xContext( xContext )
1244 : , m_rDatabases( rDatabases )
1245 : , m_eState( INITIAL_MODULE )
1246 : , m_aInitialModule( aInitialModule )
1247 1550 : , m_aLanguage( aLanguage )
1248 : {
1249 : assert( m_xContext.is() );
1250 1550 : init();
1251 1550 : }
1252 :
1253 1350 : ExtensionIteratorBase::ExtensionIteratorBase( Databases& rDatabases,
1254 : const OUString& aInitialModule, const OUString& aLanguage )
1255 : : m_xContext( comphelper::getProcessComponentContext() )
1256 : , m_rDatabases( rDatabases )
1257 : , m_eState( INITIAL_MODULE )
1258 : , m_aInitialModule( aInitialModule )
1259 1350 : , m_aLanguage( aLanguage )
1260 : {
1261 1350 : init();
1262 1350 : }
1263 :
1264 2900 : void ExtensionIteratorBase::init()
1265 : {
1266 2900 : m_xSFA = ucb::SimpleFileAccess::create(m_xContext);
1267 :
1268 2900 : m_bUserPackagesLoaded = false;
1269 2900 : m_bSharedPackagesLoaded = false;
1270 2900 : m_bBundledPackagesLoaded = false;
1271 2900 : m_iUserPackage = 0;
1272 2900 : m_iSharedPackage = 0;
1273 2900 : m_iBundledPackage = 0;
1274 2900 : }
1275 :
1276 0 : Reference< deployment::XPackage > ExtensionIteratorBase::implGetHelpPackageFromPackage
1277 : ( Reference< deployment::XPackage > xPackage, Reference< deployment::XPackage >& o_xParentPackageBundle )
1278 : {
1279 0 : o_xParentPackageBundle.clear();
1280 :
1281 0 : Reference< deployment::XPackage > xHelpPackage;
1282 0 : if( !xPackage.is() )
1283 0 : return xHelpPackage;
1284 :
1285 : // #i84550 Cache information about help content in extension
1286 0 : OUString aExtensionPath = xPackage->getURL();
1287 0 : ExtensionHelpExistanceMap::iterator it = aHelpExistanceMap.find( aExtensionPath );
1288 0 : bool bFound = ( it != aHelpExistanceMap.end() );
1289 0 : bool bHasHelp = bFound && it->second;
1290 0 : if( bFound && !bHasHelp )
1291 0 : return xHelpPackage;
1292 :
1293 : // Check if parent package is registered
1294 0 : beans::Optional< beans::Ambiguous<sal_Bool> > option( xPackage->isRegistered
1295 0 : ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ) );
1296 0 : bool bRegistered = false;
1297 0 : if( option.IsPresent )
1298 : {
1299 0 : beans::Ambiguous<sal_Bool> const & reg = option.Value;
1300 0 : if( !reg.IsAmbiguous && reg.Value )
1301 0 : bRegistered = true;
1302 : }
1303 0 : if( bRegistered )
1304 : {
1305 0 : OUString aHelpMediaType( "application/vnd.sun.star.help" );
1306 0 : if( xPackage->isBundle() )
1307 : {
1308 0 : Sequence< Reference< deployment::XPackage > > aPkgSeq = xPackage->getBundle
1309 0 : ( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() );
1310 0 : sal_Int32 nPkgCount = aPkgSeq.getLength();
1311 0 : const Reference< deployment::XPackage >* pSeq = aPkgSeq.getConstArray();
1312 0 : for( sal_Int32 iPkg = 0 ; iPkg < nPkgCount ; ++iPkg )
1313 : {
1314 0 : const Reference< deployment::XPackage > xSubPkg = pSeq[ iPkg ];
1315 0 : const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xSubPkg->getPackageType();
1316 0 : OUString aMediaType = xPackageTypeInfo->getMediaType();
1317 0 : if( aMediaType.equals( aHelpMediaType ) )
1318 : {
1319 0 : xHelpPackage = xSubPkg;
1320 0 : o_xParentPackageBundle = xPackage;
1321 0 : break;
1322 : }
1323 0 : }
1324 : }
1325 : else
1326 : {
1327 0 : const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xPackage->getPackageType();
1328 0 : OUString aMediaType = xPackageTypeInfo->getMediaType();
1329 0 : if( aMediaType.equals( aHelpMediaType ) )
1330 0 : xHelpPackage = xPackage;
1331 0 : }
1332 : }
1333 :
1334 0 : if( !bFound )
1335 0 : aHelpExistanceMap[ aExtensionPath ] = xHelpPackage.is();
1336 :
1337 0 : return xHelpPackage;
1338 : }
1339 :
1340 1466 : Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextUserHelpPackage
1341 : ( Reference< deployment::XPackage >& o_xParentPackageBundle )
1342 : {
1343 1466 : Reference< deployment::XPackage > xHelpPackage;
1344 :
1345 1466 : if( !m_bUserPackagesLoaded )
1346 : {
1347 1466 : Reference< XExtensionManager > xExtensionManager = ExtensionManager::get(m_xContext);
1348 4398 : m_aUserPackagesSeq = xExtensionManager->getDeployedExtensions
1349 2932 : ( OUString("user"), Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() );
1350 1466 : m_bUserPackagesLoaded = true;
1351 : }
1352 :
1353 1466 : if( m_iUserPackage == m_aUserPackagesSeq.getLength() )
1354 : {
1355 1466 : m_eState = SHARED_EXTENSIONS; // Later: SHARED_MODULE
1356 : }
1357 : else
1358 : {
1359 0 : const Reference< deployment::XPackage >* pUserPackages = m_aUserPackagesSeq.getConstArray();
1360 0 : Reference< deployment::XPackage > xPackage = pUserPackages[ m_iUserPackage++ ];
1361 : OSL_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextUserHelpPackage(): Invalid package" );
1362 0 : xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle );
1363 : }
1364 :
1365 1466 : return xHelpPackage;
1366 : }
1367 :
1368 1466 : Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextSharedHelpPackage
1369 : ( Reference< deployment::XPackage >& o_xParentPackageBundle )
1370 : {
1371 1466 : Reference< deployment::XPackage > xHelpPackage;
1372 :
1373 1466 : if( !m_bSharedPackagesLoaded )
1374 : {
1375 1466 : Reference< XExtensionManager > xExtensionManager = ExtensionManager::get(m_xContext);
1376 4398 : m_aSharedPackagesSeq = xExtensionManager->getDeployedExtensions
1377 2932 : ( OUString("shared"), Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() );
1378 1466 : m_bSharedPackagesLoaded = true;
1379 : }
1380 :
1381 1466 : if( m_iSharedPackage == m_aSharedPackagesSeq.getLength() )
1382 : {
1383 1466 : m_eState = BUNDLED_EXTENSIONS;
1384 : }
1385 : else
1386 : {
1387 0 : const Reference< deployment::XPackage >* pSharedPackages = m_aSharedPackagesSeq.getConstArray();
1388 0 : Reference< deployment::XPackage > xPackage = pSharedPackages[ m_iSharedPackage++ ];
1389 : OSL_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextSharedHelpPackage(): Invalid package" );
1390 0 : xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle );
1391 : }
1392 :
1393 1466 : return xHelpPackage;
1394 : }
1395 :
1396 1466 : Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextBundledHelpPackage
1397 : ( Reference< deployment::XPackage >& o_xParentPackageBundle )
1398 : {
1399 1466 : Reference< deployment::XPackage > xHelpPackage;
1400 :
1401 1466 : if( !m_bBundledPackagesLoaded )
1402 : {
1403 1466 : Reference< XExtensionManager > xExtensionManager = ExtensionManager::get(m_xContext);
1404 4398 : m_aBundledPackagesSeq = xExtensionManager->getDeployedExtensions
1405 2932 : ( OUString("bundled"), Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() );
1406 1466 : m_bBundledPackagesLoaded = true;
1407 : }
1408 :
1409 1466 : if( m_iBundledPackage == m_aBundledPackagesSeq.getLength() )
1410 : {
1411 1466 : m_eState = END_REACHED;
1412 : }
1413 : else
1414 : {
1415 : const Reference< deployment::XPackage >* pBundledPackages =
1416 0 : m_aBundledPackagesSeq.getConstArray();
1417 0 : Reference< deployment::XPackage > xPackage = pBundledPackages[ m_iBundledPackage++ ];
1418 : OSL_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextBundledHelpPackage(): Invalid package" );
1419 0 : xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle );
1420 : }
1421 :
1422 1466 : return xHelpPackage;
1423 : }
1424 :
1425 0 : OUString ExtensionIteratorBase::implGetFileFromPackage(
1426 : const OUString& rFileExtension, Reference< deployment::XPackage > xPackage )
1427 : {
1428 : // No extension -> search for pure language folder
1429 0 : bool bLangFolderOnly = rFileExtension.isEmpty();
1430 :
1431 0 : OUString aFile;
1432 0 : OUString aLanguage = m_aLanguage;
1433 0 : for( sal_Int32 iPass = 0 ; iPass < 2 ; ++iPass )
1434 : {
1435 0 : OUString aStr = xPackage->getRegistrationDataURL().Value + "/" + aLanguage;
1436 0 : if( !bLangFolderOnly )
1437 : {
1438 0 : aStr += "/help" + rFileExtension;
1439 : }
1440 :
1441 0 : aFile = m_rDatabases.expandURL( aStr );
1442 0 : if( iPass == 0 )
1443 : {
1444 0 : if( m_xSFA->exists( aFile ) )
1445 0 : break;
1446 :
1447 0 : ::std::vector< OUString > av;
1448 0 : implGetLanguageVectorFromPackage( av, xPackage );
1449 0 : ::std::vector< OUString >::const_iterator pFound = LanguageTag::getFallback( av, m_aLanguage );
1450 0 : if( pFound != av.end() )
1451 0 : aLanguage = *pFound;
1452 : }
1453 0 : }
1454 0 : return aFile;
1455 : }
1456 :
1457 0 : inline bool isLetter( sal_Unicode c )
1458 : {
1459 0 : return comphelper::string::isalphaAscii(c);
1460 : }
1461 :
1462 0 : void ExtensionIteratorBase::implGetLanguageVectorFromPackage( ::std::vector< OUString > &rv,
1463 : com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage )
1464 : {
1465 0 : rv.clear();
1466 0 : OUString aExtensionPath = xPackage->getURL();
1467 0 : Sequence< OUString > aEntrySeq = m_xSFA->getFolderContents( aExtensionPath, true );
1468 :
1469 0 : const OUString* pSeq = aEntrySeq.getConstArray();
1470 0 : sal_Int32 nCount = aEntrySeq.getLength();
1471 0 : for( sal_Int32 i = 0 ; i < nCount ; ++i )
1472 : {
1473 0 : OUString aEntry = pSeq[i];
1474 0 : if( m_xSFA->isFolder( aEntry ) )
1475 : {
1476 0 : sal_Int32 nLastSlash = aEntry.lastIndexOf( '/' );
1477 0 : if( nLastSlash != -1 )
1478 : {
1479 0 : OUString aPureEntry = aEntry.copy( nLastSlash + 1 );
1480 :
1481 : // Check language scheme
1482 0 : int nLen = aPureEntry.getLength();
1483 0 : const sal_Unicode* pc = aPureEntry.getStr();
1484 0 : bool bStartCanBeLanguage = ( nLen >= 2 && isLetter( pc[0] ) && isLetter( pc[1] ) );
1485 0 : bool bIsLanguage = bStartCanBeLanguage &&
1486 0 : ( nLen == 2 || (nLen == 5 && pc[2] == '-' && isLetter( pc[3] ) && isLetter( pc[4] )) );
1487 0 : if( bIsLanguage )
1488 0 : rv.push_back( aPureEntry );
1489 : }
1490 : }
1491 0 : }
1492 0 : }
1493 :
1494 : // class DataBaseIterator
1495 :
1496 1466 : helpdatafileproxy::Hdf* DataBaseIterator::nextHdf( OUString* o_pExtensionPath, OUString* o_pExtensionRegistryPath )
1497 : {
1498 1466 : helpdatafileproxy::Hdf* pRetHdf = NULL;
1499 :
1500 8796 : while( !pRetHdf && m_eState != END_REACHED )
1501 : {
1502 5864 : switch( m_eState )
1503 : {
1504 : case INITIAL_MODULE:
1505 1466 : pRetHdf = m_rDatabases.getHelpDataFile( m_aInitialModule, m_aLanguage, m_bHelpText );
1506 1466 : m_eState = USER_EXTENSIONS; // Later: SHARED_MODULE
1507 1466 : break;
1508 :
1509 : // Later:
1510 : //case SHARED_MODULE
1511 :
1512 :
1513 : case USER_EXTENSIONS:
1514 : {
1515 1466 : Reference< deployment::XPackage > xParentPackageBundle;
1516 2932 : Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( xParentPackageBundle );
1517 1466 : if( !xHelpPackage.is() )
1518 1466 : break;
1519 0 : pRetHdf = implGetHdfFromPackage( xHelpPackage, o_pExtensionPath, o_pExtensionRegistryPath );
1520 1466 : break;
1521 : }
1522 :
1523 : case SHARED_EXTENSIONS:
1524 : {
1525 1466 : Reference< deployment::XPackage > xParentPackageBundle;
1526 2932 : Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( xParentPackageBundle );
1527 1466 : if( !xHelpPackage.is() )
1528 1466 : break;
1529 :
1530 0 : pRetHdf = implGetHdfFromPackage( xHelpPackage, o_pExtensionPath, o_pExtensionRegistryPath );
1531 1466 : break;
1532 : }
1533 :
1534 : case BUNDLED_EXTENSIONS:
1535 : {
1536 1466 : Reference< deployment::XPackage > xParentPackageBundle;
1537 2932 : Reference< deployment::XPackage > xHelpPackage = implGetNextBundledHelpPackage( xParentPackageBundle );
1538 1466 : if( !xHelpPackage.is() )
1539 1466 : break;
1540 :
1541 0 : pRetHdf = implGetHdfFromPackage( xHelpPackage, o_pExtensionPath, o_pExtensionRegistryPath );
1542 1466 : break;
1543 : }
1544 :
1545 : case END_REACHED:
1546 : OSL_FAIL( "DataBaseIterator::nextDb(): Invalid case END_REACHED" );
1547 0 : break;
1548 : }
1549 : }
1550 :
1551 1466 : return pRetHdf;
1552 : }
1553 :
1554 0 : helpdatafileproxy::Hdf* DataBaseIterator::implGetHdfFromPackage( Reference< deployment::XPackage > xPackage,
1555 : OUString* o_pExtensionPath, OUString* o_pExtensionRegistryPath )
1556 : {
1557 :
1558 0 : beans::Optional< OUString> optRegData;
1559 : try
1560 : {
1561 0 : optRegData = xPackage->getRegistrationDataURL();
1562 : }
1563 0 : catch ( deployment::ExtensionRemovedException&)
1564 : {
1565 0 : return NULL;
1566 : }
1567 :
1568 0 : helpdatafileproxy::Hdf* pRetHdf = NULL;
1569 0 : if (optRegData.IsPresent && !optRegData.Value.isEmpty())
1570 : {
1571 0 : OUString aRegDataUrl = optRegData.Value + "/";
1572 :
1573 0 : OUString aHelpFilesBaseName("help");
1574 :
1575 0 : OUString aUsedLanguage = m_aLanguage;
1576 : pRetHdf = m_rDatabases.getHelpDataFile(
1577 0 : aHelpFilesBaseName, aUsedLanguage, m_bHelpText, &aRegDataUrl);
1578 :
1579 : // Language fallback
1580 0 : if( !pRetHdf )
1581 : {
1582 0 : ::std::vector< OUString > av;
1583 0 : implGetLanguageVectorFromPackage( av, xPackage );
1584 0 : ::std::vector< OUString >::const_iterator pFound = LanguageTag::getFallback( av, m_aLanguage );
1585 0 : if( pFound != av.end() )
1586 : {
1587 0 : aUsedLanguage = *pFound;
1588 : pRetHdf = m_rDatabases.getHelpDataFile(
1589 0 : aHelpFilesBaseName, aUsedLanguage, m_bHelpText, &aRegDataUrl);
1590 0 : }
1591 : }
1592 :
1593 0 : if( o_pExtensionPath )
1594 0 : *o_pExtensionPath = aRegDataUrl + aUsedLanguage;
1595 :
1596 0 : if( o_pExtensionRegistryPath )
1597 0 : *o_pExtensionRegistryPath = xPackage->getURL() + "/" + aUsedLanguage;
1598 : }
1599 :
1600 0 : return pRetHdf;
1601 : }
1602 :
1603 : // class KeyDataBaseFileIterator
1604 :
1605 : //returns a file URL
1606 0 : OUString KeyDataBaseFileIterator::nextDbFile( bool& o_rbExtension )
1607 : {
1608 0 : OUString aRetFile;
1609 :
1610 0 : while( aRetFile.isEmpty() && m_eState != END_REACHED )
1611 : {
1612 0 : switch( m_eState )
1613 : {
1614 : case INITIAL_MODULE:
1615 0 : aRetFile = OUStringBuffer(m_rDatabases.getInstallPathAsURL()).
1616 0 : append(m_rDatabases.processLang(m_aLanguage)).append('/').
1617 0 : append(m_aInitialModule).append(".key").makeStringAndClear();
1618 :
1619 0 : o_rbExtension = false;
1620 :
1621 0 : m_eState = USER_EXTENSIONS; // Later: SHARED_MODULE
1622 0 : break;
1623 :
1624 : // Later:
1625 : //case SHARED_MODULE
1626 :
1627 :
1628 : case USER_EXTENSIONS:
1629 : {
1630 0 : Reference< deployment::XPackage > xParentPackageBundle;
1631 0 : Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( xParentPackageBundle );
1632 0 : if( !xHelpPackage.is() )
1633 0 : break;
1634 :
1635 0 : aRetFile = implGetDbFileFromPackage( xHelpPackage );
1636 0 : o_rbExtension = true;
1637 0 : break;
1638 : }
1639 :
1640 : case SHARED_EXTENSIONS:
1641 : {
1642 0 : Reference< deployment::XPackage > xParentPackageBundle;
1643 0 : Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( xParentPackageBundle );
1644 0 : if( !xHelpPackage.is() )
1645 0 : break;
1646 :
1647 0 : aRetFile = implGetDbFileFromPackage( xHelpPackage );
1648 0 : o_rbExtension = true;
1649 0 : break;
1650 : }
1651 :
1652 : case BUNDLED_EXTENSIONS:
1653 : {
1654 0 : Reference< deployment::XPackage > xParentPackageBundle;
1655 0 : Reference< deployment::XPackage > xHelpPackage = implGetNextBundledHelpPackage( xParentPackageBundle );
1656 0 : if( !xHelpPackage.is() )
1657 0 : break;
1658 :
1659 0 : aRetFile = implGetDbFileFromPackage( xHelpPackage );
1660 0 : o_rbExtension = true;
1661 0 : break;
1662 : }
1663 :
1664 : case END_REACHED:
1665 : OSL_FAIL( "DataBaseIterator::nextDbFile(): Invalid case END_REACHED" );
1666 0 : break;
1667 : }
1668 : }
1669 :
1670 0 : return aRetFile;
1671 : }
1672 :
1673 : //Returns a file URL, that does not contain macros
1674 0 : OUString KeyDataBaseFileIterator::implGetDbFileFromPackage
1675 : ( Reference< deployment::XPackage > xPackage )
1676 : {
1677 : OUString aExpandedURL =
1678 0 : implGetFileFromPackage( OUString( ".key" ), xPackage );
1679 :
1680 0 : return aExpandedURL;
1681 : }
1682 :
1683 : // class JarFileIterator
1684 :
1685 0 : Reference< XHierarchicalNameAccess > JarFileIterator::nextJarFile
1686 : ( Reference< deployment::XPackage >& o_xParentPackageBundle,
1687 : OUString* o_pExtensionPath, OUString* o_pExtensionRegistryPath )
1688 : {
1689 0 : Reference< XHierarchicalNameAccess > xNA;
1690 :
1691 0 : while( !xNA.is() && m_eState != END_REACHED )
1692 : {
1693 0 : switch( m_eState )
1694 : {
1695 : case INITIAL_MODULE:
1696 0 : xNA = m_rDatabases.jarFile( m_aInitialModule, m_aLanguage );
1697 0 : m_eState = USER_EXTENSIONS; // Later: SHARED_MODULE
1698 0 : break;
1699 :
1700 : // Later:
1701 : //case SHARED_MODULE
1702 :
1703 :
1704 : case USER_EXTENSIONS:
1705 : {
1706 0 : Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( o_xParentPackageBundle );
1707 0 : if( !xHelpPackage.is() )
1708 0 : break;
1709 :
1710 0 : xNA = implGetJarFromPackage( xHelpPackage, o_pExtensionPath, o_pExtensionRegistryPath );
1711 0 : break;
1712 : }
1713 :
1714 : case SHARED_EXTENSIONS:
1715 : {
1716 0 : Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( o_xParentPackageBundle );
1717 0 : if( !xHelpPackage.is() )
1718 0 : break;
1719 :
1720 0 : xNA = implGetJarFromPackage( xHelpPackage, o_pExtensionPath, o_pExtensionRegistryPath );
1721 0 : break;
1722 : }
1723 :
1724 : case BUNDLED_EXTENSIONS:
1725 : {
1726 0 : Reference< deployment::XPackage > xHelpPackage = implGetNextBundledHelpPackage( o_xParentPackageBundle );
1727 0 : if( !xHelpPackage.is() )
1728 0 : break;
1729 :
1730 0 : xNA = implGetJarFromPackage( xHelpPackage, o_pExtensionPath, o_pExtensionRegistryPath );
1731 0 : break;
1732 : }
1733 :
1734 : case END_REACHED:
1735 : OSL_FAIL( "JarFileIterator::nextJarFile(): Invalid case END_REACHED" );
1736 0 : break;
1737 : }
1738 : }
1739 :
1740 0 : return xNA;
1741 : }
1742 :
1743 0 : Reference< XHierarchicalNameAccess > JarFileIterator::implGetJarFromPackage
1744 : ( Reference< deployment::XPackage > xPackage, OUString* o_pExtensionPath, OUString* o_pExtensionRegistryPath )
1745 : {
1746 0 : Reference< XHierarchicalNameAccess > xNA;
1747 :
1748 : OUString zipFile =
1749 0 : implGetFileFromPackage( OUString( ".jar" ), xPackage );
1750 :
1751 : try
1752 : {
1753 0 : Sequence< Any > aArguments( 2 );
1754 0 : aArguments[ 0 ] <<= zipFile;
1755 :
1756 : // let ZipPackage be used ( no manifest.xml is required )
1757 0 : beans::NamedValue aArg;
1758 0 : aArg.Name = "StorageFormat";
1759 0 : aArg.Value <<= OUString(ZIP_STORAGE_FORMAT_STRING);
1760 0 : aArguments[ 1 ] <<= aArg;
1761 :
1762 0 : Reference< XMultiComponentFactory >xSMgr( m_xContext->getServiceManager(), UNO_QUERY );
1763 : Reference< XInterface > xIfc
1764 0 : = xSMgr->createInstanceWithArgumentsAndContext(
1765 : OUString(
1766 : "com.sun.star.packages.comp.ZipPackage" ),
1767 0 : aArguments, m_xContext );
1768 :
1769 0 : if ( xIfc.is() )
1770 : {
1771 0 : xNA = Reference< XHierarchicalNameAccess >( xIfc, UNO_QUERY );
1772 :
1773 : OSL_ENSURE( xNA.is(),
1774 : "JarFileIterator::implGetJarFromPackage() - "
1775 : "Got no hierarchical name access!" );
1776 0 : }
1777 : }
1778 0 : catch ( RuntimeException & )
1779 : {}
1780 0 : catch ( Exception & )
1781 : {}
1782 :
1783 0 : if( xNA.is() && o_pExtensionPath != NULL )
1784 : {
1785 : // Extract path including language from file name
1786 0 : sal_Int32 nLastSlash = zipFile.lastIndexOf( '/' );
1787 0 : if( nLastSlash != -1 )
1788 0 : *o_pExtensionPath = zipFile.copy( 0, nLastSlash );
1789 :
1790 0 : if( o_pExtensionRegistryPath != NULL )
1791 : {
1792 0 : OUString& rPath = *o_pExtensionPath;
1793 0 : sal_Int32 nLastSlashInPath = rPath.lastIndexOf( '/', rPath.getLength() - 1 );
1794 :
1795 0 : *o_pExtensionRegistryPath = xPackage->getURL();
1796 0 : *o_pExtensionRegistryPath += rPath.copy( nLastSlashInPath);
1797 : }
1798 : }
1799 :
1800 0 : return xNA;
1801 : }
1802 :
1803 : // class IndexFolderIterator
1804 :
1805 0 : OUString IndexFolderIterator::nextIndexFolder( bool& o_rbExtension, bool& o_rbTemporary )
1806 : {
1807 0 : OUString aIndexFolder;
1808 :
1809 0 : while( aIndexFolder.isEmpty() && m_eState != END_REACHED )
1810 : {
1811 0 : switch( m_eState )
1812 : {
1813 : case INITIAL_MODULE:
1814 0 : aIndexFolder = m_rDatabases.getInstallPathAsURL()
1815 0 : + m_rDatabases.processLang(m_aLanguage) + "/"
1816 0 : + m_aInitialModule + ".idxl";
1817 :
1818 0 : o_rbTemporary = false;
1819 0 : o_rbExtension = false;
1820 :
1821 0 : m_eState = USER_EXTENSIONS; // Later: SHARED_MODULE
1822 0 : break;
1823 :
1824 : // Later:
1825 : //case SHARED_MODULE
1826 :
1827 :
1828 : case USER_EXTENSIONS:
1829 : {
1830 0 : Reference< deployment::XPackage > xParentPackageBundle;
1831 0 : Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( xParentPackageBundle );
1832 0 : if( !xHelpPackage.is() )
1833 0 : break;
1834 :
1835 0 : aIndexFolder = implGetIndexFolderFromPackage( o_rbTemporary, xHelpPackage );
1836 0 : o_rbExtension = true;
1837 0 : break;
1838 : }
1839 :
1840 : case SHARED_EXTENSIONS:
1841 : {
1842 0 : Reference< deployment::XPackage > xParentPackageBundle;
1843 0 : Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( xParentPackageBundle );
1844 0 : if( !xHelpPackage.is() )
1845 0 : break;
1846 :
1847 0 : aIndexFolder = implGetIndexFolderFromPackage( o_rbTemporary, xHelpPackage );
1848 0 : o_rbExtension = true;
1849 0 : break;
1850 : }
1851 :
1852 : case BUNDLED_EXTENSIONS:
1853 : {
1854 0 : Reference< deployment::XPackage > xParentPackageBundle;
1855 0 : Reference< deployment::XPackage > xHelpPackage = implGetNextBundledHelpPackage( xParentPackageBundle );
1856 0 : if( !xHelpPackage.is() )
1857 0 : break;
1858 :
1859 0 : aIndexFolder = implGetIndexFolderFromPackage( o_rbTemporary, xHelpPackage );
1860 0 : o_rbExtension = true;
1861 0 : break;
1862 : }
1863 :
1864 : case END_REACHED:
1865 : OSL_FAIL( "IndexFolderIterator::nextIndexFolder(): Invalid case END_REACHED" );
1866 0 : break;
1867 : }
1868 : }
1869 :
1870 0 : return aIndexFolder;
1871 : }
1872 :
1873 0 : OUString IndexFolderIterator::implGetIndexFolderFromPackage( bool& o_rbTemporary, Reference< deployment::XPackage > xPackage )
1874 : {
1875 : OUString aIndexFolder =
1876 0 : implGetFileFromPackage( OUString( ".idxl" ), xPackage );
1877 :
1878 0 : o_rbTemporary = false;
1879 0 : if( !m_xSFA->isFolder( aIndexFolder ) )
1880 : {
1881 : // i98680: Missing index? Try to generate now
1882 0 : OUString aLangURL = implGetFileFromPackage( OUString(), xPackage );
1883 0 : if( m_xSFA->isFolder( aLangURL ) )
1884 : {
1885 : // Test write access (shared extension may be read only)
1886 0 : bool bIsWriteAccess = false;
1887 : try
1888 : {
1889 0 : OUString aCreateTestFolder = aLangURL + "CreateTestFolder";
1890 0 : m_xSFA->createFolder( aCreateTestFolder );
1891 0 : if( m_xSFA->isFolder( aCreateTestFolder ) )
1892 0 : bIsWriteAccess = true;
1893 :
1894 0 : m_xSFA->kill( aCreateTestFolder );
1895 : }
1896 0 : catch (const Exception &)
1897 : {
1898 : }
1899 :
1900 : // TEST
1901 : //bIsWriteAccess = false;
1902 :
1903 : try
1904 : {
1905 0 : OUString aLang;
1906 0 : sal_Int32 nLastSlash = aLangURL.lastIndexOf( '/' );
1907 0 : if( nLastSlash != -1 )
1908 0 : aLang = aLangURL.copy( nLastSlash + 1 );
1909 : else
1910 0 : aLang = "en";
1911 :
1912 0 : OUString aMod("help");
1913 :
1914 0 : OUString aZipDir = aLangURL;
1915 0 : if( !bIsWriteAccess )
1916 : {
1917 0 : OUString aTempFileURL;
1918 0 : ::osl::FileBase::RC eErr = ::osl::File::createTempFile( 0, 0, &aTempFileURL );
1919 0 : if( eErr == ::osl::FileBase::E_None )
1920 : {
1921 0 : OUString aTempDirURL = aTempFileURL;
1922 : try
1923 : {
1924 0 : m_xSFA->kill( aTempDirURL );
1925 : }
1926 0 : catch (const Exception &)
1927 : {
1928 : }
1929 0 : m_xSFA->createFolder( aTempDirURL );
1930 :
1931 0 : aZipDir = aTempDirURL;
1932 0 : o_rbTemporary = true;
1933 0 : }
1934 : }
1935 :
1936 0 : HelpIndexer aIndexer(aLang, aMod, aLangURL, aZipDir);
1937 0 : aIndexer.indexDocuments();
1938 :
1939 0 : if( bIsWriteAccess )
1940 0 : aIndexFolder = implGetFileFromPackage( OUString( ".idxl" ), xPackage );
1941 : else
1942 0 : aIndexFolder = aZipDir + "/help.idxl";
1943 : }
1944 0 : catch (const Exception &)
1945 : {
1946 : }
1947 0 : }
1948 : }
1949 :
1950 0 : return aIndexFolder;
1951 : }
1952 :
1953 0 : void IndexFolderIterator::deleteTempIndexFolder( const OUString& aIndexFolder )
1954 : {
1955 0 : sal_Int32 nLastSlash = aIndexFolder.lastIndexOf( '/' );
1956 0 : if( nLastSlash != -1 )
1957 : {
1958 0 : OUString aTmpFolder = aIndexFolder.copy( 0, nLastSlash );
1959 : try
1960 : {
1961 0 : m_xSFA->kill( aTmpFolder );
1962 : }
1963 0 : catch (const Exception &)
1964 : {
1965 0 : }
1966 : }
1967 120 : }
1968 :
1969 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|