33#include <rtl/ustrbuf.hxx>
43#include <com/sun/star/lang/WrappedTargetException.hpp>
44#include <com/sun/star/graphic/XGraphic.hpp>
45#include <com/sun/star/graphic/GraphicProvider.hpp>
46#include <com/sun/star/graphic/XGraphicProvider.hpp>
47#include <com/sun/star/io/Pipe.hpp>
48#include <com/sun/star/io/XOutputStream.hpp>
49#include <com/sun/star/io/XInputStream.hpp>
50#include <com/sun/star/task/InteractionClassification.hpp>
51#include <com/sun/star/task/XInteractionApprove.hpp>
52#include <com/sun/star/ucb/CommandAbortedException.hpp>
53#include <com/sun/star/ucb/CommandFailedException.hpp>
54#include <com/sun/star/ucb/ContentCreationException.hpp>
55#include <com/sun/star/ucb/XInteractionReplaceExistingData.hpp>
56#include <com/sun/star/ucb/NameClashResolveRequest.hpp>
57#include <com/sun/star/ucb/XContentAccess.hpp>
58#include <com/sun/star/ucb/NameClash.hpp>
59#include <com/sun/star/ucb/UnsupportedCommandException.hpp>
60#include <com/sun/star/sdbc/XResultSet.hpp>
61#include <com/sun/star/sdbc/XRow.hpp>
62#include <com/sun/star/packages/manifest/ManifestReader.hpp>
63#include <com/sun/star/packages/manifest/ManifestWriter.hpp>
64#include <com/sun/star/deployment/DependencyException.hpp>
65#include <com/sun/star/deployment/DeploymentException.hpp>
66#include <com/sun/star/deployment/ExtensionRemovedException.hpp>
67#include <com/sun/star/deployment/LicenseException.hpp>
68#include <com/sun/star/deployment/PlatformException.hpp>
69#include <com/sun/star/deployment/Prerequisites.hpp>
88typedef cppu::ImplInheritanceHelper<PackageRegistryBackend> ImplBaseT;
91class BackendImpl :
public ImplBaseT
95 BackendImpl * getMyBackend()
const;
102 Sequence< Reference<deployment::XPackage> >
m_bundle;
103 Sequence< Reference<deployment::XPackage> > *
m_pBundle;
107 Reference<deployment::XPackage> bindBundleItem(
108 OUString
const & url, OUString
const & mediaType,
110 OUString
const & identifier,
111 Reference<ucb::XCommandEnvironment>
const & xCmdEnv,
112 bool notifyDetectionError =
true );
114 typedef std::vector< Reference<deployment::XPackage> > t_packagevec;
116 t_packagevec & bundle,
118 Reference<ucb::XCommandEnvironment>
const & xCmdEnv );
119 void scanLegacyBundle(
120 t_packagevec & bundle,
121 OUString
const & url,
123 Reference<ucb::XCommandEnvironment>
const & xCmdEnv,
124 bool skip_registration =
false );
125 std::vector<Reference<deployment::XPackage> > getPackagesFromDb(
126 Reference<ucb::XCommandEnvironment>
const & xCmdEnv);
128 Reference<ucb::XCommandEnvironment >
const & environment);
130 bool checkDependencies(
131 Reference<ucb::XCommandEnvironment >
const &
133 DescriptionInfoset
const & description);
142 Reference< ucb::XCommandEnvironment >
const & xCmdEnv,
143 DescriptionInfoset
const & description,
bool bNoLicenseChecking);
145 OUString getTextFromURL(
146 const Reference< ucb::XCommandEnvironment >& xCmdEnv,
147 const OUString& licenseUrl);
152 virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
153 ::osl::ResettableMutexGuard & guard,
155 Reference<ucb::XCommandEnvironment>
const & xCmdEnv )
override;
156 virtual void processPackage_(
157 ::osl::ResettableMutexGuard & guard,
158 bool registerPackage,
161 Reference<ucb::XCommandEnvironment>
const & xCmdEnv )
override;
163 virtual void SAL_CALL disposing()
override;
169 OUString
const & url,
170 OUString
const & name,
171 Reference<deployment::XPackageTypeInfo>
const & xPackageType,
174 OUString
const & identifier);
177 virtual sal_Bool SAL_CALL isBundle()
override;
179 virtual Sequence< Reference<deployment::XPackage> > SAL_CALL getBundle(
180 Reference<task::XAbortChannel>
const & xAbortChannel,
181 Reference<ucb::XCommandEnvironment>
const & xCmdEnv )
override;
182 virtual OUString SAL_CALL getDescription()
override;
184 virtual OUString SAL_CALL getLicenseText()
override;
186 virtual void SAL_CALL exportTo(
187 OUString
const & destFolderURL, OUString
const & newTitle,
188 sal_Int32 nameClashAction,
189 Reference<ucb::XCommandEnvironment>
const & xCmdEnv )
override;
191 virtual ::sal_Int32 SAL_CALL checkPrerequisites(
192 const Reference< task::XAbortChannel >& xAbortChannel,
193 const Reference< ucb::XCommandEnvironment >& xCmdEnv,
194 sal_Bool noLicenseChecking)
override;
196 virtual sal_Bool SAL_CALL checkDependencies(
197 const Reference< ucb::XCommandEnvironment >& xCmdEnv )
override;
199 virtual beans::Optional<OUString> SAL_CALL
getIdentifier()
override;
201 virtual OUString SAL_CALL getVersion()
override;
203 virtual Sequence<OUString> SAL_CALL getUpdateInformationURLs()
override;
205 virtual beans::StringPair SAL_CALL getPublisherInfo()
override;
207 virtual OUString SAL_CALL getDisplayName()
override;
210 getIcon(
sal_Bool bHighContrast )
override;
212 friend class PackageImpl;
221 void addDataToDb(OUString
const & url, ExtensionBackendDb::Data
const & data);
222 ExtensionBackendDb::Data readDataFromDb(std::u16string_view url);
223 void revokeEntryFromDb(std::u16string_view url);
226 virtual Reference<deployment::XPackage> bindPackage_(
227 OUString
const & url, OUString
const & mediaType,
228 bool bRemoved, OUString
const & identifier,
229 Reference<ucb::XCommandEnvironment>
const & xCmdEnv )
override;
231 virtual void SAL_CALL disposing()
override;
235 Sequence<Any>
const & args,
236 Reference<XComponentContext>
const & xComponentContext,
237 Reference<deployment::XPackageRegistry>
const & xRootRegistry );
245 virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
246 getSupportedPackageTypes()
override;
247 virtual void SAL_CALL packageRemoved(OUString
const & url, OUString
const & mediaType)
override;
249 using ImplBaseT::disposing;
257 explicit XPackage_eq(OUString s) :
m_URL(
std::move(s)) {}
258 bool operator() (
const Reference<deployment::XPackage> & p)
const
260 return m_URL ==
p->getURL();
265BackendImpl::BackendImpl(
266 Sequence<Any>
const & args,
267 Reference<XComponentContext>
const & xComponentContext,
268 Reference<deployment::XPackageRegistry>
const & xRootRegistry )
269 : ImplBaseT(
args, xComponentContext ),
272 "application/vnd.sun.star.package-bundle",
274 DpResId(RID_STR_PACKAGE_BUNDLE)
277 "application/vnd.sun.star.legacy-package-bundle",
283 if (!transientMode())
286 dbFile =
makeURL(dbFile,
"backenddb.xml");
293void BackendImpl::disposing()
296 PackageRegistryBackend::disposing();
300OUString BackendImpl::getImplementationName()
302 return "com.sun.star.comp.deployment.bundle.PackageRegistryBackend";
305sal_Bool BackendImpl::supportsService(OUString
const & ServiceName)
310Sequence<OUString> BackendImpl::getSupportedServiceNames()
317Sequence< Reference<deployment::XPackageTypeInfo> >
318BackendImpl::getSupportedPackageTypes()
323void BackendImpl::packageRemoved(OUString
const & url, OUString
const & )
327 ExtensionBackendDb::Data data = readDataFromDb(url);
328 for (
auto const& item : data.items)
340Reference<deployment::XPackage> BackendImpl::bindPackage_(
341 OUString
const & url, OUString
const & mediaType_,
342 bool bRemoved, OUString
const & identifier,
343 Reference<ucb::XCommandEnvironment>
const & xCmdEnv )
345 OUString mediaType( mediaType_ );
346 if (mediaType.isEmpty())
357 &metaInfContent,
makeURL( url,
"META-INF" ),
360 mediaType =
"application/vnd.sun.star.package-bundle";
366 const OUString title( StrTitle::getTitle( ucbContent ) );
367 if (title.endsWithIgnoreAsciiCase(
".oxt") ||
368 title.endsWithIgnoreAsciiCase(
".uno.pkg"))
369 mediaType =
"application/vnd.sun.star.package-bundle";
370 else if (title.endsWithIgnoreAsciiCase(
".zip"))
371 mediaType =
"application/vnd.sun.star.legacy-package-bundle";
374 if (mediaType.isEmpty())
375 throw lang::IllegalArgumentException(
376 StrCannotDetectMediaType() + url,
377 static_cast<OWeakObject *
>(
this),
static_cast<sal_Int16
>(-1) );
380 OUString
type, subType;
384 if (
type.equalsIgnoreAsciiCase(
"application"))
394 name = StrTitle::getTitle( ucbContent );
396 if (subType.equalsIgnoreAsciiCase(
"vnd.sun.star.package-bundle"))
398 return new PackageImpl(
402 else if (subType.equalsIgnoreAsciiCase(
"vnd.sun.star.legacy-package-bundle"))
404 return new PackageImpl(
410 throw lang::IllegalArgumentException(
411 StrUnsupportedMediaType() + mediaType,
412 static_cast<OWeakObject *
>(
this),
413 static_cast<sal_Int16
>(-1) );
416void BackendImpl::addDataToDb(
417 OUString
const & url, ExtensionBackendDb::Data
const & data)
423ExtensionBackendDb::Data BackendImpl::readDataFromDb(
424 std::u16string_view url)
426 ExtensionBackendDb::Data data;
432void BackendImpl::revokeEntryFromDb(std::u16string_view url)
439BackendImpl::PackageImpl::PackageImpl(
441 OUString
const & url,
442 OUString
const & name,
443 Reference<deployment::XPackageTypeInfo>
const & xPackageType,
444 bool legacyBundle,
bool bRemoved, OUString
const & identifier)
452 m_dbData = getMyBackend()->readDataFromDb(url);
455BackendImpl * BackendImpl::PackageImpl::getMyBackend()
const
457 BackendImpl * pBackend =
static_cast<BackendImpl *
>(m_myBackend.get());
458 if (
nullptr == pBackend)
464 static_cast<OWeakObject*
>(
const_cast<PackageImpl *
>(
this)));
469void BackendImpl::PackageImpl::disposing()
471 sal_Int32 len =
m_bundle.getLength();
472 Reference<deployment::XPackage>
const *
p =
m_bundle.getConstArray();
473 for ( sal_Int32 pos = 0;
pos < len; ++
pos )
477 Package::disposing();
482beans::Optional< beans::Ambiguous<sal_Bool> >
483BackendImpl::PackageImpl::isRegistered_(
484 ::osl::ResettableMutexGuard &,
486 Reference<ucb::XCommandEnvironment>
const & xCmdEnv )
494 const Sequence< Reference<deployment::XPackage> > bundle(
495 getBundle( abortChannel, xCmdEnv ) );
498 bool present =
false;
500 for ( sal_Int32 pos = bundle.getLength(); pos--; )
502 Reference<deployment::XPackage>
const & xPackage = bundle[
pos ];
503 Reference<task::XAbortChannel> xSubAbortChannel(
504 xPackage->createAbortChannel() );
505 AbortChannel::Chain chain( abortChannel, xSubAbortChannel );
506 beans::Optional< beans::Ambiguous<sal_Bool> >
option(
507 xPackage->isRegistered( xSubAbortChannel, xCmdEnv ) );
515 beans::Ambiguous<sal_Bool>
const & status =
option.Value;
519 if (reg !=
bool(status.Value)) {
534 return beans::Optional< beans::Ambiguous<sal_Bool> >(
535 present, beans::Ambiguous<sal_Bool>(reg, ambig) );
538OUString BackendImpl::PackageImpl::getTextFromURL(
539 const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv,
540 const OUString& licenseUrl)
547 return OUString(
reinterpret_cast<char const *
>(
548 seq.data()), seq.size(), RTL_TEXTENCODING_UTF8);
550 catch (
const css::uno::Exception&)
552 Any exc( ::cppu::getCaughtException() );
553 throw css::deployment::DeploymentException(
554 "Could not read file " + licenseUrl,
nullptr, exc);
564bool BackendImpl::PackageImpl::checkPlatform(
565 css::uno::Reference< css::ucb::XCommandEnvironment >
const & environment)
569 Sequence<OUString> platforms(info.getSupportedPlatforms());
578 "unsupported platform");
580 css::deployment::PlatformException(
581 msg,
static_cast<OWeakObject *
>(
this),
this));
584 environment,
nullptr,
nullptr))
586 throw css::deployment::DeploymentException(
587 msg,
static_cast<OWeakObject *
>(
this), e);
594bool BackendImpl::PackageImpl::checkDependencies(
595 css::uno::Reference< css::ucb::XCommandEnvironment >
const & environment,
596 DescriptionInfoset
const & description)
598 css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > >
601 if (!unsatisfied.hasElements()) {
605 "unsatisfied dependencies");
607 css::deployment::DependencyException(
608 msg,
static_cast<OWeakObject *
>(
this), unsatisfied));
611 environment,
nullptr,
nullptr))
613 throw css::deployment::DeploymentException(
614 msg,
static_cast<OWeakObject *
>(
this), e);
620bool BackendImpl::PackageImpl::checkLicense(
621 css::uno::Reference< css::ucb::XCommandEnvironment >
const & xCmdEnv,
622 DescriptionInfoset
const & info,
bool alreadyInstalled)
626 ::std::optional<SimpleLicenseAttributes> simplLicAttr
627 = info.getSimpleLicenseAttributes();
630 OUString sLic = info.getLocalizedLicenseURL();
635 throw css::deployment::DeploymentException(
636 "Could not obtain path to license. Possible error in description.xml",
nullptr,
Any());
638 OUString sLicense = getTextFromURL(xCmdEnv, sHref);
641 if ( simplLicAttr->acceptBy !=
"user" && simplLicAttr->acceptBy !=
"admin")
642 throw css::deployment::DeploymentException(
643 "Could not obtain attribute simple-license@accept-by or it has no valid value",
nullptr,
Any());
655 if ( !(alreadyInstalled && simplLicAttr->suppressOnUpdate))
657 css::deployment::LicenseException licExc(
658 OUString(),
nullptr, getDisplayName(), sLicense,
659 simplLicAttr->acceptBy);
660 bool approve =
false;
664 throw css::deployment::DeploymentException(
665 "Could not interact with user.",
nullptr,
Any());
670 }
catch (
const css::ucb::CommandFailedException&) {
672 }
catch (
const css::ucb::CommandAbortedException&) {
674 }
catch (
const css::deployment::DeploymentException&) {
676 }
catch (
const css::uno::RuntimeException&) {
678 }
catch (
const css::uno::Exception&) {
680 throw css::deployment::DeploymentException(
"Unexpected exception",
nullptr, anyExc);
684::sal_Int32 BackendImpl::PackageImpl::checkPrerequisites(
685 const css::uno::Reference< css::task::XAbortChannel >&,
686 const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv,
690 throw deployment::ExtensionRemovedException();
692 if (!info.hasDescription())
698 if (!checkPlatform(xCmdEnv))
699 return deployment::Prerequisites::PLATFORM |
700 deployment::Prerequisites::LICENSE;
701 else if(!checkDependencies(xCmdEnv, info))
702 return deployment::Prerequisites::DEPENDENCIES |
703 deployment::Prerequisites::LICENSE;
704 else if(!checkLicense(xCmdEnv, info, alreadyInstalled))
705 return deployment::Prerequisites::LICENSE;
710sal_Bool BackendImpl::PackageImpl::checkDependencies(
711 const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv )
714 throw deployment::ExtensionRemovedException();
716 if (!info.hasDescription())
719 return checkDependencies(xCmdEnv, info);
731 return beans::Optional<OUString>(
735OUString BackendImpl::PackageImpl::getVersion()
738 throw deployment::ExtensionRemovedException();
742Sequence<OUString> BackendImpl::PackageImpl::getUpdateInformationURLs()
745 throw deployment::ExtensionRemovedException();
749beans::StringPair BackendImpl::PackageImpl::getPublisherInfo()
752 throw deployment::ExtensionRemovedException();
754 beans::StringPair aStrPair( aInfo.first, aInfo.second );
762 throw deployment::ExtensionRemovedException();
767 if ( !aIconURL.isEmpty() )
775 "URL", aFullIconURL) };
776 xGraphic = xGraphProvider->queryGraphic( aMediaProps );
783void BackendImpl::PackageImpl::processPackage_(
784 ::osl::ResettableMutexGuard &,
785 bool doRegisterPackage,
788 Reference<ucb::XCommandEnvironment>
const & xCmdEnv )
790 const Sequence< Reference<deployment::XPackage> > bundle(
791 getBundle( abortChannel, xCmdEnv ) );
793 if (doRegisterPackage)
795 ExtensionBackendDb::Data data;
796 const sal_Int32 len = bundle.getLength();
797 for ( sal_Int32 pos = 0;
pos < len; ++
pos )
799 checkAborted(abortChannel);
800 Reference<deployment::XPackage>
const & xPackage = bundle[
pos ];
801 Reference<task::XAbortChannel> xSubAbortChannel(
802 xPackage->createAbortChannel() );
803 AbortChannel::Chain chain( abortChannel, xSubAbortChannel );
805 xPackage->registerPackage( startup, xSubAbortChannel, xCmdEnv );
807 catch (
const Exception &)
811 Any exc( ::cppu::getCaughtException() );
813 bool approve =
false, abort =
false;
815 Any( lang::WrappedTargetException(
816 "bundle item registration error!",
817 static_cast<OWeakObject *
>(
this), exc ) ),
819 &approve, &abort )) {
820 OSL_ASSERT( !approve && !abort );
826 ::cppu::throwException(exc);
828 if (approve && !abort)
832 ProgressLevel progress( xCmdEnv,
"rollback..." );
837 bundle[
pos ]->revokePackage(
838 startup, xSubAbortChannel, xCmdEnv );
840 catch (
const Exception &)
846 progress.update(
"rollback finished." );
849 deployment::DeploymentException dpExc;
851 throw ucb::CommandFailedException(
852 dpExc.Message, dpExc.Context, dpExc.Cause );
856 ::cppu::throwException(exc);
859 data.items.emplace_back(xPackage->getURL(),
860 xPackage->getPackageType()->getMediaType());
862 getMyBackend()->addDataToDb(getURL(), data);
867 for ( sal_Int32 pos = bundle.getLength(); pos--; )
869 checkAborted(abortChannel);
870 Reference<deployment::XPackage>
const & xPackage = bundle[
pos ];
871 Reference<task::XAbortChannel> xSubAbortChannel(
872 xPackage->createAbortChannel() );
873 AbortChannel::Chain chain( abortChannel, xSubAbortChannel );
875 bundle[
pos ]->revokePackage(
876 startup, xSubAbortChannel, xCmdEnv );
881 catch (
const ucb::CommandAbortedException &) {
884 catch (
const Exception &) {
886 Any exc( ::cppu::getCaughtException() );
888 bool approve =
false, abort =
false;
890 Any( lang::WrappedTargetException(
891 "bundle item revocation error!",
892 static_cast<OWeakObject *
>(
this), exc ) ),
894 &approve, &abort )) {
895 OSL_ASSERT( !approve && !abort );
901 ::cppu::throwException(exc);
907 getMyBackend()->revokeEntryFromDb(getURL());
912OUString BackendImpl::PackageImpl::getDescription()
915 throw deployment::ExtensionRemovedException();
918 OUString sDescription;
919 if (!sRelativeURL.isEmpty())
925 sDescription = getTextFromURL( css::uno::Reference< css::ucb::XCommandEnvironment >(), sURL );
927 catch (
const css::deployment::DeploymentException& )
933 if (!sDescription.isEmpty())
939OUString BackendImpl::PackageImpl::getLicenseText()
942 throw deployment::ExtensionRemovedException();
947 ::std::optional< SimpleLicenseAttributes > aSimplLicAttr = aInfo.getSimpleLicenseAttributes();
950 OUString aLicenseURL = aInfo.getLocalizedLicenseURL();
952 if ( !aLicenseURL.isEmpty() )
955 sLicense = getTextFromURL( Reference< ucb::XCommandEnvironment >(), aFullURL);
963void BackendImpl::PackageImpl::exportTo(
964 OUString
const & destFolderURL, OUString
const & newTitle,
965 sal_Int32 nameClashAction, Reference<ucb::XCommandEnvironment>
const & xCmdEnv )
968 throw deployment::ExtensionRemovedException();
972 OUString title(newTitle);
974 sourceContent.getPropertyValue(
"Title" ) >>= title;
975 OUString destURL(
makeURL( destFolderURL, ::rtl::Uri::encode(
976 title, rtl_UriCharClassPchar,
977 rtl_UriEncodeIgnoreEscapes,
978 RTL_TEXTENCODING_UTF8 ) ) );
980 if (nameClashAction == ucb::NameClash::ASK)
983 nullptr, destURL, xCmdEnv,
false )) {
984 bool replace =
false, abort =
false;
986 Any( ucb::NameClashResolveRequest(
987 "file already exists: " + title,
988 static_cast<OWeakObject *
>(
this),
989 task::InteractionClassification_QUERY,
990 destFolderURL, title, OUString() ) ),
992 &replace, &abort ) || !replace) {
997 else if (nameClashAction != ucb::NameClash::OVERWRITE) {
998 throw ucb::CommandFailedException(
"unsupported nameClashAction!",
999 static_cast<OWeakObject *
>(
this),
Any() );
1003 OUString destFolder =
1004 "vnd.sun.star.zip://" +
1005 ::rtl::Uri::encode( destURL,
1006 rtl_UriCharClassRegName,
1007 rtl_UriEncodeIgnoreEscapes,
1008 RTL_TEXTENCODING_UTF8 ) +
1015 Reference<sdbc::XResultSet> xResultSet(
1016 sourceContent.createCursor( Sequence<OUString>() ) );
1017 ProgressLevel progress( xCmdEnv, OUString() );
1018 while (xResultSet->next())
1021 Reference<ucb::XContentAccess>(
1022 xResultSet, UNO_QUERY_THROW )->queryContent(),
1024 destFolderContent.transferContent(
1026 OUString(), ucb::NameClash::OVERWRITE );
1027 progress.update(
Any() );
1034 makeURL( destFolderContent.getURL(),
"META-INF" ),
1044 Sequence< Reference<deployment::XPackage> > bundle;
1046 bundle = getBundle( Reference<task::XAbortChannel>(), xCmdEnv );
1049 catch (
const deployment::DeploymentException &) {
1052 catch (
const lang::IllegalArgumentException &) {
1056 std::vector< Sequence<beans::PropertyValue> > manifest;
1057 manifest.reserve( bundle.getLength() );
1059 Reference<deployment::XPackage>
const *pbundle = bundle.getConstArray();
1060 static constexpr OUStringLiteral strMediaType( u
"MediaType" );
1061 static constexpr OUStringLiteral strFullPath( u
"FullPath" );
1062 static constexpr OUStringLiteral strIsFolder( u
"IsFolder" );
1063 for ( sal_Int32 pos = bundle.getLength(); pos--; )
1065 Reference<deployment::XPackage>
const & xPackage = pbundle[
pos ];
1067 OSL_ASSERT(
url_.getLength() >= baseURLlen );
1069 if (
url_.getLength() > baseURLlen)
1070 fullPath =
url_.copy( baseURLlen + 1 );
1075 Sequence<beans::PropertyValue> attribs( 2 );
1076 beans::PropertyValue * pattribs = attribs.getArray();
1077 pattribs[ 0 ].Name = strFullPath;
1078 pattribs[ 0 ].Value <<= fullPath;
1079 pattribs[ 1 ].Name = strMediaType;
1080 const Reference<deployment::XPackageTypeInfo> xPackageType(
1081 xPackage->getPackageType() );
1083 OSL_ASSERT( xPackageType.is() );
1084 if (xPackageType.is())
1085 mediaType = xPackageType->getMediaType();
1087 mediaType =
"unknown";
1088 pattribs[ 1 ].Value <<= mediaType;
1089 manifest.push_back( attribs );
1093 Reference<XComponentContext>
xContext(
1095 Reference<packages::manifest::XManifestWriter> xManifestWriter =
1098 xManifestWriter->writeManifestSequence(
1105 manifestContent.writeStream(
1106 Reference<io::XInputStream>( xPipe, UNO_QUERY_THROW ),
1111 bool bSuccess =
false;
1121 OSL_FAIL(
"### missing META-INF/manifest.xml file!" );
1127 OUString(), ucb::NameClash::OVERWRITE );
1130 catch (
const css::ucb::ContentCreationException &)
1137 static_cast<OWeakObject *
>(
this) );
1142 destFolderContent.executeCommand(
"flush",
Any() );
1144 catch (
const ucb::UnsupportedCommandException &) {
1149sal_Bool BackendImpl::PackageImpl::isBundle()
1155Sequence< Reference<deployment::XPackage> > BackendImpl::PackageImpl::getBundle(
1156 Reference<task::XAbortChannel>
const & xAbortChannel,
1157 Reference<ucb::XCommandEnvironment>
const & xCmdEnv )
1159 Sequence< Reference<deployment::XPackage> > * pBundle =
m_pBundle;
1160 if (pBundle ==
nullptr)
1162 t_packagevec bundle;
1165 bundle = getPackagesFromDb(xCmdEnv);
1179 mediaType =
"application/vnd.sun.star.basic-library";
1185 mediaType =
"application/vnd.sun.star.dialog-library";
1187 if (!mediaType.isEmpty()) {
1188 const Reference<deployment::XPackage> xPackage(
1189 bindBundleItem( getURL(), mediaType,
false, OUString(),
1192 bundle.push_back( xPackage );
1195 scanLegacyBundle( bundle, getURL(),
1196 AbortChannel::get(xAbortChannel), xCmdEnv );
1201 scanBundle( bundle, AbortChannel::get(xAbortChannel), xCmdEnv );
1208 catch (
const ucb::CommandFailedException &) {
1211 catch (
const ucb::CommandAbortedException &) {
1214 catch (
const deployment::DeploymentException &) {
1217 catch (
const Exception &) {
1218 Any exc( ::cppu::getCaughtException() );
1219 throw deployment::DeploymentException(
1220 "error scanning bundle: " + getURL(),
1221 static_cast<OWeakObject *
>(
this), exc );
1226 Sequence< Reference<deployment::XPackage> > ret( bundle.size() );
1227 Reference<deployment::XPackage> * pret = ret.getArray();
1228 sal_Int32 lower_end = 0;
1229 sal_Int32 upper_end = ret.getLength();
1230 for (
auto const& elem : bundle)
1232 const Reference<deployment::XPackageTypeInfo> xPackageType(
1233 elem->getPackageType() );
1234 OSL_ASSERT( xPackageType.is() );
1235 if (xPackageType.is())
1237 const OUString mediaType( xPackageType->getMediaType() );
1238 OUString
type, subType;
1241 type.equalsIgnoreAsciiCase(
"application") &&
1242 (subType.equalsIgnoreAsciiCase(
"vnd.sun.star.uno-component") ||
1243 subType.equalsIgnoreAsciiCase(
"vnd.sun.star.configuration-data")))
1246 pret[ upper_end ] = elem;
1250 pret[ lower_end ] = elem;
1253 OSL_ASSERT( lower_end == upper_end );
1255 const ::osl::MutexGuard guard( m_aMutex );
1257 if (pBundle ==
nullptr) {
1260 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
1265 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
1270bool isBundle_( std::u16string_view mediaType )
1273 return !mediaType.empty() &&
1279Reference<deployment::XPackage> BackendImpl::PackageImpl::bindBundleItem(
1280 OUString
const & url, OUString
const & mediaType,
1281 bool bRemoved, OUString
const & identifier,
1282 Reference<ucb::XCommandEnvironment>
const & xCmdEnv,
1283 bool notifyDetectionError )
1286 if (isBundle_(mediaType))
1287 return Reference<deployment::XPackage>();
1289 Reference<deployment::XPackage>xPackage;
1293 url, mediaType, bRemoved, identifier, xCmdEnv ) );
1294 OSL_ASSERT( xPackage.is() );
1295 }
catch (css::lang::IllegalArgumentException & e) {
1297 throw css::lang::WrappedTargetException(
1298 "wrapped: " + e.Message, e.Context, exc);
1304 catch (
const ucb::CommandFailedException &) {
1307 catch (
const Exception &) {
1308 const Any exc( ::cppu::getCaughtException() );
1309 if (notifyDetectionError ||
1313 Any( lang::WrappedTargetException(
"bundle item error!",
1314 static_cast<OWeakObject *
>(
this), exc ) ),
1319 if (xPackage.is()) {
1320 const Reference<deployment::XPackageTypeInfo> xPackageType(
1321 xPackage->getPackageType() );
1322 OSL_ASSERT( xPackageType.is() );
1324 if (xPackageType.is() && isBundle_( xPackageType->getMediaType() ))
1331void BackendImpl::PackageImpl::scanBundle(
1332 t_packagevec & bundle,
1334 Reference<ucb::XCommandEnvironment>
const & xCmdEnv )
1341 &manifestContent, mfUrl, xCmdEnv,
false ))
1344 "desktop.deployment",
1345 "cannot create UCB Content for <" << mfUrl <<
">" );
1351 const std::vector< OUString > officeFallbacks( officeLocale.
getFallbackStrings(
true));
1352 const size_t nPenaltyMax = std::numeric_limits<size_t>::max();
1353 size_t descrPenalty = nPenaltyMax;
1356 const Reference<XComponentContext>
xContext(
1358 Reference<packages::manifest::XManifestReader> xManifestReader =
1360 const Sequence< Sequence<beans::PropertyValue> > manifestSeq(
1361 xManifestReader->readManifestSequence( manifestContent.
openStream() ) );
1362 const OUString packageRootURL( getURL() );
1363 for ( sal_Int32 pos = manifestSeq.getLength(); pos--; )
1365 OUString fullPath, mediaType;
1366 Sequence<beans::PropertyValue>
const & attribs = manifestSeq[
pos ];
1367 for ( sal_Int32 i = attribs.getLength(); i--; )
1369 if (!(fullPath.isEmpty() || mediaType.isEmpty()))
1371 if ( attribs[i].Name ==
"FullPath" )
1372 attribs[
i].Value >>= fullPath;
1373 else if ( attribs[i].Name ==
"MediaType" )
1374 attribs[
i].Value >>= mediaType;
1377 if ( fullPath.isEmpty() || mediaType.isEmpty() || mediaType ==
"text/xml" )
1380 OUString
type, subType;
1386 auto const iter = params.find(
"platform");
1387 if (iter != params.end() && !
platform_fits(iter->second.m_sValue))
1390 const OUString url(
makeURL( packageRootURL, fullPath ) );
1393 if (
type.equalsIgnoreAsciiCase(
"application") &&
1394 subType.equalsIgnoreAsciiCase(
"vnd.sun.star.package-bundle-description"))
1397 auto const iter = params.find(
"locale");
1398 if (iter == params.end())
1400 if (descrFile.isEmpty())
1406 if (officeLocale.
getLanguage() == descrTag.getLanguage())
1408 size_t nPenalty = nPenaltyMax;
1409 const std::vector< OUString > descrFallbacks( descrTag.getFallbackStrings(
true));
1410 for (
size_t o=0; o < officeFallbacks.size() && nPenalty == nPenaltyMax; ++o)
1412 for (
size_t d=0;
d < descrFallbacks.size() && nPenalty == nPenaltyMax; ++
d)
1414 if (officeFallbacks[o] == descrFallbacks[d])
1419 nPenalty = o * 1000 +
d;
1420 if (descrPenalty > nPenalty)
1422 descrPenalty = nPenalty;
1436 checkAborted( abortChannel );
1441 if (std::none_of(bundle.begin(), bundle.end(), XPackage_eq(url)))
1443 const Reference<deployment::XPackage> xPackage(
1444 bindBundleItem( url, mediaType,
false, OUString(), xCmdEnv ) );
1446 bundle.push_back( xPackage );
1450 SAL_WARN(
"desktop.deployment",
"manifest.xml contains a duplicate entry (from " << url <<
")");
1454 if (descrFile.isEmpty())
1463 std::vector<sal_Int8>
bytes(
readFile( descrFileContent ) );
1465 if ( !
bytes.empty() )
1467 buf.append( OUString(
reinterpret_cast<char const *
>(
1469 bytes.size(), RTL_TEXTENCODING_UTF8 ) );
1473 buf.append( Package::getDescription() );
1479void BackendImpl::PackageImpl::scanLegacyBundle(
1480 t_packagevec & bundle,
1481 OUString
const & url,
1483 Reference<ucb::XCommandEnvironment>
const & xCmdEnv,
1484 bool skip_registration )
1490 const OUString title( StrTitle::getTitle( ucbContent ) );
1491 if (title.endsWithIgnoreAsciiCase(
".plt" ) &&
1492 !
platform_fits( title.subView( 0, title.getLength() - 4 ) )) {
1495 if (title.endsWithIgnoreAsciiCase(
"skip_registration") )
1496 skip_registration =
true;
1498 Sequence<OUString> ar { OUString(
"Title"), OUString(
"IsFolder") };
1499 Reference<sdbc::XResultSet> xResultSet( ucbContent.
createCursor( ar ) );
1500 while (xResultSet->next())
1502 checkAborted( abortChannel );
1504 const Reference<sdbc::XRow> xRow( xResultSet, UNO_QUERY_THROW );
1505 const OUString title_enc( ::rtl::Uri::encode(
1506 xRow->getString( 1 ),
1507 rtl_UriCharClassPchar,
1508 rtl_UriEncodeIgnoreEscapes,
1509 RTL_TEXTENCODING_UTF8 ) );
1510 const OUString path(
makeURL( url, title_enc ) );
1513 const Reference<deployment::XPackage> xPackage(
1514 bindBundleItem( path, OUString() ,
false, OUString(),
1516 if (xPackage.is()) {
1517 const Reference<deployment::XPackageTypeInfo> xPackageType(
1518 xPackage->getPackageType() );
1519 OSL_ASSERT( xPackageType.is() );
1520 if (xPackageType.is())
1521 mediaType = xPackageType->getMediaType();
1523 if (skip_registration &&
1525 mediaType.matchIgnoreAsciiCase(
"application/vnd.sun.star.uno-component"))
1528 bundle.push_back( xPackage );
1531 if (mediaType.isEmpty() ||
1533 mediaType.matchIgnoreAsciiCase(
"application/vnd.sun.star.basic-library") ||
1534 mediaType.matchIgnoreAsciiCase(
"application/vnd.sun.star.dialog-library"))
1536 if (xRow->getBoolean( 2 )) {
1538 bundle, path, abortChannel, xCmdEnv, skip_registration );
1544OUString BackendImpl::PackageImpl::getDisplayName()
1547 throw deployment::ExtensionRemovedException();
1550 if (
sName.isEmpty())
1551 return m_displayName;
1556std::vector<Reference<deployment::XPackage> >
1557BackendImpl::PackageImpl::getPackagesFromDb(
1558 Reference<ucb::XCommandEnvironment>
const & xCmdEnv)
1560 std::vector<Reference<deployment::XPackage> > retVector;
1562 for (
auto const& item :
m_dbData.items)
1564 Reference<deployment::XPackage> xExtension =
1565 bindBundleItem(item.first, item.second,
true, m_identifier, xCmdEnv);
1566 OSL_ASSERT(xExtension.is());
1567 if (xExtension.is())
1568 retVector.push_back(xExtension);
1577Reference<deployment::XPackageRegistry>
create(
1578 Reference<deployment::XPackageRegistry>
const & xRootRegistry,
1579 OUString
const & context, OUString
const & cachePath,
1580 Reference<XComponentContext>
const & xComponentContext )
1582 Sequence<Any>
args(cachePath.isEmpty() ? 1 : 3 );
1583 auto pArgs =
args.getArray();
1584 pArgs[ 0 ] <<= context;
1585 if (!cachePath.isEmpty()) {
1586 pArgs[ 1 ] <<= cachePath;
1587 pArgs[ 2 ] <<=
false;
1589 return new BackendImpl(
args, xComponentContext, xRootRegistry );
static bool parse(OUString const &rMediaType, OUString &rType, OUString &rSubType, INetContentTypeParameterList *pParameters=nullptr)
OUString getLanguage() const
::std::vector< OUString > getFallbackStrings(bool bIncludeFullBcp47) const
css::uno::Type const & get()
OUString getLocalizedDisplayName() const
returns the localized display name of the extensions.
css::uno::Sequence< OUString > getUpdateInformationUrls() const
Return the update information URLs.
std::pair< OUString, OUString > getLocalizedPublisherNameAndURL() const
Returns the localized publisher name and the corresponding URL.
OUString getVersion() const
Return the textual version representation.
OUString getIconURL(bool bHighContrast) const
Returns the URL for the icon image.
const OUString & getURL() const
void transferContent(const Content &rSourceContent, InsertOperation eOperation, const OUString &rTitle, const sal_Int32 nNameClashAction, const OUString &rMimeType=OUString(), bool bMajorVersion=false, const OUString &rCommentVersion=OUString(), OUString *pResultURL=nullptr, const OUString &rDocumentId=OUString()) const
css::uno::Any getPropertyValue(const OUString &rPropertyName)
css::uno::Reference< css::io::XInputStream > openStream()
css::uno::Reference< css::sdbc::XResultSet > createCursor(const css::uno::Sequence< OUString > &rPropertyNames, ResultSetInclude eMode=INCLUDE_FOLDERS_AND_DOCUMENTS)
#define TOOLS_WARN_EXCEPTION(area, stream)
OUString DpResId(TranslateId aId)
ExtensionBackendDb::Data m_dbData
const Reference< deployment::XPackageTypeInfo > m_xBundleTypeInfo
std::unique_ptr< ExtensionBackendDb > m_backendDb
Sequence< Reference< deployment::XPackageTypeInfo > > m_typeInfos
const bool m_legacyBundle
const Reference< deployment::XPackageTypeInfo > m_xLegacyBundleTypeInfo
Reference< deployment::XPackageRegistry > m_xRootRegistry
OUString m_oldDescription
contains the old tooltip description for the Extension Manager GUI in OOo v.2.x We keep it for backwa...
Sequence< Reference< deployment::XPackage > > * m_pBundle
Sequence< Reference< deployment::XPackage > > m_bundle
std::unordered_map< OString, INetContentTypeParameter > INetContentTypeParameterList
static uno::Reference< css::uno::XComponentContext > xContext
#define SAL_WARN(area, stream)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Reference< XComponentContext > getComponentContext(Reference< XMultiServiceFactory > const &factory)
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
Any SAL_CALL getCaughtException()
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > check(dp_misc::DescriptionInfoset const &infoset)
Check for unsatisfied dependencies.
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)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool interactContinuation(css::uno::Any const &request, css::uno::Type const &continuation, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv, bool *pcont, bool *pabort)
OUString expandUnoRcUrl(OUString const &url)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC const LanguageTag & getOfficeLanguageTag()
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString generateIdentifier(::std::optional< OUString > const &optional, std::u16string_view fileName)
Generates an identifier from an optional identifier.
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool erase_path(OUString const &url, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv, bool throw_exc=true)
void try_dispose(css::uno::Reference< css::uno::XInterface > const &x)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool create_ucb_content(::ucbhelper::Content *ucb_content, OUString const &url, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv, bool throw_exc=true)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC std::vector< sal_Int8 > readFile(::ucbhelper::Content &ucb_content)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool platform_fits(std::u16string_view platform_string)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool hasValidPlatform(css::uno::Sequence< OUString > const &platformStrings)
determines if the current platform corresponds to one of the platform strings.
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC DescriptionInfoset getDescriptionInfoset(std::u16string_view sExtensionFolderURL)
creates a DescriptionInfoset object.
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString getIdentifier(css::uno::Reference< css::deployment::XPackage > const &package)
Gets the identifier of a package.
Reference< deployment::XPackageRegistry > create(Reference< deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, Reference< XComponentContext > const &xComponentContext)
constexpr OUStringLiteral BACKEND_SERVICE_NAME
bool matchIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2, sal_Int32 fromIndex=0)
std::vector< sal_uInt8 > bytes
::boost::spirit::classic::rule< ScannerT > identifier