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 .
23 #include <dp_backend.h>
24 #include <dp_services.hxx>
26 #include <dp_interact.h>
27 #include <com/sun/star/lang/IllegalArgumentException.hpp>
28 #include <rtl/string.hxx>
29 #include <osl/file.hxx>
30 #include <ucbhelper/content.hxx>
31 #include <comphelper/servicedecl.hxx>
32 #include <svl/inettype.hxx>
33 #include "dp_executablebackenddb.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
{
42 namespace executable
{
45 class BackendImpl
: public ::dp_registry::backend::PackageRegistryBackend
47 class ExecutablePackageImpl
: public ::dp_registry::backend::Package
49 BackendImpl
* getMyBackend() const;
52 virtual beans::Optional
< beans::Ambiguous
<sal_Bool
> > isRegistered_(
53 ::osl::ResettableMutexGuard
& guard
,
54 ::rtl::Reference
<dp_misc::AbortChannel
> const & abortChannel
,
55 Reference
<XCommandEnvironment
> const & xCmdEnv
) override
;
56 virtual void processPackage_(
57 ::osl::ResettableMutexGuard
& guard
,
60 ::rtl::Reference
<dp_misc::AbortChannel
> const & abortChannel
,
61 Reference
<XCommandEnvironment
> const & xCmdEnv
) override
;
63 bool getFileAttributes(sal_uInt64
& out_Attributes
);
64 bool isUrlTargetInExtension() const;
67 ExecutablePackageImpl(
68 ::rtl::Reference
<PackageRegistryBackend
> const & myBackend
,
69 OUString
const & url
, OUString
const & name
,
70 Reference
<deployment::XPackageTypeInfo
> const & xPackageType
,
71 bool bRemoved
, OUString
const & identifier
)
72 : Package( myBackend
, url
, name
, name
/* display-name */,
73 xPackageType
, bRemoved
, identifier
)
76 friend class ExecutablePackageImpl
;
78 typedef std::unordered_map
< OUString
, Reference
<XInterface
> > t_string2object
;
80 // PackageRegistryBackend
81 virtual Reference
<deployment::XPackage
> bindPackage_(
82 OUString
const & url
, OUString
const & mediaType
, bool bRemoved
,
83 OUString
const & identifier
, Reference
<XCommandEnvironment
> const & xCmdEnv
) override
;
85 void addDataToDb(OUString
const & url
);
86 bool hasActiveEntry(OUString
const & url
);
87 void revokeEntryFromDb(OUString
const & url
);
89 Reference
<deployment::XPackageTypeInfo
> m_xExecutableTypeInfo
;
90 std::unique_ptr
<ExecutableBackendDb
> m_backendDb
;
92 BackendImpl( Sequence
<Any
> const & args
,
93 Reference
<XComponentContext
> const & xComponentContext
);
96 virtual Sequence
< Reference
<deployment::XPackageTypeInfo
> > SAL_CALL
97 getSupportedPackageTypes() override
;
98 virtual void SAL_CALL
packageRemoved(OUString
const & url
, OUString
const & mediaType
) override
;
103 BackendImpl::BackendImpl(
104 Sequence
<Any
> const & args
,
105 Reference
<XComponentContext
> const & xComponentContext
)
106 : PackageRegistryBackend( args
, xComponentContext
),
107 m_xExecutableTypeInfo(new Package::TypeInfo(
108 "application/vnd.sun.star.executable",
111 if (!transientMode())
113 OUString dbFile
= makeURL(getCachePath(), "backenddb.xml");
115 new ExecutableBackendDb(getComponentContext(), dbFile
));
119 void BackendImpl::addDataToDb(OUString
const & url
)
122 m_backendDb
->addEntry(url
);
125 void BackendImpl::revokeEntryFromDb(OUString
const & url
)
128 m_backendDb
->revokeEntry(url
);
131 bool BackendImpl::hasActiveEntry(OUString
const & url
)
134 return m_backendDb
->hasActiveEntry(url
);
140 Sequence
< Reference
<deployment::XPackageTypeInfo
> >
141 BackendImpl::getSupportedPackageTypes()
143 return Sequence
<Reference
<deployment::XPackageTypeInfo
> >(
144 & m_xExecutableTypeInfo
, 1);
147 void BackendImpl::packageRemoved(OUString
const & url
, OUString
const & /*mediaType*/)
150 m_backendDb
->removeEntry(url
);
153 // PackageRegistryBackend
154 Reference
<deployment::XPackage
> BackendImpl::bindPackage_(
155 OUString
const & url
, OUString
const & mediaType
, bool bRemoved
,
156 OUString
const & identifier
, Reference
<XCommandEnvironment
> const & xCmdEnv
)
158 if (mediaType
.isEmpty())
160 throw lang::IllegalArgumentException(
161 StrCannotDetectMediaType() + url
,
162 static_cast<OWeakObject
*>(this), static_cast<sal_Int16
>(-1) );
165 OUString type
, subType
;
166 INetContentTypeParameterList params
;
167 if (INetContentTypes::parse( mediaType
, type
, subType
, ¶ms
))
169 if (type
.equalsIgnoreAsciiCase("application"))
174 ::ucbhelper::Content
ucbContent(
175 url
, xCmdEnv
, getComponentContext() );
176 name
= StrTitle::getTitle( ucbContent
);
178 if (subType
.equalsIgnoreAsciiCase("vnd.sun.star.executable"))
180 return new BackendImpl::ExecutablePackageImpl(
181 this, url
, name
, m_xExecutableTypeInfo
, bRemoved
,
186 return Reference
<deployment::XPackage
>();
191 BackendImpl
* BackendImpl::ExecutablePackageImpl::getMyBackend() const
193 BackendImpl
* pBackend
= static_cast<BackendImpl
*>(m_myBackend
.get());
194 if (nullptr == pBackend
)
196 //May throw a DisposedException
198 //We should never get here...
199 throw RuntimeException( "Failed to get the BackendImpl",
200 static_cast<OWeakObject
*>(const_cast<ExecutablePackageImpl
*>(this)));
205 beans::Optional
< beans::Ambiguous
<sal_Bool
> >
206 BackendImpl::ExecutablePackageImpl::isRegistered_(
207 ::osl::ResettableMutexGuard
&,
208 ::rtl::Reference
<dp_misc::AbortChannel
> const &,
209 Reference
<XCommandEnvironment
> const & )
211 bool registered
= getMyBackend()->hasActiveEntry(getURL());
212 return beans::Optional
< beans::Ambiguous
<sal_Bool
> >(
213 true /* IsPresent */,
214 beans::Ambiguous
<sal_Bool
>(
215 registered
, false /* IsAmbiguous */ ) );
218 void BackendImpl::ExecutablePackageImpl::processPackage_(
219 ::osl::ResettableMutexGuard
&,
220 bool doRegisterPackage
,
222 ::rtl::Reference
<dp_misc::AbortChannel
> const & abortChannel
,
223 Reference
<XCommandEnvironment
> const & /*xCmdEnv*/ )
225 checkAborted(abortChannel
);
226 if (doRegisterPackage
)
228 if (!isUrlTargetInExtension())
233 sal_uInt64 attributes
= 0;
234 //Setting the executable attribute does not affect executables on Windows
235 if (getFileAttributes(attributes
))
237 if(getMyBackend()->m_context
== "user")
238 attributes
|= osl_File_Attribute_OwnExe
;
239 else if (getMyBackend()->m_context
== "shared")
240 attributes
|= (osl_File_Attribute_OwnExe
| osl_File_Attribute_GrpExe
241 | osl_File_Attribute_OthExe
);
242 else if (getMyBackend()->m_context
!= "bundled")
243 //Bundled extensions are required to be in the properly
244 //installed. That is an executable must have the right flags
247 //This won't have effect on Windows
248 osl::File::setAttributes(
249 dp_misc::expandUnoRcUrl(m_url
), attributes
);
251 getMyBackend()->addDataToDb(getURL());
255 getMyBackend()->revokeEntryFromDb(getURL());
259 //We currently cannot check if this XPackage represents a content of a particular extension
260 //But we can check if we are within $UNO_USER_PACKAGES_CACHE etc.
261 //Done for security reasons. For example an extension manifest could contain a path to
262 //an executable outside the extension.
263 bool BackendImpl::ExecutablePackageImpl::isUrlTargetInExtension() const
265 bool bSuccess
= false;
266 OUString sExtensionDir
;
267 if(getMyBackend()->m_context
== "user")
268 sExtensionDir
= dp_misc::expandUnoRcTerm("$UNO_USER_PACKAGES_CACHE");
269 else if (getMyBackend()->m_context
== "shared")
270 sExtensionDir
= dp_misc::expandUnoRcTerm("$UNO_SHARED_PACKAGES_CACHE");
271 else if (getMyBackend()->m_context
== "bundled")
272 sExtensionDir
= dp_misc::expandUnoRcTerm("$BUNDLED_EXTENSIONS");
275 //remove file ellipses
276 if (osl::File::E_None
== osl::File::getAbsoluteFileURL(OUString(), sExtensionDir
, sExtensionDir
))
279 if (osl::File::E_None
== osl::File::getAbsoluteFileURL(
280 OUString(), dp_misc::expandUnoRcUrl(m_url
), sFile
))
282 if (sFile
.match(sExtensionDir
))
289 bool BackendImpl::ExecutablePackageImpl::getFileAttributes(sal_uInt64
& out_Attributes
)
291 bool bSuccess
= false;
292 const OUString
url(dp_misc::expandUnoRcUrl(m_url
));
293 osl::DirectoryItem item
;
294 if (osl::FileBase::E_None
== osl::DirectoryItem::get(url
, item
))
296 osl::FileStatus
aStatus(osl_FileStatus_Mask_Attributes
);
297 if( osl::FileBase::E_None
== item
.getFileStatus(aStatus
))
299 out_Attributes
= aStatus
.getAttributes();
309 namespace sdecl
= comphelper::service_decl
;
310 sdecl::class_
<BackendImpl
, sdecl::with_args
<true> > serviceBI
;
311 sdecl::ServiceDecl
const serviceDecl(
313 "com.sun.star.comp.deployment.executable.PackageRegistryBackend",
314 BACKEND_SERVICE_NAME
);
316 } // namespace component
317 } // namespace backend
318 } // namespace dp_registry
321 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */