21#include <config_features.h>
29#include <osl/file.hxx>
36#if HAVE_FEATURE_XMLHELP
40#include <com/sun/star/deployment/DeploymentException.hpp>
41#include <com/sun/star/deployment/ExtensionRemovedException.hpp>
42#include <com/sun/star/ucb/SimpleFileAccess.hpp>
43#include <com/sun/star/util/XMacroExpander.hpp>
60 BackendImpl * getMyBackend()
const;
63 virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
64 ::osl::ResettableMutexGuard & guard,
66 Reference<XCommandEnvironment>
const & xCmdEnv )
override;
67 virtual void processPackage_(
68 ::osl::ResettableMutexGuard & guard,
72 Reference<XCommandEnvironment>
const & xCmdEnv )
override;
78 OUString
const & url, OUString
const &
name,
79 Reference<deployment::XPackageTypeInfo>
const & xPackageType,
82 bool extensionContainsCompiledHelp();
85 virtual css::beans::Optional< OUString > SAL_CALL getRegistrationDataURL()
override;
87 friend class PackageImpl;
90 virtual Reference<deployment::XPackage> bindPackage_(
91 OUString
const & url, OUString
const & mediaType,
93 Reference<XCommandEnvironment>
const & xCmdEnv )
override;
95 void implProcessHelp( PackageImpl *
package,
bool doRegisterPackage,
96 Reference<ucb::XCommandEnvironment>
const & xCmdEnv);
97 void implCollectXhpFiles(
const OUString& aDir,
98 std::vector< OUString >& o_rXhpFileVector );
100 ::std::optional<HelpBackendDb::Data> readDataFromDb(std::u16string_view url);
101 bool hasActiveEntry(std::u16string_view url);
102 bool activateEntry(std::u16string_view url);
104 Reference< ucb::XSimpleFileAccess3 >
const & getFileAccess();
105 Reference< ucb::XSimpleFileAccess3 >
m_xSFA;
112 BackendImpl( Sequence<Any>
const & args,
113 Reference<XComponentContext>
const & xComponentContext );
121 virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
122 getSupportedPackageTypes()
override;
123 virtual void SAL_CALL packageRemoved(OUString
const & url, OUString
const & mediaType)
override;
128BackendImpl::BackendImpl(
129 Sequence<Any>
const & args,
130 Reference<XComponentContext>
const & xComponentContext )
131 : PackageRegistryBackend(
args, xComponentContext ),
141 OUString dbFile =
makeURL(getCachePath(),
"backenddb.xml");
150 std::vector<OUString> folders =
m_backendDb->getAllDataUrls();
151 deleteUnusedFolders(folders);
155OUString BackendImpl::getImplementationName()
157 return "com.sun.star.comp.deployment.help.PackageRegistryBackend";
160sal_Bool BackendImpl::supportsService(
const OUString& ServiceName )
165css::uno::Sequence< OUString > BackendImpl::getSupportedServiceNames()
172Sequence< Reference<deployment::XPackageTypeInfo> >
173BackendImpl::getSupportedPackageTypes()
178void BackendImpl::packageRemoved(OUString
const & url, OUString
const & )
186Reference<deployment::XPackage> BackendImpl::bindPackage_(
187 OUString
const & url, OUString
const & mediaType_,
188 bool bRemoved, OUString
const & identifier,
189 Reference<XCommandEnvironment>
const & xCmdEnv )
192 if (mediaType_.isEmpty())
193 throw lang::IllegalArgumentException(
194 StrCannotDetectMediaType() + url,
195 static_cast<OWeakObject *
>(
this),
static_cast<sal_Int16
>(-1) );
197 OUString
type, subType;
201 if (
type.equalsIgnoreAsciiCase(
"application"))
208 name = StrTitle::getTitle( ucbContent );
211 if (subType.equalsIgnoreAsciiCase(
"vnd.sun.star.help"))
213 return new PackageImpl(
219 throw lang::IllegalArgumentException(
220 StrUnsupportedMediaType() + mediaType_,
221 static_cast<OWeakObject *
>(
this),
222 static_cast<sal_Int16
>(-1) );
225::std::optional<HelpBackendDb::Data> BackendImpl::readDataFromDb(
226 std::u16string_view url)
228 ::std::optional<HelpBackendDb::Data> data;
234bool BackendImpl::hasActiveEntry(std::u16string_view url)
241bool BackendImpl::activateEntry(std::u16string_view url)
249BackendImpl::PackageImpl::PackageImpl(
251 OUString
const & url, OUString
const & name,
252 Reference<deployment::XPackageTypeInfo>
const & xPackageType,
253 bool bRemoved, OUString
const & identifier)
260BackendImpl * BackendImpl::PackageImpl::getMyBackend()
const
262 BackendImpl * pBackend =
static_cast<BackendImpl *
>(m_myBackend.get());
263 if (
nullptr == pBackend)
269 static_cast<OWeakObject*
>(
const_cast<PackageImpl *
>(
this)));
274bool BackendImpl::PackageImpl::extensionContainsCompiledHelp()
276 bool bCompiled =
true;
279 ::osl::Directory helpFolder(aExpandedHelpURL);
280 if ( helpFolder.open() == ::osl::File::E_None)
286 ::osl::DirectoryItem item;
287 ::osl::File::RC errorNext = ::osl::File::E_None;
288 while ((errorNext = helpFolder.getNextItem(item)) == ::osl::File::E_None)
291 ::osl::FileStatus stat(osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName |osl_FileStatus_Mask_FileURL);
292 if (item.getFileStatus(stat) == ::osl::File::E_None)
294 if (stat.getFileType() != ::osl::FileStatus::Directory)
298 OUString compUrl(stat.getFileURL() +
"/help.idxl");
299 ::osl::Directory compiledFolder(compUrl);
300 if (compiledFolder.open() != ::osl::File::E_None)
314 if (errorNext != ::osl::File::E_NOENT
315 && errorNext != ::osl::File::E_None)
326beans::Optional< beans::Ambiguous<sal_Bool> >
327BackendImpl::PackageImpl::isRegistered_(
328 ::osl::ResettableMutexGuard &,
330 Reference<XCommandEnvironment>
const & )
332 BackendImpl * that = getMyBackend();
335 if (that->hasActiveEntry(getURL()))
338 return beans::Optional< beans::Ambiguous<sal_Bool> >(
true, beans::Ambiguous<sal_Bool>( bReg,
false ) );
342void BackendImpl::PackageImpl::processPackage_(
343 ::osl::ResettableMutexGuard &,
344 bool doRegisterPackage,
347 Reference<XCommandEnvironment>
const & xCmdEnv )
349 BackendImpl* that = getMyBackend();
350 that->implProcessHelp(
this, doRegisterPackage, xCmdEnv);
353beans::Optional< OUString > BackendImpl::PackageImpl::getRegistrationDataURL()
356 throw deployment::ExtensionRemovedException();
358 ::std::optional<HelpBackendDb::Data> data =
359 getMyBackend()->readDataFromDb(getURL());
361 if (data && getMyBackend()->hasActiveEntry(getURL()))
362 return beans::Optional<OUString>(
true, data->dataUrl);
364 return beans::Optional<OUString>(
true, OUString());
367void BackendImpl::implProcessHelp(
368 PackageImpl *
package,
bool doRegisterPackage,
369 Reference<ucb::XCommandEnvironment>
const & xCmdEnv)
371 Reference< deployment::XPackage > xPackage(
package);
372 OSL_ASSERT(xPackage.is());
373 if (doRegisterPackage)
376 if ( !activateEntry(xPackage->getURL()))
378 HelpBackendDb::Data data;
379 data.dataUrl = xPackage->getURL();
380 if (!
package->extensionContainsCompiledHelp())
382#if HAVE_FEATURE_XMLHELP
383 const OUString sHelpFolder = createFolder(xCmdEnv);
384 data.dataUrl = sHelpFolder;
386 Reference< ucb::XSimpleFileAccess3 > xSFA = getFileAccess();
387 OUString aHelpURL = xPackage->getURL();
389 if( !xSFA->isFolder( aExpandedHelpURL ) )
391 OUString aErrStr =
DpResId( RID_STR_HELPPROCESSING_GENERAL_ERROR ) +
393 OWeakObject* oWeakThis =
this;
394 throw deployment::DeploymentException( OUString(), oWeakThis,
395 Any( uno::Exception( aErrStr, oWeakThis ) ) );
400 sal_Int32 nLangCount = aLanguageFolderSeq.getLength();
401 const OUString* pSeq = aLanguageFolderSeq.getConstArray();
402 for( sal_Int32 iLang = 0 ; iLang < nLangCount ; ++iLang )
404 OUString aLangURL = pSeq[iLang];
405 if( xSFA->isFolder( aLangURL ) )
407 std::vector< OUString > aXhpFileVector;
410 sal_Int32 indexStartSegment = aLangURL.lastIndexOf(
'/');
412 OUString langFolderURLSegment(
414 indexStartSegment + 1, aLangURL.getLength() - indexStartSegment - 1));
418 const OUString langFolderDest =
makeURL(sHelpFolder, langFolderURLSegment);
422 langFolderDest, xCmdEnv);
424 static constexpr OUStringLiteral aHelpStr(u
"help");
427 makeURL(sHelpFolder, langFolderURLSegment +
"/" + aHelpStr +
".jar"));
430 OUString aEncodedJarFilePath = rtl::Uri::encode(
431 aJarFile, rtl_UriCharClassPchar,
432 rtl_UriEncodeIgnoreEscapes,
433 RTL_TEXTENCODING_UTF8 );
434 OUString aDestBasePath =
"vnd.sun.star.zip://" +
435 aEncodedJarFilePath +
"/" ;
437 sal_Int32 nLenLangFolderURL = aLangURL.getLength() + 1;
440 sal_Int32 nSubLangCount = aSubLangSeq.getLength();
441 const OUString* pSubLangSeq = aSubLangSeq.getConstArray();
442 for( sal_Int32 iSubLang = 0 ; iSubLang < nSubLangCount ; ++iSubLang )
444 OUString aSubFolderURL = pSubLangSeq[iSubLang];
445 if( !xSFA->isFolder( aSubFolderURL ) )
448 implCollectXhpFiles( aSubFolderURL, aXhpFileVector );
451 std::u16string_view aPureFolderName = aSubFolderURL.subView( nLenLangFolderURL );
452 OUString aDestPath = aDestBasePath + aPureFolderName;
453 xSFA->copy( aSubFolderURL, aDestPath );
457 sal_Int32 nXhpFileCount = aXhpFileVector.size();
458 std::unique_ptr<OUString[]> pXhpFiles(
new OUString[nXhpFileCount]);
459 for( sal_Int32 iXhp = 0 ; iXhp < nXhpFileCount ; ++iXhp )
461 OUString aXhpFile = aXhpFileVector[iXhp];
462 OUString aXhpRelFile = aXhpFile.copy( nLenLangFolderURL );
463 pXhpFiles[iXhp] = aXhpRelFile;
467 OUString aOfficeHelpPathFileURL;
468 ::osl::File::getFileURLFromSystemPath( aOfficeHelpPath, aOfficeHelpPathFileURL );
472 aOfficeHelpPathFileURL, aHelpStr, aLangURL,
473 nXhpFileCount, pXhpFiles.get(),
474 langFolderDestExpanded, aErrorInfo );
481 sal_Int32 nLastSlash = aLangURL.lastIndexOf(
'/' );
482 if( nLastSlash != -1 )
483 aLang = aLangURL.copy( nLastSlash + 1 );
487 HelpIndexer aIndexer(aLang,
"help", langFolderDestExpanded, langFolderDestExpanded);
488 aIndexer.indexDocuments();
496 case HelpProcessingErrorClass::General: pErrStrId = RID_STR_HELPPROCESSING_GENERAL_ERROR;
break;
497 case HelpProcessingErrorClass::XmlParsing: pErrStrId = RID_STR_HELPPROCESSING_XMLPARSING_ERROR;
break;
509 sal_Int32 nSearchCR = aErrMsg.indexOf( nCR );
510 sal_Int32 nSearchLF = aErrMsg.indexOf( nLF );
511 if( nSearchCR != -1 || nSearchLF != -1 )
514 if( nSearchCR == -1 )
516 else if( nSearchLF == -1 )
519 nCopy = ( nSearchCR < nSearchLF ) ? nSearchCR : nSearchLF;
521 aErrMsg = aErrMsg.copy( 0, nCopy );
524 if (pErrStrId != RID_STR_HELPPROCESSING_XMLPARSING_ERROR && !aErrorInfo.
m_aXMLParsingFile.isEmpty() )
529 rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
530 aErrStr += aDecodedFile;
533 aErrStr +=
", line " +
539 OWeakObject* oWeakThis =
this;
540 throw deployment::DeploymentException( OUString(), oWeakThis,
541 Any( uno::Exception( aErrStr, oWeakThis ) ) );
562void BackendImpl::implCollectXhpFiles(
const OUString& aDir,
563 std::vector< OUString >& o_rXhpFileVector )
565 Reference< ucb::XSimpleFileAccess3 > xSFA = getFileAccess();
570 const OUString* pSeq =
aSeq.getConstArray();
571 for( sal_Int32 i = 0 ;
i <
nCount ; ++
i )
573 OUString
aURL = pSeq[
i];
574 if( xSFA->isFolder(
aURL ) )
576 implCollectXhpFiles(
aURL, o_rXhpFileVector );
580 sal_Int32 nLastDot =
aURL.lastIndexOf(
'.' );
583 std::u16string_view aExt =
aURL.subView( nLastDot + 1 );
585 o_rXhpFileVector.push_back(
aURL );
591Reference< ucb::XSimpleFileAccess3 >
const & BackendImpl::getFileAccess()
603 "dp_registry::backend::help::BackendImpl::getFileAccess(), "
604 "could not instantiate SimpleFileAccess." );
614extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
616 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any>
const& args)
618 return cppu::acquire(
new dp_registry::backend::help::BackendImpl(
args, context));
bool compileExtensionHelp(const OUString &aOfficeHelpPath, std::u16string_view aExtensionName, std::u16string_view aExtensionLanguageRoot, sal_Int32 nXhpFileCount, const OUString *pXhpFiles, std::u16string_view aDestination, HelpProcessingErrorInfo &o_rHelpProcessingErrorInfo)
static bool parse(OUString const &rMediaType, OUString &rType, OUString &rSubType, INetContentTypeParameterList *pParameters=nullptr)
Sequence< Reference< deployment::XPackageTypeInfo > > m_typeInfos
const Reference< deployment::XPackageTypeInfo > m_xHelpTypeInfo
Reference< ucb::XSimpleFileAccess3 > m_xSFA
std::unique_ptr< HelpBackendDb > m_backendDb
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_deployment_help_PackageRegistryBackend_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &args)
OUString DpResId(TranslateId aId)
std::unordered_map< OString, INetContentTypeParameter > INetContentTypeParameterList
static uno::Reference< css::uno::XComponentContext > xContext
Sequence< sal_Int8 > aSeq
Reference< XComponentContext > getComponentContext(Reference< XMultiServiceFactory > const &factory)
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
OUString makeURL(std::u16string_view baseURL, OUString const &relPath_)
appends a relative path to a url.
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool create_folder(::ucbhelper::Content *ucb_content, OUString const &url, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv, bool throw_exc=true)
OUString expandUnoRcUrl(OUString const &url)
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)
constexpr OUStringLiteral BACKEND_SERVICE_NAME
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
::boost::spirit::classic::rule< ScannerT > identifier
HelpProcessingErrorClass m_eErrorClass
OUString m_aXMLParsingFile
sal_Int32 m_nXMLParsingLine