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