1*2722ceddSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*2722ceddSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*2722ceddSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*2722ceddSAndrew Rist  * distributed with this work for additional information
6*2722ceddSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*2722ceddSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*2722ceddSAndrew Rist  * "License"); you may not use this file except in compliance
9*2722ceddSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*2722ceddSAndrew Rist  *
11*2722ceddSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*2722ceddSAndrew Rist  *
13*2722ceddSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*2722ceddSAndrew Rist  * software distributed under the License is distributed on an
15*2722ceddSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*2722ceddSAndrew Rist  * KIND, either express or implied.  See the License for the
17*2722ceddSAndrew Rist  * specific language governing permissions and limitations
18*2722ceddSAndrew Rist  * under the License.
19*2722ceddSAndrew Rist  *
20*2722ceddSAndrew Rist  *************************************************************/
21*2722ceddSAndrew Rist 
22*2722ceddSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_desktop.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "dp_misc.h"
28cdf0e10cSrcweir #include "dp_backend.h"
29cdf0e10cSrcweir #include "dp_ucb.h"
30cdf0e10cSrcweir #include "dp_interact.h"
31cdf0e10cSrcweir #include "rtl/string.hxx"
32cdf0e10cSrcweir #include "osl/file.hxx"
33cdf0e10cSrcweir #include "ucbhelper/content.hxx"
34cdf0e10cSrcweir #include "comphelper/servicedecl.hxx"
35cdf0e10cSrcweir #include "svl/inettype.hxx"
36cdf0e10cSrcweir #include "cppuhelper/implbase1.hxx"
37cdf0e10cSrcweir #include "dp_executablebackenddb.hxx"
38cdf0e10cSrcweir 
39cdf0e10cSrcweir using namespace ::com::sun::star;
40cdf0e10cSrcweir using namespace ::com::sun::star::uno;
41cdf0e10cSrcweir using namespace ::com::sun::star::ucb;
42cdf0e10cSrcweir using namespace dp_misc;
43cdf0e10cSrcweir using ::rtl::OUString;
44cdf0e10cSrcweir 
45cdf0e10cSrcweir namespace dp_registry {
46cdf0e10cSrcweir namespace backend {
47cdf0e10cSrcweir namespace executable {
48cdf0e10cSrcweir namespace {
49cdf0e10cSrcweir 
50cdf0e10cSrcweir class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend
51cdf0e10cSrcweir {
52cdf0e10cSrcweir     class ExecutablePackageImpl : public ::dp_registry::backend::Package
53cdf0e10cSrcweir     {
54cdf0e10cSrcweir         BackendImpl * getMyBackend() const;
55cdf0e10cSrcweir 
56cdf0e10cSrcweir         // Package
57cdf0e10cSrcweir         virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
58cdf0e10cSrcweir             ::osl::ResettableMutexGuard & guard,
59cdf0e10cSrcweir             ::rtl::Reference<dp_misc::AbortChannel> const & abortChannel,
60cdf0e10cSrcweir             Reference<XCommandEnvironment> const & xCmdEnv );
61cdf0e10cSrcweir         virtual void processPackage_(
62cdf0e10cSrcweir             ::osl::ResettableMutexGuard & guard,
63cdf0e10cSrcweir             bool registerPackage,
64cdf0e10cSrcweir             bool startup,
65cdf0e10cSrcweir             ::rtl::Reference<dp_misc::AbortChannel> const & abortChannel,
66cdf0e10cSrcweir             Reference<XCommandEnvironment> const & xCmdEnv );
67cdf0e10cSrcweir 
68cdf0e10cSrcweir         bool getFileAttributes(sal_uInt64& out_Attributes);
69cdf0e10cSrcweir         bool isUrlTargetInExtension();
70cdf0e10cSrcweir 
71cdf0e10cSrcweir     public:
ExecutablePackageImpl(::rtl::Reference<PackageRegistryBackend> const & myBackend,OUString const & url,OUString const & name,Reference<deployment::XPackageTypeInfo> const & xPackageType,bool bRemoved,OUString const & identifier)72cdf0e10cSrcweir         inline ExecutablePackageImpl(
73cdf0e10cSrcweir             ::rtl::Reference<PackageRegistryBackend> const & myBackend,
74cdf0e10cSrcweir             OUString const & url, OUString const & name,
75cdf0e10cSrcweir             Reference<deployment::XPackageTypeInfo> const & xPackageType,
76cdf0e10cSrcweir             bool bRemoved, OUString const & identifier)
77cdf0e10cSrcweir             : Package( myBackend, url, name, name /* display-name */,
78cdf0e10cSrcweir                        xPackageType, bRemoved, identifier)
79cdf0e10cSrcweir             {}
80cdf0e10cSrcweir     };
81cdf0e10cSrcweir     friend class ExecutablePackageImpl;
82cdf0e10cSrcweir 
83cdf0e10cSrcweir     typedef ::std::hash_map< OUString, Reference<XInterface>,
84cdf0e10cSrcweir                              ::rtl::OUStringHash > t_string2object;
85cdf0e10cSrcweir 
86cdf0e10cSrcweir     // PackageRegistryBackend
87cdf0e10cSrcweir     virtual Reference<deployment::XPackage> bindPackage_(
88cdf0e10cSrcweir         OUString const & url, OUString const & mediaType, sal_Bool bRemoved,
89cdf0e10cSrcweir         OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv );
90cdf0e10cSrcweir 
91cdf0e10cSrcweir     void addDataToDb(OUString const & url);
92cdf0e10cSrcweir     bool hasActiveEntry(OUString const & url);
93cdf0e10cSrcweir     void revokeEntryFromDb(OUString const & url);
94cdf0e10cSrcweir 
95cdf0e10cSrcweir     Reference<deployment::XPackageTypeInfo> m_xExecutableTypeInfo;
96cdf0e10cSrcweir     std::auto_ptr<ExecutableBackendDb> m_backendDb;
97cdf0e10cSrcweir public:
98cdf0e10cSrcweir     BackendImpl( Sequence<Any> const & args,
99cdf0e10cSrcweir                  Reference<XComponentContext> const & xComponentContext );
100cdf0e10cSrcweir 
101cdf0e10cSrcweir     // XPackageRegistry
102cdf0e10cSrcweir     virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
103cdf0e10cSrcweir     getSupportedPackageTypes() throw (RuntimeException);
104cdf0e10cSrcweir     virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType)
105cdf0e10cSrcweir         throw (deployment::DeploymentException,
106cdf0e10cSrcweir                uno::RuntimeException);
107cdf0e10cSrcweir 
108cdf0e10cSrcweir     using PackageRegistryBackend::disposing;
109cdf0e10cSrcweir };
110cdf0e10cSrcweir 
111cdf0e10cSrcweir 
BackendImpl(Sequence<Any> const & args,Reference<XComponentContext> const & xComponentContext)112cdf0e10cSrcweir BackendImpl::BackendImpl(
113cdf0e10cSrcweir     Sequence<Any> const & args,
114cdf0e10cSrcweir     Reference<XComponentContext> const & xComponentContext )
115cdf0e10cSrcweir     : PackageRegistryBackend( args, xComponentContext ),
116cdf0e10cSrcweir       m_xExecutableTypeInfo(new Package::TypeInfo(
117cdf0e10cSrcweir                                 OUSTR("application/vnd.sun.star.executable"),
118cdf0e10cSrcweir                                 OUSTR(""),
119cdf0e10cSrcweir                                 OUSTR("Executable"),
120cdf0e10cSrcweir                                 RID_IMG_COMPONENT,
121cdf0e10cSrcweir                                 RID_IMG_COMPONENT_HC ) )
122cdf0e10cSrcweir {
123cdf0e10cSrcweir     if (!transientMode())
124cdf0e10cSrcweir     {
125cdf0e10cSrcweir         OUString dbFile = makeURL(getCachePath(), OUSTR("backenddb.xml"));
126cdf0e10cSrcweir         m_backendDb.reset(
127cdf0e10cSrcweir             new ExecutableBackendDb(getComponentContext(), dbFile));
128cdf0e10cSrcweir    }
129cdf0e10cSrcweir }
130cdf0e10cSrcweir 
addDataToDb(OUString const & url)131cdf0e10cSrcweir void BackendImpl::addDataToDb(OUString const & url)
132cdf0e10cSrcweir {
133cdf0e10cSrcweir     if (m_backendDb.get())
134cdf0e10cSrcweir         m_backendDb->addEntry(url);
135cdf0e10cSrcweir }
136cdf0e10cSrcweir 
revokeEntryFromDb(OUString const & url)137cdf0e10cSrcweir void BackendImpl::revokeEntryFromDb(OUString const & url)
138cdf0e10cSrcweir {
139cdf0e10cSrcweir     if (m_backendDb.get())
140cdf0e10cSrcweir         m_backendDb->revokeEntry(url);
141cdf0e10cSrcweir }
142cdf0e10cSrcweir 
hasActiveEntry(OUString const & url)143cdf0e10cSrcweir bool BackendImpl::hasActiveEntry(OUString const & url)
144cdf0e10cSrcweir {
145cdf0e10cSrcweir     if (m_backendDb.get())
146cdf0e10cSrcweir         return m_backendDb->hasActiveEntry(url);
147cdf0e10cSrcweir     return false;
148cdf0e10cSrcweir }
149cdf0e10cSrcweir 
150cdf0e10cSrcweir 
151cdf0e10cSrcweir // XPackageRegistry
152cdf0e10cSrcweir Sequence< Reference<deployment::XPackageTypeInfo> >
getSupportedPackageTypes()153cdf0e10cSrcweir BackendImpl::getSupportedPackageTypes() throw (RuntimeException)
154cdf0e10cSrcweir {
155cdf0e10cSrcweir     return Sequence<Reference<deployment::XPackageTypeInfo> >(
156cdf0e10cSrcweir         & m_xExecutableTypeInfo, 1);
157cdf0e10cSrcweir }
158cdf0e10cSrcweir 
packageRemoved(OUString const & url,OUString const &)159cdf0e10cSrcweir void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/)
160cdf0e10cSrcweir         throw (deployment::DeploymentException,
161cdf0e10cSrcweir                uno::RuntimeException)
162cdf0e10cSrcweir {
163cdf0e10cSrcweir     if (m_backendDb.get())
164cdf0e10cSrcweir         m_backendDb->removeEntry(url);
165cdf0e10cSrcweir }
166cdf0e10cSrcweir 
167cdf0e10cSrcweir // PackageRegistryBackend
bindPackage_(OUString const & url,OUString const & mediaType,sal_Bool bRemoved,OUString const & identifier,Reference<XCommandEnvironment> const & xCmdEnv)168cdf0e10cSrcweir Reference<deployment::XPackage> BackendImpl::bindPackage_(
169cdf0e10cSrcweir     OUString const & url, OUString const & mediaType, sal_Bool bRemoved,
170cdf0e10cSrcweir     OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv )
171cdf0e10cSrcweir {
172cdf0e10cSrcweir     if (mediaType.getLength() == 0)
173cdf0e10cSrcweir     {
174cdf0e10cSrcweir         throw lang::IllegalArgumentException(
175cdf0e10cSrcweir             StrCannotDetectMediaType::get() + url,
176cdf0e10cSrcweir             static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
177cdf0e10cSrcweir     }
178cdf0e10cSrcweir 
179cdf0e10cSrcweir     String type, subType;
180cdf0e10cSrcweir     INetContentTypeParameterList params;
181cdf0e10cSrcweir     if (INetContentTypes::parse( mediaType, type, subType, &params ))
182cdf0e10cSrcweir     {
183cdf0e10cSrcweir         if (type.EqualsIgnoreCaseAscii("application"))
184cdf0e10cSrcweir         {
185cdf0e10cSrcweir             OUString name;
186cdf0e10cSrcweir             if (!bRemoved)
187cdf0e10cSrcweir             {
188cdf0e10cSrcweir                 ::ucbhelper::Content ucbContent( url, xCmdEnv );
189cdf0e10cSrcweir                 name = ucbContent.getPropertyValue(
190cdf0e10cSrcweir                     dp_misc::StrTitle::get() ).get<OUString>();
191cdf0e10cSrcweir             }
192cdf0e10cSrcweir             if (subType.EqualsIgnoreCaseAscii("vnd.sun.star.executable"))
193cdf0e10cSrcweir             {
194cdf0e10cSrcweir                 return new BackendImpl::ExecutablePackageImpl(
195cdf0e10cSrcweir                     this, url, name,  m_xExecutableTypeInfo, bRemoved,
196cdf0e10cSrcweir                     identifier);
197cdf0e10cSrcweir             }
198cdf0e10cSrcweir         }
199cdf0e10cSrcweir     }
200cdf0e10cSrcweir     return Reference<deployment::XPackage>();
201cdf0e10cSrcweir }
202cdf0e10cSrcweir 
203cdf0e10cSrcweir //##############################################################################
204cdf0e10cSrcweir 
205cdf0e10cSrcweir 
206cdf0e10cSrcweir // Package
getMyBackend() const207cdf0e10cSrcweir BackendImpl * BackendImpl::ExecutablePackageImpl::getMyBackend() const
208cdf0e10cSrcweir {
209cdf0e10cSrcweir     BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
210cdf0e10cSrcweir     if (NULL == pBackend)
211cdf0e10cSrcweir     {
212cdf0e10cSrcweir         //May throw a DisposedException
213cdf0e10cSrcweir         check();
214cdf0e10cSrcweir         //We should never get here...
215cdf0e10cSrcweir         throw RuntimeException(
216cdf0e10cSrcweir             OUSTR("Failed to get the BackendImpl"),
217cdf0e10cSrcweir             static_cast<OWeakObject*>(const_cast<ExecutablePackageImpl *>(this)));
218cdf0e10cSrcweir     }
219cdf0e10cSrcweir     return pBackend;
220cdf0e10cSrcweir }
221cdf0e10cSrcweir 
222cdf0e10cSrcweir beans::Optional< beans::Ambiguous<sal_Bool> >
isRegistered_(::osl::ResettableMutexGuard &,::rtl::Reference<dp_misc::AbortChannel> const &,Reference<XCommandEnvironment> const &)223cdf0e10cSrcweir BackendImpl::ExecutablePackageImpl::isRegistered_(
224cdf0e10cSrcweir     ::osl::ResettableMutexGuard &,
225cdf0e10cSrcweir     ::rtl::Reference<dp_misc::AbortChannel> const &,
226cdf0e10cSrcweir     Reference<XCommandEnvironment> const & )
227cdf0e10cSrcweir {
228cdf0e10cSrcweir     bool registered = getMyBackend()->hasActiveEntry(getURL());
229cdf0e10cSrcweir     return beans::Optional< beans::Ambiguous<sal_Bool> >(
230cdf0e10cSrcweir             sal_True /* IsPresent */,
231cdf0e10cSrcweir                 beans::Ambiguous<sal_Bool>(
232cdf0e10cSrcweir                     registered, sal_False /* IsAmbiguous */ ) );
233cdf0e10cSrcweir }
234cdf0e10cSrcweir 
processPackage_(::osl::ResettableMutexGuard &,bool doRegisterPackage,bool,::rtl::Reference<dp_misc::AbortChannel> const & abortChannel,Reference<XCommandEnvironment> const &)235cdf0e10cSrcweir void BackendImpl::ExecutablePackageImpl::processPackage_(
236cdf0e10cSrcweir     ::osl::ResettableMutexGuard &,
237cdf0e10cSrcweir     bool doRegisterPackage,
238cdf0e10cSrcweir     bool /*startup*/,
239cdf0e10cSrcweir     ::rtl::Reference<dp_misc::AbortChannel> const & abortChannel,
240cdf0e10cSrcweir     Reference<XCommandEnvironment> const & /*xCmdEnv*/ )
241cdf0e10cSrcweir {
242cdf0e10cSrcweir     checkAborted(abortChannel);
243cdf0e10cSrcweir     if (doRegisterPackage)
244cdf0e10cSrcweir     {
245cdf0e10cSrcweir         if (!isUrlTargetInExtension())
246cdf0e10cSrcweir         {
247cdf0e10cSrcweir             OSL_ASSERT(0);
248cdf0e10cSrcweir             return;
249cdf0e10cSrcweir         }
250cdf0e10cSrcweir         sal_uInt64 attributes = 0;
251cdf0e10cSrcweir         //Setting the executable attribut does not affect executables on Windows
252cdf0e10cSrcweir         if (getFileAttributes(attributes))
253cdf0e10cSrcweir         {
254cdf0e10cSrcweir             if(getMyBackend()->m_context.equals(OUSTR("user")))
255cdf0e10cSrcweir                 attributes |= osl_File_Attribute_OwnExe;
256cdf0e10cSrcweir             else if (getMyBackend()->m_context.equals(OUSTR("shared")))
257cdf0e10cSrcweir                 attributes |= (osl_File_Attribute_OwnExe | osl_File_Attribute_GrpExe
258cdf0e10cSrcweir                                | osl_File_Attribute_OthExe);
259cdf0e10cSrcweir             else if (!getMyBackend()->m_context.equals(OUSTR("bundled"))
260cdf0e10cSrcweir                 && !getMyBackend()->m_context.equals(OUSTR("bundled_prereg")))
261cdf0e10cSrcweir                 //Bundled extension are required to be in the properly
262cdf0e10cSrcweir                 //installed. That is an executable must have the right flags
263cdf0e10cSrcweir                 OSL_ASSERT(0);
264cdf0e10cSrcweir 
265cdf0e10cSrcweir             //This won't have affect on Windows
266cdf0e10cSrcweir             osl::File::setAttributes(
267cdf0e10cSrcweir                     dp_misc::expandUnoRcUrl(m_url), attributes);
268cdf0e10cSrcweir         }
269cdf0e10cSrcweir         getMyBackend()->addDataToDb(getURL());
270cdf0e10cSrcweir     }
271cdf0e10cSrcweir     else
272cdf0e10cSrcweir     {
273cdf0e10cSrcweir         getMyBackend()->revokeEntryFromDb(getURL());
274cdf0e10cSrcweir     }
275cdf0e10cSrcweir }
276cdf0e10cSrcweir 
277cdf0e10cSrcweir //We currently cannot check if this XPackage represents a content of a particular extension
278cdf0e10cSrcweir //But we can check if we are within $UNO_USER_PACKAGES_CACHE etc.
279cdf0e10cSrcweir //Done for security reasons. For example an extension manifest could contain a path to
280cdf0e10cSrcweir //an executable outside the extension.
isUrlTargetInExtension()281cdf0e10cSrcweir bool BackendImpl::ExecutablePackageImpl::isUrlTargetInExtension()
282cdf0e10cSrcweir {
283cdf0e10cSrcweir     bool bSuccess = false;
284cdf0e10cSrcweir     OUString sExtensionDir;
285cdf0e10cSrcweir     if(getMyBackend()->m_context.equals(OUSTR("user")))
286cdf0e10cSrcweir         sExtensionDir = dp_misc::expandUnoRcTerm(OUSTR("$UNO_USER_PACKAGES_CACHE"));
287cdf0e10cSrcweir     else if (getMyBackend()->m_context.equals(OUSTR("shared")))
288cdf0e10cSrcweir         sExtensionDir = dp_misc::expandUnoRcTerm(OUSTR("$UNO_SHARED_PACKAGES_CACHE"));
289cdf0e10cSrcweir     else if (getMyBackend()->m_context.equals(OUSTR("bundled"))
290cdf0e10cSrcweir         || getMyBackend()->m_context.equals(OUSTR("bundled_prereg")))
291cdf0e10cSrcweir         sExtensionDir = dp_misc::expandUnoRcTerm(OUSTR("$BUNDLED_EXTENSIONS"));
292cdf0e10cSrcweir     else
293cdf0e10cSrcweir         OSL_ASSERT(0);
294cdf0e10cSrcweir     //remove file ellipses
295cdf0e10cSrcweir     if (osl::File::E_None == osl::File::getAbsoluteFileURL(OUString(), sExtensionDir, sExtensionDir))
296cdf0e10cSrcweir     {
297cdf0e10cSrcweir         OUString sFile;
298cdf0e10cSrcweir         if (osl::File::E_None == osl::File::getAbsoluteFileURL(
299cdf0e10cSrcweir             OUString(), dp_misc::expandUnoRcUrl(m_url), sFile))
300cdf0e10cSrcweir         {
301cdf0e10cSrcweir             if (sal_True == sFile.match(sExtensionDir, 0))
302cdf0e10cSrcweir                 bSuccess = true;
303cdf0e10cSrcweir         }
304cdf0e10cSrcweir     }
305cdf0e10cSrcweir     return bSuccess;
306cdf0e10cSrcweir }
307cdf0e10cSrcweir 
getFileAttributes(sal_uInt64 & out_Attributes)308cdf0e10cSrcweir bool BackendImpl::ExecutablePackageImpl::getFileAttributes(sal_uInt64& out_Attributes)
309cdf0e10cSrcweir {
310cdf0e10cSrcweir     bool bSuccess = false;
311cdf0e10cSrcweir     const OUString url(dp_misc::expandUnoRcUrl(m_url));
312cdf0e10cSrcweir     osl::DirectoryItem item;
313cdf0e10cSrcweir     if (osl::FileBase::E_None == osl::DirectoryItem::get(url, item))
314cdf0e10cSrcweir     {
315cdf0e10cSrcweir         osl::FileStatus aStatus(osl_FileStatus_Mask_Attributes);
316cdf0e10cSrcweir         if( osl::FileBase::E_None == item.getFileStatus(aStatus))
317cdf0e10cSrcweir         {
318cdf0e10cSrcweir             out_Attributes = aStatus.getAttributes();
319cdf0e10cSrcweir             bSuccess = true;
320cdf0e10cSrcweir         }
321cdf0e10cSrcweir     }
322cdf0e10cSrcweir     return bSuccess;
323cdf0e10cSrcweir }
324cdf0e10cSrcweir 
325cdf0e10cSrcweir //##############################################################################
326cdf0e10cSrcweir 
327cdf0e10cSrcweir 
328cdf0e10cSrcweir } // anon namespace
329cdf0e10cSrcweir 
330cdf0e10cSrcweir namespace sdecl = comphelper::service_decl;
331cdf0e10cSrcweir sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI;
332cdf0e10cSrcweir extern sdecl::ServiceDecl const serviceDecl(
333cdf0e10cSrcweir     serviceBI,
334cdf0e10cSrcweir     "com.sun.star.comp.deployment.executable.PackageRegistryBackend",
335cdf0e10cSrcweir     BACKEND_SERVICE_NAME );
336cdf0e10cSrcweir 
337cdf0e10cSrcweir } // namespace component
338cdf0e10cSrcweir } // namespace backend
339cdf0e10cSrcweir } // namespace dp_registry
340cdf0e10cSrcweir 
341cdf0e10cSrcweir 
342