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