1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
22 #include <string_view>
25 #include <dp_backend.h>
27 #include <dp_interact.h>
28 #include <com/sun/star/lang/IllegalArgumentException.hpp>
29 #include <osl/file.hxx>
30 #include <ucbhelper/content.hxx>
31 #include <svl/inettype.hxx>
32 #include "dp_executablebackenddb.hxx"
33 #include <cppuhelper/supportsservice.hxx>
35 using namespace ::com::sun::star
;
36 using namespace ::com::sun::star::uno
;
37 using namespace ::com::sun::star::ucb
;
38 using namespace dp_misc
;
40 namespace dp_registry::backend::executable
{
43 class BackendImpl
: public ::dp_registry::backend::PackageRegistryBackend
45 class ExecutablePackageImpl
: public ::dp_registry::backend::Package
47 BackendImpl
* getMyBackend() const;
50 virtual beans::Optional
< beans::Ambiguous
<sal_Bool
> > isRegistered_(
51 ::osl::ResettableMutexGuard
& guard
,
52 ::rtl::Reference
<dp_misc::AbortChannel
> const & abortChannel
,
53 Reference
<XCommandEnvironment
> const & xCmdEnv
) override
;
54 virtual void processPackage_(
55 ::osl::ResettableMutexGuard
& guard
,
58 ::rtl::Reference
<dp_misc::AbortChannel
> const & abortChannel
,
59 Reference
<XCommandEnvironment
> const & xCmdEnv
) override
;
61 bool getFileAttributes(sal_uInt64
& out_Attributes
);
62 bool isUrlTargetInExtension() const;
65 ExecutablePackageImpl(
66 ::rtl::Reference
<PackageRegistryBackend
> const & myBackend
,
67 OUString
const & url
, OUString
const & name
,
68 Reference
<deployment::XPackageTypeInfo
> const & xPackageType
,
69 bool bRemoved
, OUString
const & identifier
)
70 : Package( myBackend
, url
, name
, name
/* display-name */,
71 xPackageType
, bRemoved
, identifier
)
74 friend class ExecutablePackageImpl
;
76 // PackageRegistryBackend
77 virtual Reference
<deployment::XPackage
> bindPackage_(
78 OUString
const & url
, OUString
const & mediaType
, bool bRemoved
,
79 OUString
const & identifier
, Reference
<XCommandEnvironment
> const & xCmdEnv
) override
;
81 void addDataToDb(OUString
const & url
);
82 bool hasActiveEntry(std::u16string_view url
);
83 void revokeEntryFromDb(std::u16string_view url
);
85 Reference
<deployment::XPackageTypeInfo
> m_xExecutableTypeInfo
;
86 std::unique_ptr
<ExecutableBackendDb
> m_backendDb
;
88 BackendImpl( Sequence
<Any
> const & args
,
89 Reference
<XComponentContext
> const & xComponentContext
);
92 virtual OUString SAL_CALL
getImplementationName() override
;
93 virtual sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
) override
;
94 virtual css::uno::Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
97 virtual Sequence
< Reference
<deployment::XPackageTypeInfo
> > SAL_CALL
98 getSupportedPackageTypes() override
;
99 virtual void SAL_CALL
packageRemoved(OUString
const & url
, OUString
const & mediaType
) override
;
104 BackendImpl::BackendImpl(
105 Sequence
<Any
> const & args
,
106 Reference
<XComponentContext
> const & xComponentContext
)
107 : PackageRegistryBackend( args
, xComponentContext
),
108 m_xExecutableTypeInfo(new Package::TypeInfo(
109 "application/vnd.sun.star.executable",
112 if (!transientMode())
114 OUString dbFile
= makeURL(getCachePath(), "backenddb.xml");
116 new ExecutableBackendDb(getComponentContext(), dbFile
));
121 OUString
BackendImpl::getImplementationName()
123 return "com.sun.star.comp.deployment.executable.PackageRegistryBackend";
126 sal_Bool
BackendImpl::supportsService( const OUString
& ServiceName
)
128 return cppu::supportsService(this, ServiceName
);
131 css::uno::Sequence
< OUString
> BackendImpl::getSupportedServiceNames()
133 return { BACKEND_SERVICE_NAME
};
136 void BackendImpl::addDataToDb(OUString
const & url
)
139 m_backendDb
->addEntry(url
);
142 void BackendImpl::revokeEntryFromDb(std::u16string_view url
)
145 m_backendDb
->revokeEntry(url
);
148 bool BackendImpl::hasActiveEntry(std::u16string_view url
)
151 return m_backendDb
->hasActiveEntry(url
);
157 Sequence
< Reference
<deployment::XPackageTypeInfo
> >
158 BackendImpl::getSupportedPackageTypes()
160 return Sequence
<Reference
<deployment::XPackageTypeInfo
> >(
161 & m_xExecutableTypeInfo
, 1);
164 void BackendImpl::packageRemoved(OUString
const & url
, OUString
const & /*mediaType*/)
167 m_backendDb
->removeEntry(url
);
170 // PackageRegistryBackend
171 Reference
<deployment::XPackage
> BackendImpl::bindPackage_(
172 OUString
const & url
, OUString
const & mediaType
, bool bRemoved
,
173 OUString
const & identifier
, Reference
<XCommandEnvironment
> const & xCmdEnv
)
175 if (mediaType
.isEmpty())
177 throw lang::IllegalArgumentException(
178 StrCannotDetectMediaType() + url
,
179 static_cast<OWeakObject
*>(this), static_cast<sal_Int16
>(-1) );
182 OUString type
, subType
;
183 INetContentTypeParameterList params
;
184 if (INetContentTypes::parse( mediaType
, type
, subType
, ¶ms
))
186 if (type
.equalsIgnoreAsciiCase("application"))
191 ::ucbhelper::Content
ucbContent(
192 url
, xCmdEnv
, getComponentContext() );
193 name
= StrTitle::getTitle( ucbContent
);
195 if (subType
.equalsIgnoreAsciiCase("vnd.sun.star.executable"))
197 return new BackendImpl::ExecutablePackageImpl(
198 this, url
, name
, m_xExecutableTypeInfo
, bRemoved
,
203 return Reference
<deployment::XPackage
>();
208 BackendImpl
* BackendImpl::ExecutablePackageImpl::getMyBackend() const
210 BackendImpl
* pBackend
= static_cast<BackendImpl
*>(m_myBackend
.get());
211 if (nullptr == pBackend
)
213 //May throw a DisposedException
215 //We should never get here...
216 throw RuntimeException( "Failed to get the BackendImpl",
217 static_cast<OWeakObject
*>(const_cast<ExecutablePackageImpl
*>(this)));
222 beans::Optional
< beans::Ambiguous
<sal_Bool
> >
223 BackendImpl::ExecutablePackageImpl::isRegistered_(
224 ::osl::ResettableMutexGuard
&,
225 ::rtl::Reference
<dp_misc::AbortChannel
> const &,
226 Reference
<XCommandEnvironment
> const & )
228 bool registered
= getMyBackend()->hasActiveEntry(getURL());
229 return beans::Optional
< beans::Ambiguous
<sal_Bool
> >(
230 true /* IsPresent */,
231 beans::Ambiguous
<sal_Bool
>(
232 registered
, false /* IsAmbiguous */ ) );
235 void BackendImpl::ExecutablePackageImpl::processPackage_(
236 ::osl::ResettableMutexGuard
&,
237 bool doRegisterPackage
,
239 ::rtl::Reference
<dp_misc::AbortChannel
> const & abortChannel
,
240 Reference
<XCommandEnvironment
> const & /*xCmdEnv*/ )
242 checkAborted(abortChannel
);
243 if (doRegisterPackage
)
245 if (!isUrlTargetInExtension())
250 sal_uInt64 attributes
= 0;
251 //Setting the executable attribute does not affect executables on Windows
252 if (getFileAttributes(attributes
))
254 if(getMyBackend()->m_context
== "user")
255 attributes
|= osl_File_Attribute_OwnExe
;
256 else if (getMyBackend()->m_context
== "shared")
257 attributes
|= (osl_File_Attribute_OwnExe
| osl_File_Attribute_GrpExe
258 | osl_File_Attribute_OthExe
);
259 else if (getMyBackend()->m_context
!= "bundled")
260 //Bundled extensions are required to be in the properly
261 //installed. That is an executable must have the right flags
264 //This won't have effect on Windows
265 osl::File::setAttributes(
266 dp_misc::expandUnoRcUrl(m_url
), attributes
);
268 getMyBackend()->addDataToDb(getURL());
272 getMyBackend()->revokeEntryFromDb(getURL());
276 //We currently cannot check if this XPackage represents a content of a particular extension
277 //But we can check if we are within $UNO_USER_PACKAGES_CACHE etc.
278 //Done for security reasons. For example an extension manifest could contain a path to
279 //an executable outside the extension.
280 bool BackendImpl::ExecutablePackageImpl::isUrlTargetInExtension() const
282 bool bSuccess
= false;
283 OUString sExtensionDir
;
284 if(getMyBackend()->m_context
== "user")
285 sExtensionDir
= dp_misc::expandUnoRcTerm("$UNO_USER_PACKAGES_CACHE");
286 else if (getMyBackend()->m_context
== "shared")
287 sExtensionDir
= dp_misc::expandUnoRcTerm("$UNO_SHARED_PACKAGES_CACHE");
288 else if (getMyBackend()->m_context
== "bundled")
289 sExtensionDir
= dp_misc::expandUnoRcTerm("$BUNDLED_EXTENSIONS");
292 //remove file ellipses
293 if (osl::File::E_None
== osl::File::getAbsoluteFileURL(OUString(), sExtensionDir
, sExtensionDir
))
296 if (osl::File::E_None
== osl::File::getAbsoluteFileURL(
297 OUString(), dp_misc::expandUnoRcUrl(m_url
), sFile
))
299 if (sFile
.match(sExtensionDir
))
306 bool BackendImpl::ExecutablePackageImpl::getFileAttributes(sal_uInt64
& out_Attributes
)
308 bool bSuccess
= false;
309 const OUString
url(dp_misc::expandUnoRcUrl(m_url
));
310 osl::DirectoryItem item
;
311 if (osl::FileBase::E_None
== osl::DirectoryItem::get(url
, item
))
313 osl::FileStatus
aStatus(osl_FileStatus_Mask_Attributes
);
314 if( osl::FileBase::E_None
== item
.getFileStatus(aStatus
))
316 out_Attributes
= aStatus
.getAttributes();
327 } // namespace dp_registry::backend::executable
329 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
330 com_sun_star_comp_deployment_executable_PackageRegistryBackend_get_implementation(
331 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const& args
)
333 return cppu::acquire(new dp_registry::backend::executable::BackendImpl(args
, context
));
336 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */