Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "dp_misc.h"
31 : : #include "dp_backend.h"
32 : : #include "dp_ucb.h"
33 : : #include "dp_interact.h"
34 : : #include "rtl/string.hxx"
35 : : #include "osl/file.hxx"
36 : : #include "ucbhelper/content.hxx"
37 : : #include "comphelper/servicedecl.hxx"
38 : : #include "svl/inettype.hxx"
39 : : #include "cppuhelper/implbase1.hxx"
40 : : #include "dp_executablebackenddb.hxx"
41 : :
42 : : using namespace ::com::sun::star;
43 : : using namespace ::com::sun::star::uno;
44 : : using namespace ::com::sun::star::ucb;
45 : : using namespace dp_misc;
46 : : using ::rtl::OUString;
47 : :
48 : : namespace dp_registry {
49 : : namespace backend {
50 : : namespace executable {
51 : : namespace {
52 : :
53 [ + - ][ - + ]: 380 : class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend
54 : : {
55 [ - + ]: 248 : class ExecutablePackageImpl : public ::dp_registry::backend::Package
56 : : {
57 : : BackendImpl * getMyBackend() const;
58 : :
59 : : // Package
60 : : virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
61 : : ::osl::ResettableMutexGuard & guard,
62 : : ::rtl::Reference<dp_misc::AbortChannel> const & abortChannel,
63 : : Reference<XCommandEnvironment> const & xCmdEnv );
64 : : virtual void processPackage_(
65 : : ::osl::ResettableMutexGuard & guard,
66 : : bool registerPackage,
67 : : bool startup,
68 : : ::rtl::Reference<dp_misc::AbortChannel> const & abortChannel,
69 : : Reference<XCommandEnvironment> const & xCmdEnv );
70 : :
71 : : bool getFileAttributes(sal_uInt64& out_Attributes);
72 : : bool isUrlTargetInExtension();
73 : :
74 : : public:
75 : 124 : inline ExecutablePackageImpl(
76 : : ::rtl::Reference<PackageRegistryBackend> const & myBackend,
77 : : OUString const & url, OUString const & name,
78 : : Reference<deployment::XPackageTypeInfo> const & xPackageType,
79 : : bool bRemoved, OUString const & identifier)
80 : : : Package( myBackend, url, name, name /* display-name */,
81 : 124 : xPackageType, bRemoved, identifier)
82 : 124 : {}
83 : : };
84 : : friend class ExecutablePackageImpl;
85 : :
86 : : typedef ::boost::unordered_map< OUString, Reference<XInterface>,
87 : : ::rtl::OUStringHash > t_string2object;
88 : :
89 : : // PackageRegistryBackend
90 : : virtual Reference<deployment::XPackage> bindPackage_(
91 : : OUString const & url, OUString const & mediaType, sal_Bool bRemoved,
92 : : OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv );
93 : :
94 : : void addDataToDb(OUString const & url);
95 : : bool hasActiveEntry(OUString const & url);
96 : : void revokeEntryFromDb(OUString const & url);
97 : :
98 : : Reference<deployment::XPackageTypeInfo> m_xExecutableTypeInfo;
99 : : std::auto_ptr<ExecutableBackendDb> m_backendDb;
100 : : public:
101 : : BackendImpl( Sequence<Any> const & args,
102 : : Reference<XComponentContext> const & xComponentContext );
103 : :
104 : : // XPackageRegistry
105 : : virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
106 : : getSupportedPackageTypes() throw (RuntimeException);
107 : : virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType)
108 : : throw (deployment::DeploymentException,
109 : : uno::RuntimeException);
110 : :
111 : : using PackageRegistryBackend::disposing;
112 : : };
113 : :
114 : :
115 : 380 : BackendImpl::BackendImpl(
116 : : Sequence<Any> const & args,
117 : : Reference<XComponentContext> const & xComponentContext )
118 : : : PackageRegistryBackend( args, xComponentContext ),
119 : : m_xExecutableTypeInfo(new Package::TypeInfo(
120 : : OUSTR("application/vnd.sun.star.executable"),
121 : : OUSTR(""),
122 : : OUSTR("Executable"),
123 [ + - ][ + - ]: 380 : RID_IMG_COMPONENT ) )
[ + - ][ + - ]
[ + - ][ + - ]
124 : : {
125 [ + - ]: 380 : if (!transientMode())
126 : : {
127 [ + - ][ + - ]: 380 : OUString dbFile = makeURL(getCachePath(), OUSTR("backenddb.xml"));
128 : : m_backendDb.reset(
129 [ + - ][ + - ]: 380 : new ExecutableBackendDb(getComponentContext(), dbFile));
130 : : }
131 : 380 : }
132 : :
133 : 62 : void BackendImpl::addDataToDb(OUString const & url)
134 : : {
135 [ + - ]: 62 : if (m_backendDb.get())
136 : 62 : m_backendDb->addEntry(url);
137 : 62 : }
138 : :
139 : 0 : void BackendImpl::revokeEntryFromDb(OUString const & url)
140 : : {
141 [ # # ]: 0 : if (m_backendDb.get())
142 : 0 : m_backendDb->revokeEntry(url);
143 : 0 : }
144 : :
145 : 312 : bool BackendImpl::hasActiveEntry(OUString const & url)
146 : : {
147 [ + - ]: 312 : if (m_backendDb.get())
148 : 312 : return m_backendDb->hasActiveEntry(url);
149 : 312 : return false;
150 : : }
151 : :
152 : :
153 : : // XPackageRegistry
154 : : Sequence< Reference<deployment::XPackageTypeInfo> >
155 : 380 : BackendImpl::getSupportedPackageTypes() throw (RuntimeException)
156 : : {
157 : : return Sequence<Reference<deployment::XPackageTypeInfo> >(
158 : 380 : & m_xExecutableTypeInfo, 1);
159 : : }
160 : :
161 : 0 : void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/)
162 : : throw (deployment::DeploymentException,
163 : : uno::RuntimeException)
164 : : {
165 [ # # ]: 0 : if (m_backendDb.get())
166 : 0 : m_backendDb->removeEntry(url);
167 : 0 : }
168 : :
169 : : // PackageRegistryBackend
170 : 625 : Reference<deployment::XPackage> BackendImpl::bindPackage_(
171 : : OUString const & url, OUString const & mediaType, sal_Bool bRemoved,
172 : : OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv )
173 : : {
174 [ + + ]: 625 : if (mediaType.isEmpty())
175 : : {
176 : : throw lang::IllegalArgumentException(
177 [ + - ]: 501 : StrCannotDetectMediaType::get() + url,
178 [ + - ][ + - ]: 1002 : static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
179 : : }
180 : :
181 [ + - ][ + - ]: 124 : String type, subType;
182 [ + - ]: 124 : INetContentTypeParameterList params;
183 [ + - ][ + - ]: 124 : if (INetContentTypes::parse( mediaType, type, subType, ¶ms ))
[ + - ][ + - ]
184 : : {
185 [ + - ][ + - ]: 124 : if (type.EqualsIgnoreCaseAscii("application"))
186 : : {
187 : 124 : OUString name;
188 [ + - ]: 124 : if (!bRemoved)
189 : : {
190 [ + - ]: 124 : ::ucbhelper::Content ucbContent( url, xCmdEnv );
191 [ + - ][ + - ]: 124 : name = StrTitle::getTitle( ucbContent );
192 : : }
193 [ + - ][ + - ]: 124 : if (subType.EqualsIgnoreCaseAscii("vnd.sun.star.executable"))
194 : : {
195 : : return new BackendImpl::ExecutablePackageImpl(
196 : : this, url, name, m_xExecutableTypeInfo, bRemoved,
197 [ + - ][ + - ]: 124 : identifier);
[ + - ]
198 [ - + ]: 124 : }
199 : : }
200 : : }
201 [ + - ][ + - ]: 625 : return Reference<deployment::XPackage>();
[ + - ]
202 : : }
203 : :
204 : :
205 : :
206 : : // Package
207 : 746 : BackendImpl * BackendImpl::ExecutablePackageImpl::getMyBackend() const
208 : : {
209 : 746 : BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
210 [ - + ]: 746 : if (NULL == pBackend)
211 : : {
212 : : //May throw a DisposedException
213 : 0 : check();
214 : : //We should never get here...
215 : : throw RuntimeException(
216 : : OUSTR("Failed to get the BackendImpl"),
217 [ # # ][ # # ]: 0 : static_cast<OWeakObject*>(const_cast<ExecutablePackageImpl *>(this)));
[ # # ]
218 : : }
219 : 746 : return pBackend;
220 : : }
221 : :
222 : : beans::Optional< beans::Ambiguous<sal_Bool> >
223 : 312 : BackendImpl::ExecutablePackageImpl::isRegistered_(
224 : : ::osl::ResettableMutexGuard &,
225 : : ::rtl::Reference<dp_misc::AbortChannel> const &,
226 : : Reference<XCommandEnvironment> const & )
227 : : {
228 [ + - ][ + - ]: 312 : bool registered = getMyBackend()->hasActiveEntry(getURL());
229 : : return beans::Optional< beans::Ambiguous<sal_Bool> >(
230 : : sal_True /* IsPresent */,
231 : : beans::Ambiguous<sal_Bool>(
232 : 312 : registered, sal_False /* IsAmbiguous */ ) );
233 : : }
234 : :
235 : 62 : void BackendImpl::ExecutablePackageImpl::processPackage_(
236 : : ::osl::ResettableMutexGuard &,
237 : : bool doRegisterPackage,
238 : : bool /*startup*/,
239 : : ::rtl::Reference<dp_misc::AbortChannel> const & abortChannel,
240 : : Reference<XCommandEnvironment> const & /*xCmdEnv*/ )
241 : : {
242 : 62 : checkAborted(abortChannel);
243 [ + - ]: 62 : if (doRegisterPackage)
244 : : {
245 [ + - ][ + - ]: 62 : if (!isUrlTargetInExtension())
246 : : {
247 : : OSL_ASSERT(0);
248 : 62 : return;
249 : : }
250 : 62 : sal_uInt64 attributes = 0;
251 : : //Setting the executable attribut does not affect executables on Windows
252 [ + - ][ + - ]: 62 : if (getFileAttributes(attributes))
253 : : {
254 [ + - ][ + - ]: 62 : if(getMyBackend()->m_context.equals(OUSTR("user")))
[ - + ]
255 : 0 : attributes |= osl_File_Attribute_OwnExe;
256 [ + - ][ + - ]: 62 : else if (getMyBackend()->m_context.equals(OUSTR("shared")))
[ - + ]
257 : : attributes |= (osl_File_Attribute_OwnExe | osl_File_Attribute_GrpExe
258 : 0 : | osl_File_Attribute_OthExe);
259 [ + - ][ + - ]: 62 : else if (!getMyBackend()->m_context.equals(OUSTR("bundled")))
260 : : //Bundled extension are required to be in the properly
261 : : //installed. That is an executable must have the right flags
262 : : OSL_ASSERT(0);
263 : :
264 : : //This won't have affect on Windows
265 : : osl::File::setAttributes(
266 [ + - ][ + - ]: 62 : dp_misc::expandUnoRcUrl(m_url), attributes);
267 : : }
268 [ + - ][ + - ]: 62 : getMyBackend()->addDataToDb(getURL());
[ + - ]
269 : : }
270 : : else
271 : : {
272 [ # # ][ # # ]: 0 : getMyBackend()->revokeEntryFromDb(getURL());
273 : : }
274 : : }
275 : :
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 : 62 : bool BackendImpl::ExecutablePackageImpl::isUrlTargetInExtension()
281 : : {
282 : 62 : bool bSuccess = false;
283 : 62 : OUString sExtensionDir;
284 [ + - ][ - + ]: 62 : if(getMyBackend()->m_context.equals(OUSTR("user")))
[ + - ]
285 [ # # ][ # # ]: 0 : sExtensionDir = dp_misc::expandUnoRcTerm(OUSTR("$UNO_USER_PACKAGES_CACHE"));
286 [ + - ][ + - ]: 62 : else if (getMyBackend()->m_context.equals(OUSTR("shared")))
[ - + ]
287 [ # # ][ # # ]: 0 : sExtensionDir = dp_misc::expandUnoRcTerm(OUSTR("$UNO_SHARED_PACKAGES_CACHE"));
288 [ + - ][ + - ]: 62 : else if (getMyBackend()->m_context.equals(OUSTR("bundled")))
[ + - ]
289 [ + - ][ + - ]: 62 : sExtensionDir = dp_misc::expandUnoRcTerm(OUSTR("$BUNDLED_EXTENSIONS"));
290 : : else
291 : : OSL_ASSERT(0);
292 : : //remove file ellipses
293 [ + - ][ + - ]: 62 : if (osl::File::E_None == osl::File::getAbsoluteFileURL(OUString(), sExtensionDir, sExtensionDir))
294 : : {
295 : 62 : OUString sFile;
296 [ + - ]: 62 : if (osl::File::E_None == osl::File::getAbsoluteFileURL(
297 [ + - ][ + - ]: 62 : OUString(), dp_misc::expandUnoRcUrl(m_url), sFile))
298 : : {
299 [ + - ]: 62 : if (sal_True == sFile.match(sExtensionDir, 0))
300 : 62 : bSuccess = true;
301 : 62 : }
302 : : }
303 : 62 : return bSuccess;
304 : : }
305 : :
306 : 62 : bool BackendImpl::ExecutablePackageImpl::getFileAttributes(sal_uInt64& out_Attributes)
307 : : {
308 : 62 : bool bSuccess = false;
309 [ + - ]: 62 : const OUString url(dp_misc::expandUnoRcUrl(m_url));
310 : 62 : osl::DirectoryItem item;
311 [ + - ][ + - ]: 62 : if (osl::FileBase::E_None == osl::DirectoryItem::get(url, item))
312 : : {
313 : 62 : osl::FileStatus aStatus(osl_FileStatus_Mask_Attributes);
314 [ + - ][ + - ]: 62 : if( osl::FileBase::E_None == item.getFileStatus(aStatus))
315 : : {
316 [ + - ]: 62 : out_Attributes = aStatus.getAttributes();
317 : 62 : bSuccess = true;
318 : 62 : }
319 : : }
320 [ + - ]: 62 : return bSuccess;
321 : : }
322 : :
323 : :
324 : :
325 : : } // anon namespace
326 : :
327 : : namespace sdecl = comphelper::service_decl;
328 : 124 : sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI;
329 : 124 : extern sdecl::ServiceDecl const serviceDecl(
330 : : serviceBI,
331 : : "com.sun.star.comp.deployment.executable.PackageRegistryBackend",
332 : : BACKEND_SERVICE_NAME );
333 : :
334 : : } // namespace component
335 : : } // namespace backend
336 [ + - ][ + - ]: 372 : } // namespace dp_registry
337 : :
338 : :
339 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|