diff options
Diffstat (limited to 'desktop/source/app')
41 files changed, 10671 insertions, 0 deletions
diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx new file mode 100644 index 000000000000..cf5997ea3722 --- /dev/null +++ b/desktop/source/app/app.cxx @@ -0,0 +1,3338 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include <cstdlib> +#include <vector> + +#include <memory> +#include <unistd.h> +#include "app.hxx" +#include "desktop.hrc" +#include "appinit.hxx" +#include "officeipcthread.hxx" +#include "cmdlineargs.hxx" +#include "desktopresid.hxx" +#include "dispatchwatcher.hxx" +#include "configinit.hxx" +#include "lockfile.hxx" +#include "checkinstall.hxx" +#include "cmdlinehelp.hxx" +#include "userinstall.hxx" +#include "desktopcontext.hxx" +#include "exithelper.hxx" +#include "../migration/pages.hxx" + +#include <svtools/javacontext.hxx> +#include <com/sun/star/frame/XSessionManagerListener.hpp> +#include <com/sun/star/frame/XSynchronousDispatch.hpp> +#include <com/sun/star/document/CorruptedFilterConfigurationException.hpp> +#include <com/sun/star/configuration/CorruptedConfigurationException.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/util/XModifiable.hpp> +#include <com/sun/star/util/XFlushable.hpp> +#include <com/sun/star/system/XSystemShellExecute.hpp> +#include <com/sun/star/system/SystemShellExecuteFlags.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/io/IOException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/WrappedTargetException.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/view/XPrintable.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/frame/XFramesSupplier.hpp> +#include <com/sun/star/awt/XTopWindow.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/util/URL.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/lang/ServiceNotRegisteredException.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/configuration/MissingBootstrapFileException.hpp> +#include <com/sun/star/configuration/InvalidBootstrapFileException.hpp> +#include <com/sun/star/configuration/InstallationIncompleteException.hpp> +#include <com/sun/star/configuration/backend/BackendSetupException.hpp> +#include <com/sun/star/configuration/backend/BackendAccessException.hpp> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <com/sun/star/task/XJobExecutor.hpp> +#include <com/sun/star/task/XRestartManager.hpp> +#ifndef _COM_SUN_STAR_TASK_XJOBEXECUTOR_HPP_ +#include <com/sun/star/task/XJob.hpp> +#endif +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/task/XJob.hpp> +#include <com/sun/star/document/XEventListener.hpp> +#include <com/sun/star/ui/XUIElementFactoryRegistration.hpp> +#include <com/sun/star/frame/XUIControllerRegistration.hpp> + +#include <com/sun/star/java/XJavaVM.hpp> +#include <tools/testtoolloader.hxx> +#include <tools/solar.h> +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/unohlp.hxx> +#endif +#include <vos/security.hxx> +#include <vos/ref.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/componentcontext.hxx> +#include <comphelper/configurationhelper.hxx> +#ifndef _UTL__HXX_ +#include <unotools/configmgr.hxx> +#endif +#include <unotools/configitem.hxx> +#include <unotools/confignode.hxx> +#include <unotools/ucbhelper.hxx> +#include <tools/tempfile.hxx> +#include <tools/urlobj.hxx> +#include <unotools/moduleoptions.hxx> +#include <osl/module.h> +#include <osl/file.hxx> +#include <osl/signal.h> +#include <rtl/uuid.h> +#include <rtl/uri.hxx> +#include <unotools/pathoptions.hxx> +#include <svl/languageoptions.hxx> +#include <unotools/internaloptions.hxx> +#include <svtools/miscopt.hxx> +#include <svtools/menuoptions.hxx> +#include <unotools/syslocaleoptions.hxx> +#include <unotools/syslocale.hxx> +#include <svl/folderrestriction.hxx> +#include <unotools/tempfile.hxx> +#include <rtl/logfile.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/strbuf.hxx> +#include <rtl/bootstrap.hxx> +#include <rtl/instance.hxx> +#include <unotools/configmgr.hxx> +#include <vcl/help.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/bitmap.hxx> +#include <vcl/stdtext.hxx> +#include <vcl/msgbox.hxx> +#include <sfx2/sfx.hrc> +#include <ucbhelper/contentbroker.hxx> +#include <unotools/bootstrap.hxx> +#include <cppuhelper/bootstrap.hxx> + +#include "vos/process.hxx" + +#include <svtools/fontsubstconfig.hxx> +#include <svtools/accessibilityoptions.hxx> +#include <svtools/apearcfg.hxx> +#include <unotools/misccfg.hxx> +#include <svtools/filter.hxx> +#include <unotools/regoptions.hxx> + +#include "langselect.hxx" + +#if defined MACOSX +#include <errno.h> +#include <sys/wait.h> +#endif + +#define DEFINE_CONST_UNICODE(CONSTASCII) UniString(RTL_CONSTASCII_USTRINGPARAM(CONSTASCII)) +#define U2S(STRING) ::rtl::OUStringToOString(STRING, RTL_TEXTENCODING_UTF8) + +using namespace vos; +using namespace rtl; + +//Gives an ICE with MSVC6 +//namespace css = ::com::sun::star; + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +//using namespace ::com::sun::star::bridge; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::document; +using namespace ::com::sun::star::view; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::system; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::container; + +namespace css = ::com::sun::star; + +ResMgr* desktop::Desktop::pResMgr = 0; + +namespace desktop +{ + +static SalMainPipeExchangeSignalHandler* pSignalHandler = 0; +static sal_Bool _bCrashReporterEnabled = sal_True; + +static const ::rtl::OUString CFG_PACKAGE_COMMON_HELP ( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Office.Common/Help")); +static const ::rtl::OUString CFG_PATH_REG ( RTL_CONSTASCII_USTRINGPARAM( "Registration" )); +static const ::rtl::OUString CFG_ENTRY_REGURL ( RTL_CONSTASCII_USTRINGPARAM( "URL" )); +static const ::rtl::OUString CFG_ENTRY_TEMPLATEREGURL ( RTL_CONSTASCII_USTRINGPARAM( "TemplateURL" )); + +// ---------------------------------------------------------------------------- + +ResMgr* Desktop::GetDesktopResManager() +{ + if ( !Desktop::pResMgr ) + { + String aMgrName = String::CreateFromAscii( "dkt" ); + + // Create desktop resource manager and bootstrap process + // was successful. Use default way to get language specific message. + if ( Application::IsInExecute() ) + Desktop::pResMgr = ResMgr::CreateResMgr( U2S( aMgrName )); + + if ( !Desktop::pResMgr ) + { + // Use VCL to get the correct language specific message as we + // are in the bootstrap process and not able to get the installed + // language!! +/* + LanguageType aLanguageType = LANGUAGE_DONTKNOW; + + Desktop::pResMgr = ResMgr::SearchCreateResMgr( U2S( aMgrName ), aLanguageType ); + AllSettings as = GetSettings(); + as.SetUILanguage(aLanguageType); + SetSettings(as); +*/ + // LanguageSelection langselect; + OUString aUILocaleString = LanguageSelection::getLanguageString(); + sal_Int32 nIndex = 0; + OUString aLanguage = aUILocaleString.getToken( 0, '-', nIndex); + OUString aCountry = aUILocaleString.getToken( 0, '-', nIndex); + OUString aVariant = aUILocaleString.getToken( 0, '-', nIndex); + + ::com::sun::star::lang::Locale aLocale( aLanguage, aCountry, aVariant ); + + Desktop::pResMgr = ResMgr::SearchCreateResMgr( U2S( aMgrName ), aLocale); + AllSettings as = GetSettings(); + as.SetUILocale(aLocale); + SetSettings(as); + } + } + + return Desktop::pResMgr; +} + +// ---------------------------------------------------------------------------- +// Get a message string securely. There is a fallback string if the resource +// is not available. + +OUString Desktop::GetMsgString( USHORT nId, const OUString& aFaultBackMsg ) +{ + ResMgr* resMgr = GetDesktopResManager(); + if ( !resMgr ) + return aFaultBackMsg; + else + return OUString( String( ResId( nId, *resMgr ))); +} + +OUString MakeStartupErrorMessage(OUString const & aErrorMessage) +{ + OUStringBuffer aDiagnosticMessage( 100 ); + + ResMgr* pResMgr = Desktop::GetDesktopResManager(); + if ( pResMgr ) + aDiagnosticMessage.append( OUString(String(ResId(STR_BOOTSTRAP_ERR_CANNOT_START, *pResMgr))) ); + else + aDiagnosticMessage.appendAscii( "The program cannot be started." ); + + aDiagnosticMessage.appendAscii( "\n" ); + + aDiagnosticMessage.append( aErrorMessage ); + + return aDiagnosticMessage.makeStringAndClear(); +} + +OUString MakeStartupConfigAccessErrorMessage( OUString const & aInternalErrMsg ) +{ + OUStringBuffer aDiagnosticMessage( 200 ); + + ResMgr* pResMgr = Desktop::GetDesktopResManager(); + if ( pResMgr ) + aDiagnosticMessage.append( OUString(String(ResId(STR_BOOTSTRAP_ERR_CFG_DATAACCESS, *pResMgr ))) ); + else + aDiagnosticMessage.appendAscii( "The program cannot be started." ); + + if ( aInternalErrMsg.getLength() > 0 ) + { + aDiagnosticMessage.appendAscii( "\n\n" ); + if ( pResMgr ) + aDiagnosticMessage.append( OUString(String(ResId(STR_INTERNAL_ERRMSG, *pResMgr ))) ); + else + aDiagnosticMessage.appendAscii( "The following internal error has occured:\n\n" ); + aDiagnosticMessage.append( aInternalErrMsg ); + } + + return aDiagnosticMessage.makeStringAndClear(); +} + +//============================================================================= +// shows a simple error box with the given message ... but exits from these process ! +// +// Fatal errors cant be solved by the process ... nor any recovery can help. +// Mostly the installation was damaged and must be repaired manually .. or by calling +// setup again. +// +// On the other side we must make sure that no further actions will be possible within +// the current office process ! No pipe requests, no menu/toolbar/shortuct actions +// are allowed. Otherwise we will force a "crash inside a crash". +// +// Thats why we have to use a special native message box here which does not use yield :-) +//============================================================================= +void FatalError(const ::rtl::OUString& sMessage) +{ + ::rtl::OUString sProductKey = ::utl::Bootstrap::getProductKey(); + if ( ! sProductKey.getLength()) + { + ::vos::OStartupInfo aInfo; + aInfo.getExecutableFile( sProductKey ); + + ::sal_uInt32 nLastIndex = sProductKey.lastIndexOf('/'); + if ( nLastIndex > 0 ) + sProductKey = sProductKey.copy( nLastIndex+1 ); + } + + ::rtl::OUStringBuffer sTitle (128); + sTitle.append (sProductKey ); + sTitle.appendAscii (" - Fatal Error"); + + Application::ShowNativeErrorBox (sTitle.makeStringAndClear (), sMessage); + _exit(ExitHelper::E_FATAL_ERROR); +} + +static bool ShouldSuppressUI(CommandLineArgs* pCmdLine) +{ + return pCmdLine->IsInvisible() || + pCmdLine->IsHeadless() || + pCmdLine->IsQuickstart(); +} + +CommandLineArgs* Desktop::GetCommandLineArgs() +{ + static CommandLineArgs* pArgs = 0; + if ( !pArgs ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !pArgs ) + { + pArgs = new CommandLineArgs; + } + } + + return pArgs; +} + +sal_Bool InitConfiguration() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (jb99855) ::InitConfiguration" ); + + Reference< XMultiServiceFactory > xProvider( CreateApplicationConfigurationProvider( ) ); + return xProvider.is(); +} + +namespace +{ + struct BrandName + : public rtl::Static< String, BrandName > {}; + struct Version + : public rtl::Static< String, Version > {}; + struct AboutBoxVersion + : public rtl::Static< String, AboutBoxVersion > {}; + struct OOOVendor + : public rtl::Static< String, OOOVendor > {}; + struct Extension + : public rtl::Static< String, Extension > {}; + struct XMLFileFormatName + : public rtl::Static< String, XMLFileFormatName > {}; + struct XMLFileFormatVersion + : public rtl::Static< String, XMLFileFormatVersion > {}; + struct WriterCompatibilityVersionOOo11 + : public rtl::Static< String, WriterCompatibilityVersionOOo11 > {}; +} + +void ReplaceStringHookProc( UniString& rStr ) +{ + static int nAll = 0, nPro = 0; + + nAll++; + if ( rStr.SearchAscii( "%PRODUCT" ) != STRING_NOTFOUND ) + { + String &rBrandName = BrandName::get(); + String &rVersion = Version::get(); + String &rAboutBoxVersion = AboutBoxVersion::get(); + String &rExtension = Extension::get(); + String &rXMLFileFormatName = XMLFileFormatName::get(); + String &rXMLFileFormatVersion = XMLFileFormatVersion::get(); + + if ( !rBrandName.Len() ) + { + rtl::OUString aTmp; + Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME ); + aRet >>= aTmp; + rBrandName = aTmp; + + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTXMLFILEFORMATNAME ); + aRet >>= aTmp; + rXMLFileFormatName = aTmp; + + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTXMLFILEFORMATVERSION ); + aRet >>= aTmp; + rXMLFileFormatVersion = aTmp; + + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTVERSION ); + aRet >>= aTmp; + rVersion = aTmp; + + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::ABOUTBOXPRODUCTVERSION ); + aRet >>= aTmp; + rAboutBoxVersion = aTmp; + + if ( !rExtension.Len() ) + { + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTEXTENSION ); + aRet >>= aTmp; + rExtension = aTmp; + } + } + + nPro++; + rStr.SearchAndReplaceAllAscii( "%PRODUCTNAME", rBrandName ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTVERSION", rVersion ); + rStr.SearchAndReplaceAllAscii( "%ABOUTBOXPRODUCTVERSION", rAboutBoxVersion ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTEXTENSION", rExtension ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTXMLFILEFORMATNAME", rXMLFileFormatName ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTXMLFILEFORMATVERSION", rXMLFileFormatVersion ); + } + if ( rStr.SearchAscii( "%OOOVENDOR" ) != STRING_NOTFOUND ) + { + String &rOOOVendor = OOOVendor::get(); + + if ( !rOOOVendor.Len() ) + { + rtl::OUString aTmp; + Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::OOOVENDOR ); + aRet >>= aTmp; + rOOOVendor = aTmp; + + } + rStr.SearchAndReplaceAllAscii( "%OOOVENDOR" ,rOOOVendor ); + } + + if ( rStr.SearchAscii( "%WRITERCOMPATIBILITYVERSIONOOO11" ) != STRING_NOTFOUND ) + { + String &rWriterCompatibilityVersionOOo11 = WriterCompatibilityVersionOOo11::get(); + if ( !rWriterCompatibilityVersionOOo11.Len() ) + { + rtl::OUString aTmp; + Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::WRITERCOMPATIBILITYVERSIONOOO11 ); + aRet >>= aTmp; + rWriterCompatibilityVersionOOo11 = aTmp; + } + + rStr.SearchAndReplaceAllAscii( "%WRITERCOMPATIBILITYVERSIONOOO11", + rWriterCompatibilityVersionOOo11 ); + } +} + +static const char pLastSyncFileName[] = "lastsynchronized"; +static const sal_Int32 nStrLenLastSync = 16; + +static bool needsSynchronization( + ::rtl::OUString const & baseSynchronizedURL, ::rtl::OUString const & userSynchronizedURL ) +{ + bool bNeedsSync( false ); + + ::osl::DirectoryItem itemUserFile; + ::osl::File::RC err1 = + ::osl::DirectoryItem::get(userSynchronizedURL, itemUserFile); + + //If it does not exist, then there is nothing to be done + if (err1 == ::osl::File::E_NOENT) + { + return true; + } + else if (err1 != ::osl::File::E_None) + { + OSL_ENSURE(0, "Cannot access lastsynchronized in user layer"); + return true; //sync just in case + } + + //If last synchronized does not exist in base layer, then do nothing + ::osl::DirectoryItem itemBaseFile; + ::osl::File::RC err2 = ::osl::DirectoryItem::get(baseSynchronizedURL, itemBaseFile); + if (err2 == ::osl::File::E_NOENT) + { + return true; + + } + else if (err2 != ::osl::File::E_None) + { + OSL_ENSURE(0, "Cannot access file lastsynchronized in base layer"); + return true; //sync just in case + } + + //compare the modification time of the extension folder and the last + //modified file + ::osl::FileStatus statUser(FileStatusMask_ModifyTime); + ::osl::FileStatus statBase(FileStatusMask_ModifyTime); + if (itemUserFile.getFileStatus(statUser) == ::osl::File::E_None) + { + if (itemBaseFile.getFileStatus(statBase) == ::osl::File::E_None) + { + TimeValue timeUser = statUser.getModifyTime(); + TimeValue timeBase = statBase.getModifyTime(); + + if (timeUser.Seconds < timeBase.Seconds) + bNeedsSync = true; + } + else + { + OSL_ASSERT(0); + bNeedsSync = true; + } + } + else + { + OSL_ASSERT(0); + bNeedsSync = true; + } + + return bNeedsSync; +} + +static ::rtl::OUString getBrandSharePreregBundledPathURL() +{ + ::rtl::OUString url( + RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR/share/prereg/bundled")); + + ::rtl::Bootstrap::expandMacros(url); + return url; +} + +static ::rtl::OUString getUserBundledExtPathURL() +{ + ::rtl::OUString folder( RTL_CONSTASCII_USTRINGPARAM( "$BUNDLED_EXTENSIONS_USER" )); + ::rtl::Bootstrap::expandMacros(folder); + + return folder; +} + +static ::rtl::OUString getLastSyncFileURLFromBrandInstallation() +{ + ::rtl::OUString aURL = getBrandSharePreregBundledPathURL(); + ::sal_Int32 nLastIndex = aURL.lastIndexOf('/'); + + ::rtl::OUStringBuffer aTmp( aURL ); + + if ( nLastIndex != aURL.getLength()-1 ) + aTmp.appendAscii( "/" ); + aTmp.appendAscii( pLastSyncFileName ); + + return aTmp.makeStringAndClear(); +} + +static ::rtl::OUString getLastSyncFileURLFromUserInstallation() +{ + ::rtl::OUString aUserBundledPathURL = getUserBundledExtPathURL(); + ::sal_Int32 nLastIndex = aUserBundledPathURL.lastIndexOf('/'); + + ::rtl::OUStringBuffer aTmp( aUserBundledPathURL ); + + if ( nLastIndex != aUserBundledPathURL.getLength()-1 ) + aTmp.appendAscii( "/" ); + aTmp.appendAscii( pLastSyncFileName ); + + return aTmp.makeStringAndClear(); +} + +static osl::FileBase::RC copy_bundled_recursive( + const rtl::OUString& srcUnqPath, + const rtl::OUString& dstUnqPath, + sal_Int32 TypeToCopy ) +throw() +{ + osl::FileBase::RC err = osl::FileBase::E_None; + + if( TypeToCopy == -1 ) // Document + { + err = osl::File::copy( srcUnqPath,dstUnqPath ); + } + else if( TypeToCopy == +1 ) // Folder + { + osl::Directory aDir( srcUnqPath ); + aDir.open(); + + err = osl::Directory::create( dstUnqPath ); + osl::FileBase::RC next = err; + if( err == osl::FileBase::E_None || + err == osl::FileBase::E_EXIST ) + { + err = osl::FileBase::E_None; + sal_Int32 n_Mask = FileStatusMask_FileURL | FileStatusMask_FileName | FileStatusMask_Type; + + osl::DirectoryItem aDirItem; + + while( err == osl::FileBase::E_None && ( next = aDir.getNextItem( aDirItem ) ) == osl::FileBase::E_None ) + { + sal_Bool IsDoc = false; + sal_Bool bFilter = false; + osl::FileStatus aFileStatus( n_Mask ); + aDirItem.getFileStatus( aFileStatus ); + if( aFileStatus.isValid( FileStatusMask_Type ) ) + IsDoc = aFileStatus.getFileType() == osl::FileStatus::Regular; + + // Getting the information for the next recursive copy + sal_Int32 newTypeToCopy = IsDoc ? -1 : +1; + + rtl::OUString newSrcUnqPath; + if( aFileStatus.isValid( FileStatusMask_FileURL ) ) + newSrcUnqPath = aFileStatus.getFileURL(); + + rtl::OUString newDstUnqPath = dstUnqPath; + rtl::OUString tit; + if( aFileStatus.isValid( FileStatusMask_FileName ) ) + { + ::rtl::OUString aFileName = aFileStatus.getFileName(); + tit = rtl::Uri::encode( aFileName, + rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ); + + // Special treatment for "lastsychronized" file. Must not be + // copied from the bundled folder! + if ( IsDoc && aFileName.equalsAscii( pLastSyncFileName )) + bFilter = true; + } + + if( newDstUnqPath.lastIndexOf( sal_Unicode('/') ) != newDstUnqPath.getLength()-1 ) + newDstUnqPath += rtl::OUString::createFromAscii( "/" ); + + newDstUnqPath += tit; + + if (( newSrcUnqPath != dstUnqPath ) && !bFilter ) + err = copy_bundled_recursive( newSrcUnqPath,newDstUnqPath, newTypeToCopy ); + } + + if( err == osl::FileBase::E_None && next != osl::FileBase::E_NOENT ) + err = next; + } + aDir.close(); + } + + return err; +} + +Desktop::Desktop() +: m_bServicesRegistered( false ) +, m_aBootstrapError( BE_OK ) +, m_pLockfile( NULL ) +{ + RTL_LOGFILE_TRACE( "desktop (cd100003) ::Desktop::Desktop" ); +} + +Desktop::~Desktop() +{ +} + +void Desktop::Init() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::Init" ); + SetBootstrapStatus(BS_OK); + + // Check for lastsynchronized file for bundled extensions in the user directory + // and test if synchronzation is necessary! + { + ::rtl::OUString aUserLastSyncFilePathURL = getLastSyncFileURLFromUserInstallation(); + ::rtl::OUString aPreregSyncFilePathURL = getLastSyncFileURLFromBrandInstallation(); + + if ( needsSynchronization( aPreregSyncFilePathURL, aUserLastSyncFilePathURL )) + { + rtl::OUString aUserPath = getUserBundledExtPathURL(); + rtl::OUString aPreregBundledPath = getBrandSharePreregBundledPathURL(); + + // copy bundled folder to the user directory + osl::FileBase::RC rc = osl::Directory::createPath(aUserPath); + (void) rc; + copy_bundled_recursive( aPreregBundledPath, aUserPath, +1 ); + } + } + + // create service factory... + Reference < XMultiServiceFactory > rSMgr = CreateApplicationServiceManager(); + if( rSMgr.is() ) + { + ::comphelper::setProcessServiceFactory( rSMgr ); + } + else + { + SetBootstrapError( BE_UNO_SERVICEMANAGER ); + } + + if ( GetBootstrapError() == BE_OK ) + { + // prepare language + if ( !LanguageSelection::prepareLanguage() ) + { + if ( LanguageSelection::getStatus() == LanguageSelection::LS_STATUS_CANNOT_DETERMINE_LANGUAGE ) + SetBootstrapError( BE_LANGUAGE_MISSING ); + else + SetBootstrapError( BE_OFFICECONFIG_BROKEN ); + } + } + + if ( GetBootstrapError() == BE_OK ) + { + CommandLineArgs* pCmdLineArgs = GetCommandLineArgs(); +#ifdef UNX + // check whether we need to print cmdline help + if ( pCmdLineArgs->IsHelp() ) { + displayCmdlineHelp(); + SetBootstrapStatus(BS_TERMINATE); + } +#endif + // start ipc thread only for non-remote offices + RTL_LOGFILE_CONTEXT( aLog2, "desktop (cd100003) ::OfficeIPCThread::EnableOfficeIPCThread" ); + OfficeIPCThread::Status aStatus = OfficeIPCThread::EnableOfficeIPCThread(); + if ( aStatus == OfficeIPCThread::IPC_STATUS_BOOTSTRAP_ERROR ) + { + SetBootstrapError( BE_PATHINFO_MISSING ); + } + else if ( aStatus == OfficeIPCThread::IPC_STATUS_2ND_OFFICE ) + { + // 2nd office startup should terminate after sending cmdlineargs through pipe + SetBootstrapStatus(BS_TERMINATE); + } + else if ( pCmdLineArgs->IsHelp() ) + { + // disable IPC thread in an instance that is just showing a help message + OfficeIPCThread::DisableOfficeIPCThread(); + } + pSignalHandler = new SalMainPipeExchangeSignalHandler; + } +} + +void Desktop::DeInit() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::DeInit" ); + + try { + // instead of removing of the configManager just let it commit all the changes + RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); + utl::ConfigManager::GetConfigManager()->StoreConfigItems(); + FlushConfiguration(); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); + + // close splashscreen if it's still open + CloseSplashScreen(); + Reference<XMultiServiceFactory> xXMultiServiceFactory(::comphelper::getProcessServiceFactory()); + DestroyApplicationServiceManager( xXMultiServiceFactory ); + // nobody should get a destroyd service factory... + ::comphelper::setProcessServiceFactory( NULL ); + + // clear lockfile + if (m_pLockfile != NULL) + m_pLockfile->clean(); + + OfficeIPCThread::DisableOfficeIPCThread(); + if( pSignalHandler ) + DELETEZ( pSignalHandler ); + } catch (RuntimeException&) { + // someone threw an exception during shutdown + // this will leave some garbage behind.. + } + + RTL_LOGFILE_CONTEXT_TRACE( aLog, "FINISHED WITH Destop::DeInit" ); +} + +BOOL Desktop::QueryExit() +{ + try + { + RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); + utl::ConfigManager::GetConfigManager()->StoreConfigItems(); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); + } + catch ( RuntimeException& ) + { + } + + const sal_Char SUSPEND_QUICKSTARTVETO[] = "SuspendQuickstartVeto"; + + Reference< ::com::sun::star::frame::XDesktop > + xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + UNO_QUERY ); + + Reference < ::com::sun::star::beans::XPropertySet > xPropertySet( xDesktop, UNO_QUERY ); + if ( xPropertySet.is() ) + { + Any a; + a <<= (sal_Bool)sal_True; + xPropertySet->setPropertyValue( OUSTRING(RTL_CONSTASCII_USTRINGPARAM( SUSPEND_QUICKSTARTVETO )), a ); + } + + BOOL bExit = ( !xDesktop.is() || xDesktop->terminate() ); + + + if ( !bExit && xPropertySet.is() ) + { + Any a; + a <<= (sal_Bool)sal_False; + xPropertySet->setPropertyValue( OUSTRING(RTL_CONSTASCII_USTRINGPARAM( SUSPEND_QUICKSTARTVETO )), a ); + } + else + { + FlushConfiguration(); + try + { + // it is no problem to call DisableOfficeIPCThread() more than once + // it also looks to be threadsafe + OfficeIPCThread::DisableOfficeIPCThread(); + } + catch ( RuntimeException& ) + { + } + + if (m_pLockfile != NULL) m_pLockfile->clean(); + } + + return bExit; +} + +void Desktop::HandleBootstrapPathErrors( ::utl::Bootstrap::Status aBootstrapStatus, const OUString& aDiagnosticMessage ) +{ + if ( aBootstrapStatus != ::utl::Bootstrap::DATA_OK ) + { + sal_Bool bWorkstationInstallation = sal_False; + ::rtl::OUString aBaseInstallURL; + ::rtl::OUString aUserInstallURL; + ::rtl::OUString aProductKey; + ::rtl::OUString aTemp; + ::vos::OStartupInfo aInfo; + + aInfo.getExecutableFile( aProductKey ); + sal_uInt32 lastIndex = aProductKey.lastIndexOf('/'); + if ( lastIndex > 0 ) + aProductKey = aProductKey.copy( lastIndex+1 ); + + aTemp = ::utl::Bootstrap::getProductKey( aProductKey ); + if ( aTemp.getLength() > 0 ) + aProductKey = aTemp; + + ::utl::Bootstrap::PathStatus aBaseInstallStatus = ::utl::Bootstrap::locateBaseInstallation( aBaseInstallURL ); + ::utl::Bootstrap::PathStatus aUserInstallStatus = ::utl::Bootstrap::locateUserInstallation( aUserInstallURL ); + + if (( aBaseInstallStatus == ::utl::Bootstrap::PATH_EXISTS && + aUserInstallStatus == ::utl::Bootstrap::PATH_EXISTS )) + { + if ( aBaseInstallURL != aUserInstallURL ) + bWorkstationInstallation = sal_True; + } + + OUString aMessage; + OUStringBuffer aBuffer( 100 ); + aBuffer.append( aDiagnosticMessage ); + + aBuffer.appendAscii( "\n" ); + + ErrorBox aBootstrapFailedBox( NULL, WB_OK, aMessage ); + aBootstrapFailedBox.SetText( aProductKey ); + aBootstrapFailedBox.Execute(); + } +} + +// Create a error message depending on bootstrap failure code and an optional file url +::rtl::OUString Desktop::CreateErrorMsgString( + utl::Bootstrap::FailureCode nFailureCode, + const ::rtl::OUString& aFileURL ) +{ + OUString aMsg; + OUString aFilePath; + sal_Bool bFileInfo = sal_True; + + switch ( nFailureCode ) + { + /// the shared installation directory could not be located + case ::utl::Bootstrap::MISSING_INSTALL_DIRECTORY: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_PATH_INVALID, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The installation path is not available." )) ); + bFileInfo = sal_False; + } + break; + + /// the bootstrap INI file could not be found or read + case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_MISSING, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration file \"$1\" is missing." )) ); + } + break; + + /// the bootstrap INI is missing a required entry + /// the bootstrap INI contains invalid data + case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY: + case ::utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_CORRUPT, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration file \"$1\" is corrupt." )) ); + } + break; + + /// the version locator INI file could not be found or read + case ::utl::Bootstrap::MISSING_VERSION_FILE: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_MISSING, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration file \"$1\" is missing." )) ); + } + break; + + /// the version locator INI has no entry for this version + case ::utl::Bootstrap::MISSING_VERSION_FILE_ENTRY: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_SUPPORT, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The main configuration file \"$1\" does not support the current version." )) ); + } + break; + + /// the user installation directory does not exist + case ::utl::Bootstrap::MISSING_USER_DIRECTORY: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_DIR_MISSING, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration directory \"$1\" is missing." )) ); + } + break; + + /// some bootstrap data was invalid in unexpected ways + case ::utl::Bootstrap::INVALID_BOOTSTRAP_DATA: + { + aMsg = GetMsgString( STR_BOOTSTRAP_ERR_INTERNAL, + OUString( RTL_CONSTASCII_USTRINGPARAM( "An internal failure occurred." )) ); + bFileInfo = sal_False; + } + break; + + case ::utl::Bootstrap::INVALID_VERSION_FILE_ENTRY: + { + // This needs to be improved, see #i67575#: + aMsg = OUString( + RTL_CONSTASCII_USTRINGPARAM( "Invalid version file entry" ) ); + bFileInfo = sal_False; + } + break; + + case ::utl::Bootstrap::NO_FAILURE: + { + OSL_ASSERT(false); + } + break; + } + + if ( bFileInfo ) + { + String aMsgString( aMsg ); + + osl::File::getSystemPathFromFileURL( aFileURL, aFilePath ); + + aMsgString.SearchAndReplaceAscii( "$1", aFilePath ); + aMsg = aMsgString; + } + + return MakeStartupErrorMessage( aMsg ); +} + +void Desktop::HandleBootstrapErrors( BootstrapError aBootstrapError ) +{ + if ( aBootstrapError == BE_PATHINFO_MISSING ) + { + OUString aErrorMsg; + OUString aBuffer; + utl::Bootstrap::Status aBootstrapStatus; + utl::Bootstrap::FailureCode nFailureCode; + + aBootstrapStatus = ::utl::Bootstrap::checkBootstrapStatus( aBuffer, nFailureCode ); + if ( aBootstrapStatus != ::utl::Bootstrap::DATA_OK ) + { + switch ( nFailureCode ) + { + case ::utl::Bootstrap::MISSING_INSTALL_DIRECTORY: + case ::utl::Bootstrap::INVALID_BOOTSTRAP_DATA: + { + aErrorMsg = CreateErrorMsgString( nFailureCode, OUString() ); + } + break; + + /// the bootstrap INI file could not be found or read + /// the bootstrap INI is missing a required entry + /// the bootstrap INI contains invalid data + case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY: + case ::utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY: + case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE: + { + OUString aBootstrapFileURL; + + utl::Bootstrap::locateBootstrapFile( aBootstrapFileURL ); + aErrorMsg = CreateErrorMsgString( nFailureCode, aBootstrapFileURL ); + } + break; + + /// the version locator INI file could not be found or read + /// the version locator INI has no entry for this version + /// the version locator INI entry is not a valid directory URL + case ::utl::Bootstrap::INVALID_VERSION_FILE_ENTRY: + case ::utl::Bootstrap::MISSING_VERSION_FILE_ENTRY: + case ::utl::Bootstrap::MISSING_VERSION_FILE: + { + OUString aVersionFileURL; + + utl::Bootstrap::locateVersionFile( aVersionFileURL ); + aErrorMsg = CreateErrorMsgString( nFailureCode, aVersionFileURL ); + } + break; + + /// the user installation directory does not exist + case ::utl::Bootstrap::MISSING_USER_DIRECTORY: + { + OUString aUserInstallationURL; + + utl::Bootstrap::locateUserInstallation( aUserInstallationURL ); + aErrorMsg = CreateErrorMsgString( nFailureCode, aUserInstallationURL ); + } + break; + + case ::utl::Bootstrap::NO_FAILURE: + { + OSL_ASSERT(false); + } + break; + } + + HandleBootstrapPathErrors( aBootstrapStatus, aErrorMsg ); + } + } + else if ( aBootstrapError == BE_UNO_SERVICEMANAGER || aBootstrapError == BE_UNO_SERVICE_CONFIG_MISSING ) + { + // Uno service manager is not available. VCL needs a uno service manager to display a message box!!! + // Currently we are not able to display a message box with a service manager due to this limitations inside VCL. + + // When UNO is not properly initialized, all kinds of things can fail + // and cause the process to crash (e.g., a call to GetMsgString may + // crash when somewhere deep within that call Any::operator <= is used + // with a PropertyValue, and no binary UNO type description for + // PropertyValue is available). To give the user a hint even if + // generating and displaying a message box below crashes, print a + // hard-coded message on stderr first: + fputs( + aBootstrapError == BE_UNO_SERVICEMANAGER + ? ("The application cannot be started. " "\n" + "The component manager is not available." "\n") + // STR_BOOTSTRAP_ERR_CANNOT_START, STR_BOOTSTRAP_ERR_NO_SERVICE + : ("The application cannot be started. " "\n" + "The configuration service is not available." "\n"), + // STR_BOOTSTRAP_ERR_CANNOT_START, + // STR_BOOTSTRAP_ERR_NO_CFG_SERVICE + stderr); + + // First sentence. We cannot bootstrap office further! + OUString aMessage; + OUStringBuffer aDiagnosticMessage( 100 ); + + OUString aErrorMsg; + + if ( aBootstrapError == BE_UNO_SERVICEMANAGER ) + aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_SERVICE, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The service manager is not available." )) ); + else + aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_CFG_SERVICE, + OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration service is not available." )) ); + + aDiagnosticMessage.append( aErrorMsg ); + aDiagnosticMessage.appendAscii( "\n" ); + + // Due to the fact the we haven't a backup applicat.rdb file anymore it is not possible to + // repair the installation with the setup executable besides the office executable. Now + // we have to ask the user to start the setup on CD/installation directory manually!! + OUString aStartSetupManually( GetMsgString( + STR_ASK_START_SETUP_MANUALLY, + OUString( RTL_CONSTASCII_USTRINGPARAM( "Start setup application to repair the installation from CD, or the folder containing the installation packages." )) )); + + aDiagnosticMessage.append( aStartSetupManually ); + aMessage = MakeStartupErrorMessage( aDiagnosticMessage.makeStringAndClear() ); + + FatalError( aMessage); + } + else if ( aBootstrapError == BE_OFFICECONFIG_BROKEN ) + { + OUString aMessage; + OUStringBuffer aDiagnosticMessage( 100 ); + OUString aErrorMsg; + aErrorMsg = GetMsgString( STR_CONFIG_ERR_ACCESS_GENERAL, + OUString( RTL_CONSTASCII_USTRINGPARAM( "A general error occurred while accessing your central configuration." )) ); + aDiagnosticMessage.append( aErrorMsg ); + aMessage = MakeStartupErrorMessage( aDiagnosticMessage.makeStringAndClear() ); + FatalError(aMessage); + } + else if ( aBootstrapError == BE_USERINSTALL_FAILED ) + { + OUString aMessage; + OUStringBuffer aDiagnosticMessage( 100 ); + OUString aErrorMsg; + aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_INTERNAL, + OUString( RTL_CONSTASCII_USTRINGPARAM( "User installation could not be completed" )) ); + aDiagnosticMessage.append( aErrorMsg ); + aMessage = MakeStartupErrorMessage( aDiagnosticMessage.makeStringAndClear() ); + FatalError(aMessage); + } + else if ( aBootstrapError == BE_LANGUAGE_MISSING ) + { + OUString aMessage; + OUStringBuffer aDiagnosticMessage( 100 ); + OUString aErrorMsg; + aErrorMsg = GetMsgString( + //@@@ FIXME: should use an own resource string => #i36213# + STR_BOOTSTRAP_ERR_LANGUAGE_MISSING, + OUString( RTL_CONSTASCII_USTRINGPARAM( + "Language could not be determined." )) ); + aDiagnosticMessage.append( aErrorMsg ); + aMessage = MakeStartupErrorMessage( + aDiagnosticMessage.makeStringAndClear() ); + FatalError(aMessage); + } + else if (( aBootstrapError == BE_USERINSTALL_NOTENOUGHDISKSPACE ) || + ( aBootstrapError == BE_USERINSTALL_NOWRITEACCESS )) + { + OUString aUserInstallationURL; + OUString aUserInstallationPath; + OUString aMessage; + OUString aErrorMsg; + OUStringBuffer aDiagnosticMessage( 100 ); + + utl::Bootstrap::locateUserInstallation( aUserInstallationURL ); + + if ( aBootstrapError == BE_USERINSTALL_NOTENOUGHDISKSPACE ) + aErrorMsg = GetMsgString( + STR_BOOSTRAP_ERR_NOTENOUGHDISKSPACE, + OUString( RTL_CONSTASCII_USTRINGPARAM( + "User installation could not be completed due to insufficient free disk space." )) ); + else + aErrorMsg = GetMsgString( + STR_BOOSTRAP_ERR_NOACCESSRIGHTS, + OUString( RTL_CONSTASCII_USTRINGPARAM( + "User installation could not be processed due to missing access rights." )) ); + + osl::File::getSystemPathFromFileURL( aUserInstallationURL, aUserInstallationPath ); + + aDiagnosticMessage.append( aErrorMsg ); + aDiagnosticMessage.append( aUserInstallationPath ); + aMessage = MakeStartupErrorMessage( + aDiagnosticMessage.makeStringAndClear() ); + FatalError(aMessage); + } + + return; +} + + +void Desktop::retrieveCrashReporterState() +{ + static const ::rtl::OUString CFG_PACKAGE_RECOVERY = ::rtl::OUString::createFromAscii("org.openoffice.Office.Recovery/"); + static const ::rtl::OUString CFG_PATH_CRASHREPORTER = ::rtl::OUString::createFromAscii("CrashReporter" ); + static const ::rtl::OUString CFG_ENTRY_ENABLED = ::rtl::OUString::createFromAscii("Enabled" ); + + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + + sal_Bool bEnabled( sal_True ); + if ( xSMGR.is() ) + { + css::uno::Any aVal = ::comphelper::ConfigurationHelper::readDirectKey( + xSMGR, + CFG_PACKAGE_RECOVERY, + CFG_PATH_CRASHREPORTER, + CFG_ENTRY_ENABLED, + ::comphelper::ConfigurationHelper::E_READONLY); + aVal >>= bEnabled; + } + _bCrashReporterEnabled = bEnabled; +} + +sal_Bool Desktop::isUIOnSessionShutdownAllowed() +{ + static const ::rtl::OUString CFG_PACKAGE_RECOVERY = ::rtl::OUString::createFromAscii("org.openoffice.Office.Recovery/"); + static const ::rtl::OUString CFG_PATH_SESSION = ::rtl::OUString::createFromAscii("SessionShutdown" ); + static const ::rtl::OUString CFG_ENTRY_UIENABLED = ::rtl::OUString::createFromAscii("DocumentStoreUIEnabled" ); + + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + + sal_Bool bResult = sal_False; + if ( xSMGR.is() ) + { + css::uno::Any aVal = ::comphelper::ConfigurationHelper::readDirectKey( + xSMGR, + CFG_PACKAGE_RECOVERY, + CFG_PATH_SESSION, + CFG_ENTRY_UIENABLED, + ::comphelper::ConfigurationHelper::E_READONLY); + aVal >>= bResult; + } + + return bResult; +} + +//----------------------------------------------- +/** @short check if crash reporter feature is enabled or + disabled. +*/ +sal_Bool Desktop::isCrashReporterEnabled() +{ + return _bCrashReporterEnabled; +} + +//----------------------------------------------- +/** @short check if recovery must be started or not. + + @param bCrashed [boolean ... out!] + the office crashed last times. + But may be there are no recovery data. + Usefull to trigger the error report tool without + showing the recovery UI. + + @param bRecoveryDataExists [boolean ... out!] + there exists some recovery data. + + @param bSessionDataExists [boolean ... out!] + there exists some session data. + Because the user may be logged out last time from it's + unix session... +*/ +void impl_checkRecoveryState(sal_Bool& bCrashed , + sal_Bool& bRecoveryDataExists, + sal_Bool& bSessionDataExists ) +{ + static const ::rtl::OUString SERVICENAME_RECOVERYCORE = ::rtl::OUString::createFromAscii("com.sun.star.frame.AutoRecovery"); + static const ::rtl::OUString PROP_CRASHED = ::rtl::OUString::createFromAscii("Crashed" ); + static const ::rtl::OUString PROP_EXISTSRECOVERY = ::rtl::OUString::createFromAscii("ExistsRecoveryData" ); + static const ::rtl::OUString PROP_EXISTSSESSION = ::rtl::OUString::createFromAscii("ExistsSessionData" ); + static const ::rtl::OUString CFG_PACKAGE_RECOVERY = ::rtl::OUString::createFromAscii("org.openoffice.Office.Recovery/"); + static const ::rtl::OUString CFG_PATH_RECOVERYINFO = ::rtl::OUString::createFromAscii("RecoveryInfo" ); + + bCrashed = sal_False; + bRecoveryDataExists = sal_False; + bSessionDataExists = sal_False; + + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + try + { + css::uno::Reference< css::beans::XPropertySet > xRecovery( + xSMGR->createInstance(SERVICENAME_RECOVERYCORE), + css::uno::UNO_QUERY_THROW); + + xRecovery->getPropertyValue(PROP_CRASHED ) >>= bCrashed ; + xRecovery->getPropertyValue(PROP_EXISTSRECOVERY) >>= bRecoveryDataExists; + xRecovery->getPropertyValue(PROP_EXISTSSESSION ) >>= bSessionDataExists ; + } + catch(const css::uno::Exception&) {} +} + +//----------------------------------------------- +/* @short start the recovery wizard. + + @param bEmergencySave + differs between EMERGENCY_SAVE and RECOVERY +*/ +sal_Bool impl_callRecoveryUI(sal_Bool bEmergencySave , + sal_Bool bCrashed , + sal_Bool bExistsRecoveryData) +{ + static ::rtl::OUString SERVICENAME_RECOVERYUI = ::rtl::OUString::createFromAscii("com.sun.star.comp.svx.RecoveryUI" ); + static ::rtl::OUString SERVICENAME_URLPARSER = ::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" ); + static ::rtl::OUString COMMAND_EMERGENCYSAVE = ::rtl::OUString::createFromAscii("vnd.sun.star.autorecovery:/doEmergencySave"); + static ::rtl::OUString COMMAND_RECOVERY = ::rtl::OUString::createFromAscii("vnd.sun.star.autorecovery:/doAutoRecovery" ); + static ::rtl::OUString COMMAND_CRASHREPORT = ::rtl::OUString::createFromAscii("vnd.sun.star.autorecovery:/doCrashReport" ); + + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + + css::uno::Reference< css::frame::XSynchronousDispatch > xRecoveryUI( + xSMGR->createInstance(SERVICENAME_RECOVERYUI), + css::uno::UNO_QUERY_THROW); + + css::uno::Reference< css::util::XURLTransformer > xURLParser( + xSMGR->createInstance(SERVICENAME_URLPARSER), + css::uno::UNO_QUERY_THROW); + + css::util::URL aURL; + if (bEmergencySave) + aURL.Complete = COMMAND_EMERGENCYSAVE; + else + { + if (bExistsRecoveryData) + aURL.Complete = COMMAND_RECOVERY; + else + if (bCrashed && Desktop::isCrashReporterEnabled() ) + aURL.Complete = COMMAND_CRASHREPORT; + } + + sal_Bool bRet = sal_False; + if ( aURL.Complete.getLength() > 0 ) + { + xURLParser->parseStrict(aURL); + + css::uno::Any aRet = xRecoveryUI->dispatchWithReturnValue(aURL, css::uno::Sequence< css::beans::PropertyValue >()); + aRet >>= bRet; + } + return bRet; +} + +/* + * Save all open documents so they will be reopened + * the next time the application ist started + * + * returns sal_True if at least one document could be saved... + * + */ + +sal_Bool Desktop::_bTasksSaved = sal_False; + +sal_Bool Desktop::SaveTasks() +{ + return impl_callRecoveryUI( + sal_True , // sal_True => force emergency save + sal_False, // 2. and 3. param not used if 1. = true! + sal_False); +} + +namespace { + +void restartOnMac(bool passArguments) { +#if defined MACOSX + OfficeIPCThread::DisableOfficeIPCThread(); + rtl::OUString execUrl; + OSL_VERIFY(osl_getExecutableFile(&execUrl.pData) == osl_Process_E_None); + rtl::OUString execPath; + rtl::OString execPath8; + if ((osl::FileBase::getSystemPathFromFileURL(execUrl, execPath) + != osl::FileBase::E_None) || + !execPath.convertToString( + &execPath8, osl_getThreadTextEncoding(), + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | + RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))) + { + std::abort(); + } + std::vector< rtl::OString > args; + args.push_back(execPath8); + bool wait = false; + if (passArguments) { + sal_uInt32 n = osl_getCommandArgCount(); + for (sal_uInt32 i = 0; i < n; ++i) { + rtl::OUString arg; + OSL_VERIFY(osl_getCommandArg(i, &arg.pData) == osl_Process_E_None); + if (arg.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("-accept="))) { + wait = true; + } + rtl::OString arg8; + if (!arg.convertToString( + &arg8, osl_getThreadTextEncoding(), + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | + RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))) + { + std::abort(); + } + args.push_back(arg8); + } + } + std::vector< char const * > argPtrs; + for (std::vector< rtl::OString >::iterator i(args.begin()); i != args.end(); + ++i) + { + argPtrs.push_back(i->getStr()); + } + argPtrs.push_back(0); + execv(execPath8.getStr(), const_cast< char ** >(&argPtrs[0])); + if (errno == ENOTSUP) { // happens when multithreaded on OS X < 10.6 + pid_t pid = fork(); + if (pid == 0) { + execv(execPath8.getStr(), const_cast< char ** >(&argPtrs[0])); + } else if (pid > 0) { + // Two simultaneously running soffice processes lead to two dock + // icons, so avoid waiting here unless it must be assumed that the + // process invoking soffice itself wants to wait for soffice to + // finish: + if (!wait) { + return; + } + int stat; + if (waitpid(pid, &stat, 0) == pid && WIFEXITED(stat)) { + _exit(WEXITSTATUS(stat)); + } + } + } + std::abort(); +#else + (void) passArguments; // avoid warnings +#endif +} + +} + +USHORT Desktop::Exception(USHORT nError) +{ + // protect against recursive calls + static BOOL bInException = FALSE; + + sal_uInt16 nOldMode = Application::GetSystemWindowMode(); + Application::SetSystemWindowMode( nOldMode & ~SYSTEMWINDOW_MODE_NOAUTOMODE ); + Application::SetDefDialogParent( NULL ); + + if ( bInException ) + { + String aDoubleExceptionString; + Application::Abort( aDoubleExceptionString ); + } + + bInException = TRUE; + CommandLineArgs* pArgs = GetCommandLineArgs(); + + // save all modified documents ... if it's allowed doing so. + sal_Bool bRestart = sal_False; + sal_Bool bAllowRecoveryAndSessionManagement = ( + ( !pArgs->IsNoRestore() ) && // some use cases of office must work without recovery + ( !pArgs->IsHeadless() ) && + ( !pArgs->IsServer() ) && + (( nError & EXC_MAJORTYPE ) != EXC_DISPLAY ) && // recovery cant work without UI ... but UI layer seams to be the reason for this crash + ( Application::IsInExecute() ) // crashes during startup and shutdown should be ignored (they indicates a corrupt installation ...) + ); + if ( bAllowRecoveryAndSessionManagement ) + bRestart = SaveTasks(); + + FlushConfiguration(); + + switch( nError & EXC_MAJORTYPE ) + { + case EXC_RSCNOTLOADED: + { + String aResExceptionString; + Application::Abort( aResExceptionString ); + break; + } + + case EXC_SYSOBJNOTCREATED: + { + String aSysResExceptionString; + Application::Abort( aSysResExceptionString ); + break; + } + + default: + { + if (m_pLockfile != NULL) { + m_pLockfile->clean(); + } + if( bRestart ) + { + OfficeIPCThread::DisableOfficeIPCThread(); + if( pSignalHandler ) + DELETEZ( pSignalHandler ); + restartOnMac(false); + _exit( ExitHelper::E_CRASH_WITH_RESTART ); + } + else + { + Application::Abort( String() ); + } + + break; + } + } + + OSL_ASSERT(false); // unreachable + return 0; +} + +void Desktop::AppEvent( const ApplicationEvent& rAppEvent ) +{ + HandleAppEvent( rAppEvent ); +} + +void Desktop::Main() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::Main" ); + + // Remember current context object + com::sun::star::uno::ContextLayer layer( + com::sun::star::uno::getCurrentContext() ); + + BootstrapError eError = GetBootstrapError(); + if ( eError != BE_OK ) + { + HandleBootstrapErrors( eError ); + return; + } + + BootstrapStatus eStatus = GetBootstrapStatus(); + if (eStatus == BS_TERMINATE) { + return; + } + + // Detect desktop environment - need to do this as early as possible + com::sun::star::uno::setCurrentContext( + new DesktopContext( com::sun::star::uno::getCurrentContext() ) ); + + CommandLineArgs* pCmdLineArgs = GetCommandLineArgs(); + + // setup configuration error handling + ConfigurationErrorHandler aConfigErrHandler; + if (!ShouldSuppressUI(pCmdLineArgs)) + aConfigErrHandler.activate(); + + ResMgr::SetReadStringHook( ReplaceStringHookProc ); + + // Startup screen + RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main { OpenSplashScreen" ); + OpenSplashScreen(); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main } OpenSplashScreen" ); + + { + UserInstall::UserInstallError instErr_fin = UserInstall::finalize(); + if ( instErr_fin != UserInstall::E_None) + { + OSL_ENSURE(sal_False, "userinstall failed"); + if ( instErr_fin == UserInstall::E_NoDiskSpace ) + HandleBootstrapErrors( BE_USERINSTALL_NOTENOUGHDISKSPACE ); + else if ( instErr_fin == UserInstall::E_NoWriteAccess ) + HandleBootstrapErrors( BE_USERINSTALL_NOWRITEACCESS ); + else + HandleBootstrapErrors( BE_USERINSTALL_FAILED ); + return; + } + // refresh path information + utl::Bootstrap::reloadData(); + SetSplashScreenProgress(25); + } + + Reference< XMultiServiceFactory > xSMgr = + ::comphelper::getProcessServiceFactory(); + + std::auto_ptr<SvtLanguageOptions> pLanguageOptions; + std::auto_ptr<SvtPathOptions> pPathOptions; + + Reference< ::com::sun::star::task::XRestartManager > xRestartManager; + sal_Bool bRestartRequested( sal_False ); + sal_Bool bUseSystemFileDialog(sal_True); + int nAcquireCount( 0 ); + Reference < css::document::XEventListener > xGlobalBroadcaster; + try + { + RegisterServices( xSMgr ); + + //SetSplashScreenProgress(15); + +#ifndef UNX + if ( pCmdLineArgs->IsHelp() ) { + displayCmdlineHelp(); + return; + } +#endif + + // check user installation directory for lockfile so we can be sure + // there is no other instance using our data files from a remote host + RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main -> Lockfile" ); + m_pLockfile = new Lockfile; + if ( !pCmdLineArgs->IsInvisible() && !pCmdLineArgs->IsNoLockcheck() && !m_pLockfile->check( Lockfile_execWarning )) { + // Lockfile exists, and user clicked 'no' + return; + } + RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main <- Lockfile" ); + + // check if accessibility is enabled but not working and allow to quit + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ GetEnableATToolSupport" ); + if( Application::GetSettings().GetMiscSettings().GetEnableATToolSupport() ) + { + BOOL bQuitApp; + + if( !InitAccessBridge( true, bQuitApp ) ) + if( bQuitApp ) + return; + } + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} GetEnableATToolSupport" ); + + // terminate if requested... + if( pCmdLineArgs->IsTerminateAfterInit() ) return; + + + // Read the common configuration items for optimization purpose + if ( !InitializeConfiguration() ) return; + + //SetSplashScreenProgress(20); + + // set static variable to enabled/disable crash reporter + retrieveCrashReporterState(); + if ( !isCrashReporterEnabled() ) + { + osl_setErrorReporting( sal_False ); + // disable stack trace feature + } + + // create title string + sal_Bool bCheckOk = sal_False; + ::com::sun::star::lang::Locale aLocale; + String aMgrName = String::CreateFromAscii( "iso" ); + ResMgr* pLabelResMgr = ResMgr::SearchCreateResMgr( U2S( aMgrName ), aLocale ); + if ( !pLabelResMgr ) + { + // no "iso" resource -> search for "ooo" resource + aMgrName = String::CreateFromAscii( "ooo" ); + pLabelResMgr = ResMgr::SearchCreateResMgr( U2S( aMgrName ), aLocale); + } + String aTitle = pLabelResMgr ? String( ResId( RID_APPTITLE, *pLabelResMgr ) ) : String(); + delete pLabelResMgr; +/* + // locale and UI locale in AppSettings are now retrieved from configuration or system directly via SvtSysLocale + // no reason to set while starting + // set UI language and locale + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ set locale settings" ); + //LanguageSelection langselect; + OUString aUILocaleString = LanguageSelection::getLanguageString(); + Locale aUILocale = LanguageSelection::IsoStringToLocale(aUILocaleString); + LanguageType eLanguage = SvtSysLocale().GetLanguage(); + + // #i39040#, do not call anything between GetSettings and SetSettings that might have + // a side effect on the settings (like, eg, SvtSysLocaleOptions().GetLocaleLanguageType(), + // which changes the MiscSettings !!! ) + AllSettings aSettings( Application::GetSettings() ); + aSettings.SetUILocale( aUILocale ); + aSettings.SetLanguage( eLanguage ); + Application::SetSettings( aSettings ); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} set locale settings" ); +*/ + + // Check for StarOffice/Suite specific extensions runs also with OpenOffice installation sets + OUString aTitleString( aTitle ); + bCheckOk = CheckInstallation( aTitleString ); + if ( !bCheckOk ) + return; + else + aTitle = aTitleString; + +#ifdef DBG_UTIL + //include version ID in non product builds + ::rtl::OUString aDefault; + aTitle += DEFINE_CONST_UNICODE(" ["); + String aVerId( utl::Bootstrap::getBuildIdData( aDefault )); + aTitle += aVerId; + aTitle += ']'; +#endif + + SetDisplayName( aTitle ); +// SetSplashScreenProgress(30); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ create SvtPathOptions and SvtLanguageOptions" ); + pPathOptions.reset( new SvtPathOptions); +// SetSplashScreenProgress(40); +// pLanguageOptions = new SvtLanguageOptions(sal_True); +// SetSplashScreenProgress(45); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} create SvtPathOptions and SvtLanguageOptions" ); + + // Check special env variable #111015# + std::vector< String > aUnrestrictedFolders; + svt::getUnrestrictedFolders( aUnrestrictedFolders ); + + if ( aUnrestrictedFolders.size() > 0 ) + { + // Set different working directory. The first entry is + // the new work path. + String aWorkPath = aUnrestrictedFolders[0]; + SvtPathOptions().SetWorkPath( aWorkPath ); + } + + // create service for loadin SFX (still needed in startup) + xGlobalBroadcaster = Reference < css::document::XEventListener > + ( xSMgr->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.frame.GlobalEventBroadcaster" ) ), UNO_QUERY ); + + /* ensure existance of a default window that messages can be dispatched to + This is for the benefit of testtool which uses PostUserEvent extensively + and else can deadlock while creating this window from another tread while + the main thread is not yet in the event loop. + */ + Application::GetDefaultDevice(); + + // initialize test-tool library (if available) + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ tools::InitTestToolLib" ); + tools::InitTestToolLib(); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} tools::InitTestToolLib" ); + + // Check if bundled or shared extensions were added /removed + // and process those extensions (has to be done before checking + // the extension dependencies! + SynchronizeExtensionRepositories(); + bool bAbort = CheckExtensionDependencies(); + if ( bAbort ) + return; + // First Start Wizard allowed ? + if ( ! pCmdLineArgs->IsNoFirstStartWizard()) + { + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ FirstStartWizard" ); + + if (IsFirstStartWizardNeeded()) + { + ::utl::RegOptions().removeReminder(); // remove patch registration reminder + Reference< XJob > xFirstStartJob( xSMgr->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.comp.desktop.FirstStart" ) ), UNO_QUERY ); + if (xFirstStartJob.is()) + { + sal_Bool bDone = sal_False; + Sequence< NamedValue > lArgs(2); + lArgs[0].Name = ::rtl::OUString::createFromAscii("LicenseNeedsAcceptance"); + lArgs[0].Value <<= LicenseNeedsAcceptance(); + lArgs[1].Name = ::rtl::OUString::createFromAscii("LicensePath"); + lArgs[1].Value <<= GetLicensePath(); + + xFirstStartJob->execute(lArgs) >>= bDone; + if ( !bDone ) + { + return; + } + } + } + else if ( RegistrationPage::hasReminderDateCome() ) + RegistrationPage::executeSingleMode(); + + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} FirstStartWizard" ); + } + + // keep a language options instance... + pLanguageOptions.reset( new SvtLanguageOptions(sal_True)); + + if (xGlobalBroadcaster.is()) + { + css::document::EventObject aEvent; + aEvent.EventName = ::rtl::OUString::createFromAscii("OnStartApp"); + xGlobalBroadcaster->notifyEvent(aEvent); + } + + SetSplashScreenProgress(50); + // Backing Component + sal_Bool bCrashed = sal_False; + sal_Bool bExistsRecoveryData = sal_False; + sal_Bool bExistsSessionData = sal_False; + + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ impl_checkRecoveryState" ); + impl_checkRecoveryState(bCrashed, bExistsRecoveryData, bExistsSessionData); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} impl_checkRecoveryState" ); + + { + ::comphelper::ComponentContext aContext( xSMgr ); + xRestartManager.set( aContext.getSingleton( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.OfficeRestartManager" ) ) ), UNO_QUERY ); + } + + // check whether the shutdown is caused by restart + bRestartRequested = ( xRestartManager.is() && xRestartManager->isRestartRequested( sal_True ) ); + + if ( pCmdLineArgs->IsHeadless() ) + { + // Ensure that we use not the system file dialogs as + // headless mode relies on Application::EnableHeadlessMode() + // which does only work for VCL dialogs!! + SvtMiscOptions aMiscOptions; + bUseSystemFileDialog = aMiscOptions.UseSystemFileDialog(); + aMiscOptions.SetUseSystemFileDialog( sal_False ); + } + + if ( !bRestartRequested ) + { + if ( + (pCmdLineArgs->IsEmptyOrAcceptOnly() ) && + (SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::E_SSTARTMODULE)) && + (!bExistsRecoveryData ) && + (!bExistsSessionData ) && + (!Application::AnyInput( INPUT_APPEVENT ) ) + ) + { + RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ create BackingComponent" ); + Reference< XFrame > xDesktopFrame( xSMgr->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ))), UNO_QUERY ); + if (xDesktopFrame.is()) + { + // SetSplashScreenProgress(60); + Reference< XFrame > xBackingFrame; + Reference< ::com::sun::star::awt::XWindow > xContainerWindow; + + xBackingFrame = xDesktopFrame->findFrame(OUString( RTL_CONSTASCII_USTRINGPARAM( "_blank" )), 0); + if (xBackingFrame.is()) + xContainerWindow = xBackingFrame->getContainerWindow(); + if (xContainerWindow.is()) + { + // set the WB_EXT_DOCUMENT style. Normally, this is done by the TaskCreator service when a "_blank" + // frame/window is created. Since we do not use the TaskCreator here, we need to mimic its behavior, + // otherwise documents loaded into this frame will later on miss functionality depending on the style. + Window* pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow ); + OSL_ENSURE( pContainerWindow, "Desktop::Main: no implementation access to the frame's container window!" ); + pContainerWindow->SetExtendedStyle( pContainerWindow->GetExtendedStyle() | WB_EXT_DOCUMENT ); + + SetSplashScreenProgress(75); + Sequence< Any > lArgs(1); + lArgs[0] <<= xContainerWindow; + + Reference< XController > xBackingComp( + xSMgr->createInstanceWithArguments(OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.StartModule") ), lArgs), + UNO_QUERY); + // SetSplashScreenProgress(80); + if (xBackingComp.is()) + { + Reference< ::com::sun::star::awt::XWindow > xBackingWin(xBackingComp, UNO_QUERY); + // Attention: You MUST(!) call setComponent() before you call attachFrame(). + // Because the backing component set the property "IsBackingMode" of the frame + // to true inside attachFrame(). But setComponent() reset this state everytimes ... + xBackingFrame->setComponent(xBackingWin, xBackingComp); + SetSplashScreenProgress(100); + xBackingComp->attachFrame(xBackingFrame); + CloseSplashScreen(); + xContainerWindow->setVisible(sal_True); + } + } + } + RTL_LOGFILE_CONTEXT_TRACE( aLog, "} create BackingComponent" ); + } + } + } + catch ( com::sun::star::lang::WrappedTargetException& wte ) + { + com::sun::star::uno::Exception te; + wte.TargetException >>= te; + FatalError( MakeStartupConfigAccessErrorMessage(wte.Message + te.Message) ); + return; + } + catch ( com::sun::star::uno::Exception& e ) + { + FatalError( MakeStartupErrorMessage(e.Message) ); + return; + } + /* + catch ( ... ) + { + FatalError( MakeStartupErrorMessage( + OUString::createFromAscii( + "Unknown error during startup (Office wrapper service).\nInstallation could be damaged."))); + return; + } + */ +// SetSplashScreenProgress(55); + + SvtFontSubstConfig().Apply(); + + SvtTabAppearanceCfg aAppearanceCfg; + aAppearanceCfg.SetInitialized(); + aAppearanceCfg.SetApplicationDefaults( this ); + SvtAccessibilityOptions aOptions; + aOptions.SetVCLSettings(); +// SetSplashScreenProgress(60); + + if ( !bRestartRequested ) + { + Application::SetFilterHdl( LINK( this, Desktop, ImplInitFilterHdl ) ); + + sal_Bool bTerminateRequested = sal_False; + + // Preload function depends on an initialized sfx application! + SetSplashScreenProgress(75); + + // use system window dialogs + Application::SetSystemWindowMode( SYSTEMWINDOW_MODE_DIALOG ); + + // SetSplashScreenProgress(80); + + if ( !bTerminateRequested && !pCmdLineArgs->IsInvisible() && + !pCmdLineArgs->IsNoQuickstart() ) + InitializeQuickstartMode( xSMgr ); + + RTL_LOGFILE_CONTEXT( aLog2, "desktop (cd100003) createInstance com.sun.star.frame.Desktop" ); + try + { + Reference< XDesktop > xDesktop( xSMgr->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ))), UNO_QUERY ); + if ( xDesktop.is() ) + xDesktop->addTerminateListener( new OfficeIPCThreadController ); + SetSplashScreenProgress(100); + } + catch ( com::sun::star::uno::Exception& e ) + { + FatalError( MakeStartupErrorMessage(e.Message) ); + return; + } + /* + catch ( ... ) + { + FatalError( MakeStartupErrorMessage( + OUString::createFromAscii( + "Unknown error during startup (TD/Desktop service).\nInstallation could be damaged."))); + return; + } + */ + + // Post user event to startup first application component window + // We have to send this OpenClients message short before execute() to + // minimize the risk that this message overtakes type detection contruction!! + Application::PostUserEvent( LINK( this, Desktop, OpenClients_Impl ) ); + + // Post event to enable acceptors + Application::PostUserEvent( LINK( this, Desktop, EnableAcceptors_Impl) ); + + // The configuration error handler currently is only for startup + aConfigErrHandler.deactivate(); + + // Acquire solar mutex just before we enter our message loop + if ( nAcquireCount ) + Application::AcquireSolarMutex( nAcquireCount ); + + // call Application::Execute to process messages in vcl message loop + RTL_LOGFILE_PRODUCT_TRACE( "PERFORMANCE - enter Application::Execute()" ); + + try + { + // The JavaContext contains an interaction handler which is used when + // the creation of a Java Virtual Machine fails + com::sun::star::uno::ContextLayer layer2( + new svt::JavaContext( com::sun::star::uno::getCurrentContext() ) ); + + // check whether the shutdown is caused by restart just before entering the Execute + bRestartRequested = bRestartRequested || ( xRestartManager.is() && xRestartManager->isRestartRequested( sal_True ) ); + + if ( !bRestartRequested ) + { + // if this run of the office is triggered by restart, some additional actions should be done + DoRestartActionsIfNecessary( !pCmdLineArgs->IsInvisible() && !pCmdLineArgs->IsNoQuickstart() ); + + Execute(); + } + } + catch(const com::sun::star::document::CorruptedFilterConfigurationException& exFilterCfg) + { + OfficeIPCThread::SetDowning(); + FatalError( MakeStartupErrorMessage(exFilterCfg.Message) ); + } + catch(const com::sun::star::configuration::CorruptedConfigurationException& exAnyCfg) + { + OfficeIPCThread::SetDowning(); + FatalError( MakeStartupErrorMessage(exAnyCfg.Message) ); + } + } + + if ( bRestartRequested ) + SetRestartState(); + + if (xGlobalBroadcaster.is()) + { + css::document::EventObject aEvent; + aEvent.EventName = ::rtl::OUString::createFromAscii("OnCloseApp"); + xGlobalBroadcaster->notifyEvent(aEvent); + } + + delete pResMgr; + // Restore old value + if ( pCmdLineArgs->IsHeadless() ) + SvtMiscOptions().SetUseSystemFileDialog( bUseSystemFileDialog ); + + // remove temp directory + RemoveTemporaryDirectory(); + FlushConfiguration(); + // The acceptors in the AcceptorMap must be released (in DeregisterServices) + // with the solar mutex unlocked, to avoid deadlock: + nAcquireCount = Application::ReleaseSolarMutex(); + DeregisterServices(); + Application::AcquireSolarMutex(nAcquireCount); + tools::DeInitTestToolLib(); + // be sure that path/language options gets destroyed before + // UCB is deinitialized + RTL_LOGFILE_CONTEXT_TRACE( aLog, "-> dispose path/language options" ); + pLanguageOptions.reset( 0 ); + pPathOptions.reset( 0 ); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- dispose path/language options" ); + + RTL_LOGFILE_CONTEXT_TRACE( aLog, "-> deinit ucb" ); + ::ucbhelper::ContentBroker::deinitialize(); + RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- deinit ucb" ); + + RTL_LOGFILE_CONTEXT_TRACE( aLog, "FINISHED WITH Destop::Main" ); + if ( bRestartRequested ) + { + restartOnMac(true); + // wouldn't the solution be more clean if SalMain returns the exit code to the system? + _exit( ExitHelper::E_NORMAL_RESTART ); + } +} + +IMPL_LINK( Desktop, ImplInitFilterHdl, ConvertData*, pData ) +{ + return GraphicFilter::GetGraphicFilter()->GetFilterCallback().Call( pData ); +} + +sal_Bool Desktop::InitializeConfiguration() +{ + sal_Bool bOk = sal_False; + + try + { + bOk = InitConfiguration(); + } + catch( ::com::sun::star::lang::ServiceNotRegisteredException& ) + { + this->HandleBootstrapErrors( Desktop::BE_UNO_SERVICE_CONFIG_MISSING ); + } + catch( ::com::sun::star::configuration::MissingBootstrapFileException& e ) + { + OUString aMsg( CreateErrorMsgString( utl::Bootstrap::MISSING_BOOTSTRAP_FILE, + e.BootstrapFileURL )); + HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_USER_INSTALL, aMsg ); + } + catch( ::com::sun::star::configuration::InvalidBootstrapFileException& e ) + { + OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY, + e.BootstrapFileURL )); + HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg ); + } + catch( ::com::sun::star::configuration::InstallationIncompleteException& ) + { + OUString aVersionFileURL; + OUString aMsg; + utl::Bootstrap::PathStatus aPathStatus = utl::Bootstrap::locateVersionFile( aVersionFileURL ); + if ( aPathStatus == utl::Bootstrap::PATH_EXISTS ) + aMsg = CreateErrorMsgString( utl::Bootstrap::MISSING_VERSION_FILE_ENTRY, aVersionFileURL ); + else + aMsg = CreateErrorMsgString( utl::Bootstrap::MISSING_VERSION_FILE, aVersionFileURL ); + + HandleBootstrapPathErrors( ::utl::Bootstrap::MISSING_USER_INSTALL, aMsg ); + } + catch ( com::sun::star::configuration::backend::BackendAccessException& exception) + { + // [cm122549] It is assumed in this case that the message + // coming from InitConfiguration (in fact CreateApplicationConf...) + // is suitable for display directly. + FatalError( MakeStartupErrorMessage( exception.Message ) ); + } + catch ( com::sun::star::configuration::backend::BackendSetupException& exception) + { + // [cm122549] It is assumed in this case that the message + // coming from InitConfiguration (in fact CreateApplicationConf...) + // is suitable for display directly. + FatalError( MakeStartupErrorMessage( exception.Message ) ); + } + catch ( ::com::sun::star::configuration::CannotLoadConfigurationException& ) + { + OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_DATA, + OUString() )); + HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg ); + } + catch( ::com::sun::star::uno::Exception& ) + { + OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_DATA, + OUString() )); + HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg ); + } + + return bOk; +} + +void Desktop::FlushConfiguration() +{ + Reference < XFlushable > xCFGFlush( ::utl::ConfigManager::GetConfigManager()->GetConfigurationProvider(), UNO_QUERY ); + if (xCFGFlush.is()) + { + xCFGFlush->flush(); + } + else + { + // because there is no method to flush the condiguration data, we must dispose the ConfigManager + Reference < XComponent > xCFGDispose( ::utl::ConfigManager::GetConfigManager()->GetConfigurationProvider(), UNO_QUERY ); + if (xCFGDispose.is()) + xCFGDispose->dispose(); + } +} + +sal_Bool Desktop::InitializeQuickstartMode( Reference< XMultiServiceFactory >& rSMgr ) +{ + try + { + // the shutdown icon sits in the systray and allows the user to keep + // the office instance running for quicker restart + // this will only be activated if -quickstart was specified on cmdline + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) createInstance com.sun.star.office.Quickstart" ); + + sal_Bool bQuickstart = GetCommandLineArgs()->IsQuickstart(); + Sequence< Any > aSeq( 1 ); + aSeq[0] <<= bQuickstart; + + // Try to instanciate quickstart service. This service is not mandatory, so + // do nothing if service is not available + + // #i105753# the following if was invented for performance + // unfortunately this broke the QUARTZ behavior which is to always run + // in quickstart mode since Mac applications do not usually quit + // when the last document closes + #ifndef QUARTZ + if ( bQuickstart ) + #endif + { + Reference < XComponent > xQuickstart( rSMgr->createInstanceWithArguments( + DEFINE_CONST_UNICODE( "com.sun.star.office.Quickstart" ), aSeq ), + UNO_QUERY ); + } + return sal_True; + } + catch( ::com::sun::star::uno::Exception& ) + { + return sal_False; + } +} + +void Desktop::SystemSettingsChanging( AllSettings& rSettings, Window* ) +{ + if ( !SvtTabAppearanceCfg::IsInitialized () ) + return; + +# define DRAGFULL_OPTION_ALL \ + ( DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE \ + | DRAGFULL_OPTION_OBJECTMOVE | DRAGFULL_OPTION_OBJECTSIZE \ + | DRAGFULL_OPTION_DOCKING | DRAGFULL_OPTION_SPLIT \ + | DRAGFULL_OPTION_SCROLL ) +# define DRAGFULL_OPTION_NONE ((sal_uInt32)~DRAGFULL_OPTION_ALL) + + StyleSettings hStyleSettings = rSettings.GetStyleSettings(); + MouseSettings hMouseSettings = rSettings.GetMouseSettings(); + + sal_uInt32 nDragFullOptions = hStyleSettings.GetDragFullOptions(); + + SvtTabAppearanceCfg aAppearanceCfg; + sal_uInt16 nGet = aAppearanceCfg.GetDragMode(); + switch ( nGet ) + { + case DragFullWindow: + nDragFullOptions |= DRAGFULL_OPTION_ALL; + break; + case DragFrame: + nDragFullOptions &= DRAGFULL_OPTION_NONE; + break; + case DragSystemDep: + default: + break; + } + + sal_uInt32 nFollow = hMouseSettings.GetFollow(); + hMouseSettings.SetFollow( aAppearanceCfg.IsMenuMouseFollow() ? (nFollow|MOUSE_FOLLOW_MENU) : (nFollow&~MOUSE_FOLLOW_MENU)); + rSettings.SetMouseSettings(hMouseSettings); + + BOOL bUseImagesInMenus = hStyleSettings.GetUseImagesInMenus(); + + SvtMenuOptions aMenuOpt; + nGet = aMenuOpt.GetMenuIconsState(); + switch ( nGet ) + { + case 0: + bUseImagesInMenus = FALSE; + break; + case 1: + bUseImagesInMenus = TRUE; + break; + case 2: + default: + break; + } + hStyleSettings.SetUseImagesInMenus(bUseImagesInMenus); + + sal_uInt16 nTabStyle = hStyleSettings.GetTabControlStyle(); + nTabStyle &= ~STYLE_TABCONTROL_SINGLELINE; + if( aAppearanceCfg.IsSingleLineTabCtrl() ) + nTabStyle |=STYLE_TABCONTROL_SINGLELINE; + + nTabStyle &= ~STYLE_TABCONTROL_COLOR; + if( aAppearanceCfg.IsColoredTabCtrl() ) + nTabStyle |= STYLE_TABCONTROL_COLOR; + + hStyleSettings.SetTabControlStyle(nTabStyle); + + hStyleSettings.SetDragFullOptions( nDragFullOptions ); + rSettings.SetStyleSettings ( hStyleSettings ); +} + +// ======================================================================== +IMPL_LINK( Desktop, AsyncInitFirstRun, void*, EMPTYARG ) +{ + DoFirstRunInitializations(); + return 0L; +} + +// ======================================================================== + +class ExitTimer : public Timer +{ + public: + ExitTimer() + { + SetTimeout(500); + Start(); + } + virtual void Timeout() + { + exit(42); + } +}; + +IMPL_LINK( Desktop, OpenClients_Impl, void*, EMPTYARG ) +{ + RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "PERFORMANCE - DesktopOpenClients_Impl()" ); + + OpenClients(); + + OfficeIPCThread::SetReady(); + + // CloseStartupScreen(); + CloseSplashScreen(); + + CheckFirstRun( ); + + // allow ipc interaction +// OfficeIPCThread::SetReady(); + + EnableOleAutomation(); + + if (getenv ("OOO_EXIT_POST_STARTUP")) + new ExitTimer(); + return 0; +} + +// enable acceptos +IMPL_LINK( Desktop, EnableAcceptors_Impl, void*, EMPTYARG ) +{ + enableAcceptors(); + return 0; +} + + +// Registers a COM class factory of the service manager with the windows operating system. +void Desktop::EnableOleAutomation() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (jl97489) ::Desktop::EnableOleAutomation" ); +#ifdef WNT + Reference< XMultiServiceFactory > xSMgr= comphelper::getProcessServiceFactory(); + xSMgr->createInstance(DEFINE_CONST_UNICODE("com.sun.star.bridge.OleApplicationRegistration")); + xSMgr->createInstance(DEFINE_CONST_UNICODE("com.sun.star.comp.ole.EmbedServer")); +#endif +} + +sal_Bool Desktop::CheckOEM() +{ + Reference<XMultiServiceFactory> rFactory = ::comphelper::getProcessServiceFactory(); + Reference<XJob> rOemJob(rFactory->createInstance( + OUString::createFromAscii("com.sun.star.office.OEMPreloadJob")), + UNO_QUERY ); + Sequence<NamedValue> args; + sal_Bool bResult = sal_False; + if (rOemJob.is()) { + Any aResult = rOemJob->execute(args); + aResult >>= bResult; + return bResult; + } else { + return sal_True; + } +} + +void Desktop::PreloadModuleData( CommandLineArgs* pArgs ) +{ + Reference< XMultiServiceFactory > rFactory = ::comphelper::getProcessServiceFactory(); + + Sequence < com::sun::star::beans::PropertyValue > args(1); + args[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Hidden")); + args[0].Value <<= sal_True; + Reference < XComponentLoader > xLoader( ::comphelper::getProcessServiceFactory()->createInstance( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), UNO_QUERY ); + + if ( !xLoader.is() ) + return; + + if ( pArgs->IsWriter() ) + { + try + { + Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/swriter"), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW ); + xDoc->close( sal_False ); + } + catch ( com::sun::star::uno::Exception& ) + { + } + } + if ( pArgs->IsCalc() ) + { + try + { + Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/scalc"), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW ); + xDoc->close( sal_False ); + } + catch ( com::sun::star::uno::Exception& ) + { + } + } + if ( pArgs->IsDraw() ) + { + try + { + Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/sdraw"), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW ); + xDoc->close( sal_False ); + } + catch ( com::sun::star::uno::Exception& ) + { + } + } + if ( pArgs->IsImpress() ) + { + try + { + Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/simpress"), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW ); + xDoc->close( sal_False ); + } + catch ( com::sun::star::uno::Exception& ) + { + } + } +} + +void Desktop::PreloadConfigurationData() +{ + Reference< XMultiServiceFactory > rFactory = ::comphelper::getProcessServiceFactory(); + Reference< XNameAccess > xNameAccess( rFactory->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.frame.UICommandDescription" )), UNO_QUERY ); + + rtl::OUString aWriterDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextDocument" )); + rtl::OUString aCalcDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.SpreadsheetDocument" )); + rtl::OUString aDrawDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.DrawingDocument" )); + rtl::OUString aImpressDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.PresentationDocument" )); + + // preload commands configuration + if ( xNameAccess.is() ) + { + Any a; + Reference< XNameAccess > xCmdAccess; + + try + { + a = xNameAccess->getByName( aWriterDoc ); + a >>= xCmdAccess; + if ( xCmdAccess.is() ) + { + xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:BasicShapes" )); + xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:EditGlossary" )); + } + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + + try + { + a = xNameAccess->getByName( aCalcDoc ); + a >>= xCmdAccess; + if ( xCmdAccess.is() ) + xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:InsertObjectStarMath" )); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + + try + { + // draw and impress share the same configuration file (DrawImpressCommands.xcu) + a = xNameAccess->getByName( aDrawDoc ); + a >>= xCmdAccess; + if ( xCmdAccess.is() ) + xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:Polygon" )); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + // preload window state configuration + xNameAccess = Reference< XNameAccess >( rFactory->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.ui.WindowStateConfiguration" )), UNO_QUERY ); + if ( xNameAccess.is() ) + { + Any a; + Reference< XNameAccess > xWindowAccess; + try + { + a = xNameAccess->getByName( aWriterDoc ); + a >>= xWindowAccess; + if ( xWindowAccess.is() ) + xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" )); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + try + { + a = xNameAccess->getByName( aCalcDoc ); + a >>= xWindowAccess; + if ( xWindowAccess.is() ) + xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" )); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + try + { + a = xNameAccess->getByName( aDrawDoc ); + a >>= xWindowAccess; + if ( xWindowAccess.is() ) + xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" )); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + try + { + a = xNameAccess->getByName( aImpressDoc ); + a >>= xWindowAccess; + if ( xWindowAccess.is() ) + xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" )); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + // preload user interface element factories + Sequence< Sequence< css::beans::PropertyValue > > aSeqSeqPropValue; + Reference< ::com::sun::star::ui::XUIElementFactoryRegistration > xUIElementFactory( + rFactory->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.ui.UIElementFactoryManager" )), + UNO_QUERY ); + if ( xUIElementFactory.is() ) + { + try + { + aSeqSeqPropValue = xUIElementFactory->getRegisteredFactories(); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + // preload popup menu controller factories. As all controllers are in the same + // configuration file they also get preloaded! + Reference< ::com::sun::star::frame::XUIControllerRegistration > xPopupMenuControllerFactory( + rFactory->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.frame.PopupMenuControllerFactory" )), + UNO_QUERY ); + if ( xPopupMenuControllerFactory.is() ) + { + try + { + xPopupMenuControllerFactory->hasController( + DEFINE_CONST_UNICODE( ".uno:CharFontName" ), + OUString() ); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + // preload filter configuration + Sequence< OUString > aSeq; + xNameAccess = Reference< XNameAccess >( rFactory->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.document.FilterFactory" )), UNO_QUERY ); + if ( xNameAccess.is() ) + { + try + { + aSeq = xNameAccess->getElementNames(); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + // preload type detection configuration + xNameAccess = Reference< XNameAccess >( rFactory->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.document.TypeDetection" )), UNO_QUERY ); + if ( xNameAccess.is() ) + { + try + { + aSeq = xNameAccess->getElementNames(); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + static const OUString sConfigSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) ); + static const OUString sAccessSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationAccess" ) ); + + // get configuration provider + Reference< XMultiServiceFactory > xConfigProvider; + xConfigProvider = Reference< XMultiServiceFactory > ( + rFactory->createInstance( sConfigSrvc ),UNO_QUERY ); + + if ( xConfigProvider.is() ) + { + // preload writer configuration + Sequence< Any > theArgs(1); + theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Writer/MailMergeWizard" ); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // WriterWeb + theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.WriterWeb/Content" ); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // preload compatibility + theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Compatibility/WriterCompatibilityVersion" ); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // preload calc configuration + theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Calc/Content" ); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // preload impress configuration + theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.UI.Effects/UserInterface" ); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Impress/Layout" ); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // preload draw configuration + theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Draw/Layout" ); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // preload ui configuration + theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.UI/FilterClassification" ); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + + // preload addons configuration + theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Addons/AddonUI" ); + try + { + xNameAccess = Reference< XNameAccess >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY ); + } + catch (::com::sun::star::uno::Exception& ) + { + } + } +} + +void Desktop::OpenClients() +{ + + // check if a document has been recovered - if there is one of if a document was loaded by cmdline, no default document + // should be created + Reference < XComponent > xFirst; + BOOL bLoaded = FALSE; + + CommandLineArgs* pArgs = GetCommandLineArgs(); + SvtInternalOptions aInternalOptions; + + Reference<XMultiServiceFactory> rFactory = ::comphelper::getProcessServiceFactory(); + + if (!pArgs->IsQuickstart()) { + sal_Bool bShowHelp = sal_False; + ::rtl::OUStringBuffer aHelpURLBuffer; + if (pArgs->IsHelpWriter()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://swriter/start"); + } else if (pArgs->IsHelpCalc()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://scalc/start"); + } else if (pArgs->IsHelpDraw()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdraw/start"); + } else if (pArgs->IsHelpImpress()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://simpress/start"); + } else if (pArgs->IsHelpBase()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdatabase/start"); + } else if (pArgs->IsHelpBasic()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://sbasic/start"); + } else if (pArgs->IsHelpMath()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://smath/start"); + } + if (bShowHelp) { + Help *pHelp = Application::GetHelp(); + + Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::LOCALE ); + rtl::OUString aTmp; + aRet >>= aTmp; + aHelpURLBuffer.appendAscii("?Language="); + aHelpURLBuffer.append(aTmp); +#if defined UNX + aHelpURLBuffer.appendAscii("&System=UNX"); +#elif defined WNT + aHelpURLBuffer.appendAscii("&System=WIN"); +#elif defined MAC + aHelpURLBuffer.appendAscii("&System=MAC"); +#elif defined OS2 + aHelpURLBuffer.appendAscii("&System=OS2"); +#endif + pHelp->Start(aHelpURLBuffer.makeStringAndClear(), NULL); + return; + } + } + else + { + OUString aIniName; + ::vos::OStartupInfo aInfo; + + aInfo.getExecutableFile( aIniName ); + sal_uInt32 lastIndex = aIniName.lastIndexOf('/'); + if ( lastIndex > 0 ) + { + aIniName = aIniName.copy( 0, lastIndex+1 ); + aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( "perftune" )); +#if defined(WNT) || defined(OS2) + aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( ".ini" )); +#else + aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( "rc" )); +#endif + } + + rtl::Bootstrap aPerfTuneIniFile( aIniName ); + + OUString aDefault( RTL_CONSTASCII_USTRINGPARAM( "0" )); + OUString aPreloadData; + + aPerfTuneIniFile.getFrom( OUString( RTL_CONSTASCII_USTRINGPARAM( "QuickstartPreloadConfiguration" )), aPreloadData, aDefault ); + if ( aPreloadData.equalsAscii( "1" )) + { + if ( pArgs->IsWriter() || + pArgs->IsCalc() || + pArgs->IsDraw() || + pArgs->IsImpress() ) + { + PreloadModuleData( pArgs ); + } + + PreloadConfigurationData(); + } + } + + // Disable AutoSave feature in case "-norestore" or a similare command line switch is set on the command line. + // The reason behind: AutoSave/EmergencySave/AutoRecovery share the same data. + // But the require that all documents, which are saved as backup should exists inside + // memory. May be this mechanism will be inconsistent if the configuration exists ... + // but no document inside memory corrspond to this data. + // Furter it's not acceptable to recover such documents without any UI. It can + // need some time, where the user wont see any results and wait for finishing the office startup ... + sal_Bool bAllowRecoveryAndSessionManagement = ( + ( !pArgs->IsNoRestore() ) && + ( !pArgs->IsHeadless() ) && + ( !pArgs->IsServer() ) + ); + + if ( ! bAllowRecoveryAndSessionManagement ) + { + /* + ::comphelper::ConfigurationHelper::writeDirectKey( + ::comphelper::getProcessServiceFactory(), + ::rtl::OUString::createFromAscii("org.openoffice.Office.Recovery"), + ::rtl::OUString::createFromAscii("AutoSave"), + ::rtl::OUString::createFromAscii("Enabled"), + ::com::sun::star::uno::makeAny(sal_False), + ::comphelper::ConfigurationHelper::E_STANDARD); + + */ + try + { + Reference< XDispatch > xRecovery( + ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.AutoRecovery")) ), + ::com::sun::star::uno::UNO_QUERY_THROW ); + + Reference< XURLTransformer > xParser( + ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer")) ), + ::com::sun::star::uno::UNO_QUERY_THROW ); + + css::util::URL aCmd; + aCmd.Complete = ::rtl::OUString::createFromAscii("vnd.sun.star.autorecovery:/disableRecovery"); + xParser->parseStrict(aCmd); + + xRecovery->dispatch(aCmd, css::uno::Sequence< css::beans::PropertyValue >()); + } + catch(const css::uno::Exception& e) + { + OUString aMessage = OUString::createFromAscii("Could not disable AutoRecovery.\n") + + e.Message; + OSL_ENSURE(sal_False, OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr()); + } + } + else + { + sal_Bool bCrashed = sal_False; + sal_Bool bExistsRecoveryData = sal_False; + sal_Bool bExistsSessionData = sal_False; + + impl_checkRecoveryState(bCrashed, bExistsRecoveryData, bExistsSessionData); + + if ( !getenv ("OOO_DISABLE_RECOVERY") && + ( ! bLoaded ) && + ( + ( bExistsRecoveryData ) || // => crash with files => recovery + ( bCrashed ) // => crash without files => error report + ) + ) + { + try + { + impl_callRecoveryUI( + sal_False , // false => force recovery instead of emergency save + bCrashed , + bExistsRecoveryData); + /* TODO we cant be shure, that at least one document could be recovered here successfully + So we set bLoaded=TRUE to supress opening of the default document. + But we should make it more safe. Otherwhise we have an office without an UI ... + ... + May be we can check the desktop if some documents are existing there. + */ + Reference< XFramesSupplier > xTasksSupplier( + ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + ::com::sun::star::uno::UNO_QUERY_THROW ); + Reference< XElementAccess > xList( xTasksSupplier->getFrames(), UNO_QUERY_THROW ); + if ( xList->hasElements() ) + bLoaded = sal_True; + } + catch(const css::uno::Exception& e) + { + OUString aMessage = OUString::createFromAscii("Error during recovery\n") + + e.Message; + OSL_ENSURE(sal_False, OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr()); + } + } + + Reference< XInitialization > xSessionListener; + try + { + xSessionListener = Reference< XInitialization >(::comphelper::getProcessServiceFactory()->createInstance( + OUString::createFromAscii("com.sun.star.frame.SessionListener")), UNO_QUERY_THROW); + + // specifies whether the UI-interaction on Session shutdown is allowed + sal_Bool bAllowUI = isUIOnSessionShutdownAllowed(); + css::beans::NamedValue aProperty( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AllowUserInteractionOnQuit" ) ), + css::uno::makeAny( bAllowUI ) ); + css::uno::Sequence< css::uno::Any > aArgs( 1 ); + aArgs[0] <<= aProperty; + + xSessionListener->initialize( aArgs ); + } + catch(const com::sun::star::uno::Exception& e) + { + OUString aMessage = OUString::createFromAscii("Registration of session listener failed\n") + + e.Message; + OSL_ENSURE(sal_False, OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr()); + } + + if ( + ( ! bLoaded ) && + ( bExistsSessionData ) + ) + { + // session management + try + { + Reference< XSessionManagerListener > r(xSessionListener, UNO_QUERY_THROW); + bLoaded = r->doRestore(); + } + catch(const com::sun::star::uno::Exception& e) + { + OUString aMessage = OUString::createFromAscii("Error in session management\n") + + e.Message; + OSL_ENSURE(sal_False, OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr()); + } + } + } + + OfficeIPCThread::EnableRequests(); + + sal_Bool bShutdown( sal_False ); + if ( !pArgs->IsServer() ) + { + ProcessDocumentsRequest aRequest(pArgs->getCwdUrl()); + aRequest.pcProcessed = NULL; + + pArgs->GetOpenList( aRequest.aOpenList ); + pArgs->GetViewList( aRequest.aViewList ); + pArgs->GetStartList( aRequest.aStartList ); + pArgs->GetPrintList( aRequest.aPrintList ); + pArgs->GetPrintToList( aRequest.aPrintToList ); + pArgs->GetPrinterName( aRequest.aPrinterName ); + pArgs->GetForceOpenList( aRequest.aForceOpenList ); + pArgs->GetForceNewList( aRequest.aForceNewList ); + + if ( aRequest.aOpenList.getLength() > 0 || + aRequest.aViewList.getLength() > 0 || + aRequest.aStartList.getLength() > 0 || + aRequest.aPrintList.getLength() > 0 || + aRequest.aForceOpenList.getLength() > 0 || + aRequest.aForceNewList.getLength() > 0 || + ( aRequest.aPrintToList.getLength() > 0 && aRequest.aPrinterName.getLength() > 0 )) + { + bLoaded = sal_True; + + if ( pArgs->HasModuleParam() ) + { + SvtModuleOptions aOpt; + + // Support command line parameters to start a module (as preselection) + if ( pArgs->IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + aRequest.aModule = aOpt.GetFactoryName( SvtModuleOptions::E_WRITER ); + else if ( pArgs->IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) ) + aRequest.aModule = aOpt.GetFactoryName( SvtModuleOptions::E_CALC ); + else if ( pArgs->IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) ) + aRequest.aModule= aOpt.GetFactoryName( SvtModuleOptions::E_IMPRESS ); + else if ( pArgs->IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) ) + aRequest.aModule= aOpt.GetFactoryName( SvtModuleOptions::E_DRAW ); + } + + // check for printing disabled + if( ( aRequest.aPrintList.getLength() || aRequest.aPrintToList.getLength() ) + && Application::GetSettings().GetMiscSettings().GetDisablePrinting() ) + { + aRequest.aPrintList = rtl::OUString(); + aRequest.aPrintToList = rtl::OUString(); + ResMgr* pDtResMgr = GetDesktopResManager(); + if( pDtResMgr ) + { + ErrorBox aBox( NULL, ResId( EBX_ERR_PRINTDISABLED, *pDtResMgr ) ); + aBox.Execute(); + } + } + + // Process request + bShutdown = OfficeIPCThread::ExecuteCmdLineRequests( aRequest ); + } + } + + // Don't do anything if we have successfully called terminate at desktop + if ( bShutdown ) + return; + + // no default document if a document was loaded by recovery or by command line or if soffice is used as server + Reference< XFramesSupplier > xTasksSupplier( + ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + ::com::sun::star::uno::UNO_QUERY_THROW ); + Reference< XElementAccess > xList( xTasksSupplier->getFrames(), UNO_QUERY_THROW ); + if ( xList->hasElements() || pArgs->IsServer() ) + return; + + if ( pArgs->IsQuickstart() || pArgs->IsInvisible() || pArgs->IsBean() || Application::AnyInput( INPUT_APPEVENT ) ) + // soffice was started as tray icon ... + return; + { + OpenDefault(); + } +} + +void Desktop::OpenDefault() +{ + + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::OpenDefault" ); + + ::rtl::OUString aName; + SvtModuleOptions aOpt; + + CommandLineArgs* pArgs = GetCommandLineArgs(); + if ( pArgs->IsNoDefault() ) return; + if ( pArgs->HasModuleParam() ) + { + // Support new command line parameters to start a module + if ( pArgs->IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITER ); + else if ( pArgs->IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_CALC ); + else if ( pArgs->IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_IMPRESS ); + else if ( pArgs->IsBase() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DATABASE ); + else if ( pArgs->IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DRAW ); + else if ( pArgs->IsMath() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SMATH ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_MATH ); + else if ( pArgs->IsGlobal() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITERGLOBAL ); + else if ( pArgs->IsWeb() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITERWEB ); + } + + if ( !aName.getLength() ) + { + // Old way to create a default document + if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITER ); + else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_CALC ); + else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_IMPRESS ); + else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DATABASE ); + else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) ) + aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DRAW ); + else + return; + } + + ProcessDocumentsRequest aRequest(pArgs->getCwdUrl()); + aRequest.pcProcessed = NULL; + aRequest.aOpenList = aName; + OfficeIPCThread::ExecuteCmdLineRequests( aRequest ); +} + + +String GetURL_Impl( + const String& rName, boost::optional< rtl::OUString > const & cwdUrl ) +{ + // if rName is a vnd.sun.star.script URL do not attempt to parse it + // as INetURLObj does not handle handle there URLs + if (rName.CompareToAscii("vnd.sun.star.script" , 19) == COMPARE_EQUAL) + { + return rName; + } + + // dont touch file urls, those should already be in internal form + // they won't get better here (#112849#) + if (rName.CompareToAscii("file:" , 5) == COMPARE_EQUAL) + { + return rName; + } + + if ( rName.CompareToAscii("service:" , 8) == COMPARE_EQUAL ) + { + return rName; + } + + // Add path seperator to these directory and make given URL (rName) absolute by using of current working directory + // Attention: "setFianlSlash()" is neccessary for calling "smartRel2Abs()"!!! + // Otherwhise last part will be ignored and wrong result will be returned!!! + // "smartRel2Abs()" interpret given URL as file not as path. So he truncate last element to get the base path ... + // But if we add a seperator - he doesn't do it anymore. + INetURLObject aObj; + if (cwdUrl) { + aObj.SetURL(*cwdUrl); + aObj.setFinalSlash(); + } + + // Use the provided parameters for smartRel2Abs to support the usage of '%' in system paths. + // Otherwise this char won't get encoded and we are not able to load such files later, + // see #110156# + bool bWasAbsolute; + INetURLObject aURL = aObj.smartRel2Abs( rName, bWasAbsolute, false, INetURLObject::WAS_ENCODED, + RTL_TEXTENCODING_UTF8, true ); + String aFileURL = aURL.GetMainURL(INetURLObject::NO_DECODE); + + ::osl::FileStatus aStatus( FileStatusMask_FileURL ); + ::osl::DirectoryItem aItem; + if( ::osl::FileBase::E_None == ::osl::DirectoryItem::get( aFileURL, aItem ) && + ::osl::FileBase::E_None == aItem.getFileStatus( aStatus ) ) + aFileURL = aStatus.getFileURL(); + + return aFileURL; +} + +void Desktop::HandleAppEvent( const ApplicationEvent& rAppEvent ) +{ + if ( rAppEvent.GetEvent() == "APPEAR" && !GetCommandLineArgs()->IsInvisible() ) + { + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + + // find active task - the active task is always a visible task + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFramesSupplier > + xDesktop( xSMGR->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + ::com::sun::star::uno::UNO_QUERY ); + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xTask = xDesktop->getActiveFrame(); + if ( !xTask.is() ) + { + // get any task if there is no active one + ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > xList( xDesktop->getFrames(), ::com::sun::star::uno::UNO_QUERY ); + if ( xList->getCount()>0 ) + xList->getByIndex(0) >>= xTask; + } + + if ( xTask.is() ) + { + Reference< com::sun::star::awt::XTopWindow > xTop( xTask->getContainerWindow(), UNO_QUERY ); + xTop->toFront(); + } + else + { + // no visible task that could be activated found + Reference< XFrame > xBackingFrame; + Reference< ::com::sun::star::awt::XWindow > xContainerWindow; + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xDesktopFrame( xDesktop, UNO_QUERY ); + + xBackingFrame = xDesktopFrame->findFrame(OUString( RTL_CONSTASCII_USTRINGPARAM( "_blank" )), 0); + if (xBackingFrame.is()) + xContainerWindow = xBackingFrame->getContainerWindow(); + if (xContainerWindow.is()) + { + Sequence< Any > lArgs(1); + lArgs[0] <<= xContainerWindow; + Reference< XController > xBackingComp( + xSMGR->createInstanceWithArguments(OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.StartModule") ), lArgs), + UNO_QUERY); + if (xBackingComp.is()) + { + Reference< ::com::sun::star::awt::XWindow > xBackingWin(xBackingComp, UNO_QUERY); + // Attention: You MUST(!) call setComponent() before you call attachFrame(). + // Because the backing component set the property "IsBackingMode" of the frame + // to true inside attachFrame(). But setComponent() reset this state everytimes ... + xBackingFrame->setComponent(xBackingWin, xBackingComp); + xBackingComp->attachFrame(xBackingFrame); + xContainerWindow->setVisible(sal_True); + + Window* pCompWindow = VCLUnoHelper::GetWindow(xBackingFrame->getComponentWindow()); + if (pCompWindow) + pCompWindow->Update(); + } + } + } + } + else if ( rAppEvent.GetEvent() == "QUICKSTART" && !GetCommandLineArgs()->IsInvisible() ) + { + // If the office has been started the second time its command line arguments are sent through a pipe + // connection to the first office. We want to reuse the quickstart option for the first office. + // NOTICE: The quickstart service must be initialized inside the "main thread", so we use the + // application events to do this (they are executed inside main thread)!!! + // Don't start quickstart service if the user specified "-invisible" on the command line! + sal_Bool bQuickstart( sal_True ); + Sequence< Any > aSeq( 1 ); + aSeq[0] <<= bQuickstart; + + Reference < XInitialization > xQuickstart( ::comphelper::getProcessServiceFactory()->createInstance( + DEFINE_CONST_UNICODE( "com.sun.star.office.Quickstart" )), + UNO_QUERY ); + if ( xQuickstart.is() ) + xQuickstart->initialize( aSeq ); + } + else if ( rAppEvent.GetEvent() == "ACCEPT" ) + { + // every time an accept parameter is used we create an acceptor + // with the corresponding accept-string + OUString aAcceptString(rAppEvent.GetData().GetBuffer()); + createAcceptor(aAcceptString); + } + else if ( rAppEvent.GetEvent() == "UNACCEPT" ) + { + // try to remove corresponding acceptor + OUString aUnAcceptString(rAppEvent.GetData().GetBuffer()); + destroyAcceptor(aUnAcceptString); + } + else if ( rAppEvent.GetEvent() == "SaveDocuments" ) + { + Desktop::_bTasksSaved = sal_False; + Desktop::_bTasksSaved = SaveTasks(); + } + else if ( rAppEvent.GetEvent() == "OPENHELPURL" ) + { + // start help for a specific URL + OUString aHelpURL(rAppEvent.GetData().GetBuffer()); + Help *pHelp = Application::GetHelp(); + pHelp->Start(aHelpURL, NULL); + } + else if ( rAppEvent.GetEvent() == APPEVENT_OPEN_STRING ) + { + OUString aOpenURL(rAppEvent.GetData().GetBuffer()); + + CommandLineArgs* pCmdLine = GetCommandLineArgs(); + if ( !pCmdLine->IsInvisible() && !pCmdLine->IsTerminateAfterInit() ) + { + ProcessDocumentsRequest* pDocsRequest = new ProcessDocumentsRequest( + pCmdLine->getCwdUrl()); + pDocsRequest->aOpenList = aOpenURL; + pDocsRequest->pcProcessed = NULL; + + OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest ); + delete pDocsRequest; + } + } + else if ( rAppEvent.GetEvent() == APPEVENT_PRINT_STRING ) + { + OUString aPrintURL(rAppEvent.GetData().GetBuffer()); + + CommandLineArgs* pCmdLine = GetCommandLineArgs(); + if ( !pCmdLine->IsInvisible() && !pCmdLine->IsTerminateAfterInit() ) + { + ProcessDocumentsRequest* pDocsRequest = new ProcessDocumentsRequest( + pCmdLine->getCwdUrl()); + pDocsRequest->aPrintList = aPrintURL; + pDocsRequest->pcProcessed = NULL; + + OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest ); + delete pDocsRequest; + } + } +#ifndef UNX + else if ( rAppEvent.GetEvent() == "HELP" ) + { + // in non unix version allow showing of cmdline help window + displayCmdlineHelp(); + } +#endif + else if ( rAppEvent.GetEvent() == "SHOWDIALOG" ) + { + // ignore all errors here. It's clicking a menu entry only ... + // The user will try it again, in case nothing happens .-) + try + { + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + + com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > + xDesktop( xSMGR->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + ::com::sun::star::uno::UNO_QUERY ); + + // check provider ... we know it's weak reference only + if ( ! xDesktop.is()) + return; + + css::uno::Reference< css::util::XURLTransformer > xParser(xSMGR->createInstance(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer"))), css::uno::UNO_QUERY_THROW); + css::util::URL aCommand; + if( rAppEvent.GetData().EqualsAscii( "PREFERENCES" ) ) + aCommand.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:OptionsTreeDialog" ) ); + else if( rAppEvent.GetData().EqualsAscii( "ABOUT" ) ) + aCommand.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:About" ) ); + if( aCommand.Complete.getLength() ) + { + xParser->parseStrict(aCommand); + + css::uno::Reference< css::frame::XDispatch > xDispatch = xDesktop->queryDispatch(aCommand, rtl::OUString(), 0); + if (xDispatch.is()) + xDispatch->dispatch(aCommand, css::uno::Sequence< css::beans::PropertyValue >()); + } + } + catch(const css::uno::Exception&) + {} + } +} + +void Desktop::OpenSplashScreen() +{ + ::rtl::OUString aTmpString; + CommandLineArgs* pCmdLine = GetCommandLineArgs(); + sal_Bool bVisible = sal_False; + // Show intro only if this is normal start (e.g. no server, no quickstart, no printing ) + if ( !pCmdLine->IsInvisible() && + !pCmdLine->IsQuickstart() && + !pCmdLine->IsMinimized() && + !pCmdLine->IsNoLogo() && + !pCmdLine->IsTerminateAfterInit() && + !pCmdLine->GetPrintList( aTmpString ) && + !pCmdLine->GetPrintToList( aTmpString ) ) + { + // Determine application name from command line parameters + OUString aAppName; + if ( pCmdLine->IsWriter() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "writer" )); + else if ( pCmdLine->IsCalc() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "calc" )); + else if ( pCmdLine->IsDraw() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "draw" )); + else if ( pCmdLine->IsImpress() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "impress" )); + else if ( pCmdLine->IsBase() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "base" )); + else if ( pCmdLine->IsGlobal() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "global" )); + else if ( pCmdLine->IsMath() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "math" )); + else if ( pCmdLine->IsWeb() ) + aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "web" )); + + bVisible = sal_True; + Sequence< Any > aSeq( 2 ); + aSeq[0] <<= bVisible; + aSeq[1] <<= aAppName; + m_rSplashScreen = Reference<XStatusIndicator>( + comphelper::getProcessServiceFactory()->createInstanceWithArguments( + OUString::createFromAscii("com.sun.star.office.SplashScreen"), + aSeq), UNO_QUERY); + + if(m_rSplashScreen.is()) + m_rSplashScreen->start(OUString::createFromAscii("SplashScreen"), 100); + } + +} + +void Desktop::SetSplashScreenProgress(sal_Int32 iProgress) +{ + if(m_rSplashScreen.is()) + { + m_rSplashScreen->setValue(iProgress); + } +} + +void Desktop::SetSplashScreenText( const ::rtl::OUString& rText ) +{ + if( m_rSplashScreen.is() ) + { + m_rSplashScreen->setText( rText ); + } +} + +void Desktop::CloseSplashScreen() +{ + if(m_rSplashScreen.is()) + { + m_rSplashScreen->end(); + m_rSplashScreen = NULL; + } +} + +// ======================================================================== +void Desktop::DoFirstRunInitializations() +{ + try + { + Reference< XJobExecutor > xExecutor( ::comphelper::getProcessServiceFactory()->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.task.JobExecutor" ) ), UNO_QUERY ); + if( xExecutor.is() ) + xExecutor->trigger( ::rtl::OUString::createFromAscii("onFirstRunInitialization") ); + } + catch(const ::com::sun::star::uno::Exception&) + { + OSL_ENSURE( sal_False, "Desktop::DoFirstRunInitializations: caught an exception while trigger job executor ..." ); + } +} + +// ======================================================================== +void Desktop::CheckFirstRun( ) +{ + const ::rtl::OUString sCommonMiscNodeName = ::rtl::OUString::createFromAscii( "/org.openoffice.Office.Common/Misc" ); + const ::rtl::OUString sFirstRunNodeName = ::rtl::OUString::createFromAscii( "FirstRun" ); + + // -------------------------------------------------------------------- + // check if this is the first office start + + // for this, open the Common/Misc node where this info is stored + ::utl::OConfigurationTreeRoot aCommonMisc = ::utl::OConfigurationTreeRoot::createWithServiceFactory( + ::comphelper::getProcessServiceFactory( ), + sCommonMiscNodeName, + 2, + ::utl::OConfigurationTreeRoot::CM_UPDATABLE + ); + + // read the flag + OSL_ENSURE( aCommonMisc.isValid(), "Desktop::CheckFirstRun: could not open the config node needed!" ); + sal_Bool bIsFirstRun = sal_False; + aCommonMisc.getNodeValue( sFirstRunNodeName ) >>= bIsFirstRun; + + if ( !bIsFirstRun ) + // nothing to do .... + return; + + // -------------------------------------------------------------------- + // it is the first run + // this has once been done using a vos timer. this could lead to problems when + // the timer would trigger when the app is already going down again, since VCL would + // no longer be available. Since the old handler would do a postUserEvent to the main + // thread anyway, we can use a vcl timer here to prevent the race contition (#107197#) + m_firstRunTimer.SetTimeout(3000); // 3 sec. + m_firstRunTimer.SetTimeoutHdl(LINK(this, Desktop, AsyncInitFirstRun)); + m_firstRunTimer.Start(); + + // -------------------------------------------------------------------- + // reset the config flag + + // set the value + aCommonMisc.setNodeValue( sFirstRunNodeName, makeAny( (sal_Bool)sal_False ) ); + // commit the changes + aCommonMisc.commit(); +} + +} diff --git a/desktop/source/app/appfirststart.cxx b/desktop/source/app/appfirststart.cxx new file mode 100644 index 000000000000..c06d94fd0812 --- /dev/null +++ b/desktop/source/app/appfirststart.cxx @@ -0,0 +1,318 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include <osl/file.hxx> +#include <rtl/bootstrap.hxx> +#include <rtl/ustring.hxx> +#include <tools/datetime.hxx> +#include <unotools/configmgr.hxx> + +#include <comphelper/processfactory.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> + +#include "app.hxx" + +using ::rtl::OUString; +using namespace ::desktop; +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; + +static const OUString sConfigSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) ); +static const OUString sAccessSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) ); + +/* Path of the license. */ +OUString Desktop::GetLicensePath() +{ + // license file name + static const char *szLicensePath = "/share/readme"; +#if defined(WNT) || defined(OS2) + static const char *szWNTLicenseName = "/license"; + static const char *szWNTLicenseExt = ".txt"; +#else + static const char *szUNXLicenseName = "/LICENSE"; + static const char *szUNXLicenseExt = ""; +#endif + static OUString aLicensePath; + + if (aLicensePath.getLength() > 0) + return aLicensePath; + + OUString aBaseInstallPath(RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR")); + rtl::Bootstrap::expandMacros(aBaseInstallPath); + + // determine the filename of the license to show + OUString aLangString; + ::com::sun::star::lang::Locale aLocale; + OString aMgrName = OString("dkt"); + + AllSettings aSettings(Application::GetSettings()); + aLocale = aSettings.GetUILocale(); + ResMgr* pLocalResMgr = ResMgr::SearchCreateResMgr(aMgrName, aLocale); + + aLangString = aLocale.Language; + if ( aLocale.Country.getLength() != 0 ) + { + aLangString += OUString::createFromAscii("-"); + aLangString += aLocale.Country; + if ( aLocale.Variant.getLength() != 0 ) + { + aLangString += OUString::createFromAscii("-"); + aLangString += aLocale.Variant; + } + } +#if defined(WNT) || defined(OS2) + aLicensePath = + aBaseInstallPath + OUString::createFromAscii(szLicensePath) + + OUString::createFromAscii(szWNTLicenseName) + + OUString::createFromAscii("_") + + aLangString + + OUString::createFromAscii(szWNTLicenseExt); +#else + aLicensePath = + aBaseInstallPath + OUString::createFromAscii(szLicensePath) + + OUString::createFromAscii(szUNXLicenseName) + + OUString::createFromAscii("_") + + aLangString + + OUString::createFromAscii(szUNXLicenseExt); +#endif + delete pLocalResMgr; + return aLicensePath; +} + +/* Check if we need to accept license. */ +sal_Bool Desktop::LicenseNeedsAcceptance() +{ + // Don't show a license + return sal_False; +/* + sal_Bool bShowLicense = sal_True; + sal_Int32 nOpenSourceContext = 0; + try + { + ::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::OPENSOURCECONTEXT ) >>= nOpenSourceContext; + } + catch( const ::com::sun::star::uno::Exception& ) {} + + // open source needs no license + if ( nOpenSourceContext > 0 ) + bShowLicense = sal_False; + + return bShowLicense; +*/ +} + +/* Local function - get access to the configuration */ +static Reference< XPropertySet > impl_getConfigurationAccess( const OUString& rPath ) +{ + Reference < XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + + // get configuration provider + Reference< XMultiServiceFactory > xConfigProvider = Reference< XMultiServiceFactory >( + xFactory->createInstance( sConfigSrvc ), UNO_QUERY_THROW ); + + Sequence< Any > aArgs( 1 ); + NamedValue aValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "NodePath" ) ), makeAny( rPath ) ); + aArgs[0] <<= aValue; + return Reference< XPropertySet >( + xConfigProvider->createInstanceWithArguments( sAccessSrvc, aArgs ), UNO_QUERY_THROW ); +} + +/* Local function - was the wizard completed already? */ +static sal_Bool impl_isFirstStart() +{ + try { + Reference< XPropertySet > xPSet = impl_getConfigurationAccess( OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Setup/Office" ) ) ); + + Any result = xPSet->getPropertyValue(OUString::createFromAscii("FirstStartWizardCompleted")); + sal_Bool bCompleted = sal_False; + if ((result >>= bCompleted) && bCompleted) + return sal_False; // wizard was already completed + else + return sal_True; + } catch (const Exception&) + { + return sal_True; + } +} + +/* Local function - convert oslDateTime to tools DateTime */ +static DateTime impl_oslDateTimeToDateTime(const oslDateTime& aDateTime) +{ + return DateTime( + Date(aDateTime.Day, aDateTime.Month, aDateTime.Year), + Time(aDateTime.Hours, aDateTime.Minutes, aDateTime.Seconds)); +} + +/* Local function - get DateTime from a string */ +static sal_Bool impl_parseDateTime(const OUString& aString, DateTime& aDateTime) +{ + // take apart a canonical literal xsd:dateTime string + //CCYY-MM-DDThh:mm:ss(Z) + + OUString aDateTimeString = aString.trim(); + + // check length + if (aDateTimeString.getLength() < 19 || aDateTimeString.getLength() > 20) + return sal_False; + + sal_Int32 nDateLength = 10; + sal_Int32 nTimeLength = 8; + + OUString aDateTimeSep = OUString::createFromAscii("T"); + OUString aDateSep = OUString::createFromAscii("-"); + OUString aTimeSep = OUString::createFromAscii(":"); + OUString aUTCString = OUString::createFromAscii("Z"); + + OUString aDateString = aDateTimeString.copy(0, nDateLength); + OUString aTimeString = aDateTimeString.copy(nDateLength+1, nTimeLength); + + sal_Int32 nIndex = 0; + sal_Int32 nYear = aDateString.getToken(0, '-', nIndex).toInt32(); + sal_Int32 nMonth = aDateString.getToken(0, '-', nIndex).toInt32(); + sal_Int32 nDay = aDateString.getToken(0, '-', nIndex).toInt32(); + nIndex = 0; + sal_Int32 nHour = aTimeString.getToken(0, ':', nIndex).toInt32(); + sal_Int32 nMinute = aTimeString.getToken(0, ':', nIndex).toInt32(); + sal_Int32 nSecond = aTimeString.getToken(0, ':', nIndex).toInt32(); + + Date tmpDate((USHORT)nDay, (USHORT)nMonth, (USHORT)nYear); + Time tmpTime(nHour, nMinute, nSecond); + DateTime tmpDateTime(tmpDate, tmpTime); + if (aString.indexOf(aUTCString) < 0) + tmpDateTime.ConvertToUTC(); + + aDateTime = tmpDateTime; + return sal_True; +} + +/* Local function - was the license accepted already? */ +static sal_Bool impl_isLicenseAccepted() +{ + // If no license will be shown ... it must not be accepted. + // So it was accepted "hardly" by the outside installer. + // But if the configuration entry "HideEula" will be removed afterwards .. + // we have to show the licese page again and user has to accept it here .-) + if ( ! Desktop::LicenseNeedsAcceptance() ) + return sal_True; + + try + { + Reference< XPropertySet > xPSet = impl_getConfigurationAccess( OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Setup/Office" ) ) ); + + Any result = xPSet->getPropertyValue(OUString::createFromAscii("LicenseAcceptDate")); + + OUString aAcceptDate; + if (result >>= aAcceptDate) + { + // compare to date of license file + OUString aLicenseURL = Desktop::GetLicensePath(); + osl::DirectoryItem aDirItem; + if (osl::DirectoryItem::get(aLicenseURL, aDirItem) != osl::FileBase::E_None) + return sal_False; + osl::FileStatus aStatus(FileStatusMask_All); + if (aDirItem.getFileStatus(aStatus) != osl::FileBase::E_None) + return sal_False; + TimeValue aTimeVal = aStatus.getModifyTime(); + oslDateTime aDateTimeVal; + if (!osl_getDateTimeFromTimeValue(&aTimeVal, &aDateTimeVal)) + return sal_False; + + // compare dates + DateTime aLicenseDateTime = impl_oslDateTimeToDateTime(aDateTimeVal); + DateTime aAcceptDateTime; + if (!impl_parseDateTime(aAcceptDate, aAcceptDateTime)) + return sal_False; + + if ( aAcceptDateTime > aLicenseDateTime ) + return sal_True; + } + return sal_False; + } catch (const Exception&) + { + return sal_False; + } +} + +/* Check if we need the first start wizard. */ +sal_Bool Desktop::IsFirstStartWizardNeeded() +{ + return impl_isFirstStart() || !impl_isLicenseAccepted(); +} + +void Desktop::DoRestartActionsIfNecessary( sal_Bool bQuickStart ) +{ + if ( bQuickStart ) + { + try + { + Reference< XPropertySet > xPSet = impl_getConfigurationAccess( OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Setup/Office" ) ) ); + + OUString sPropName( RTL_CONSTASCII_USTRINGPARAM( "OfficeRestartInProgress" ) ); + Any aRestart = xPSet->getPropertyValue( sPropName ); + sal_Bool bRestart = sal_False; + if ( ( aRestart >>= bRestart ) && bRestart ) + { + xPSet->setPropertyValue( sPropName, makeAny( sal_False ) ); + Reference< util::XChangesBatch >( xPSet, UNO_QUERY_THROW )->commitChanges(); + + Sequence< Any > aSeq( 2 ); + aSeq[0] <<= sal_True; + aSeq[1] <<= sal_True; + + Reference < XInitialization > xQuickstart( ::comphelper::getProcessServiceFactory()->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.office.Quickstart" ) ) ),UNO_QUERY_THROW ); + xQuickstart->initialize( aSeq ); + } + } + catch( uno::Exception& ) + { + // this is no critical operation so it should not prevent office from starting + } + } +} + +void Desktop::SetRestartState() +{ + try + { + Reference< XPropertySet > xPSet = impl_getConfigurationAccess( OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Setup/Office" ) ) ); + OUString sPropName( RTL_CONSTASCII_USTRINGPARAM( "OfficeRestartInProgress" ) ); + xPSet->setPropertyValue( sPropName, makeAny( sal_True ) ); + Reference< util::XChangesBatch >( xPSet, UNO_QUERY_THROW )->commitChanges(); + } + catch( uno::Exception& ) + { + // this is no critical operation, ignore the exception + } + +} + diff --git a/desktop/source/app/appinit.cxx b/desktop/source/app/appinit.cxx new file mode 100644 index 000000000000..97eb3f555f60 --- /dev/null +++ b/desktop/source/app/appinit.cxx @@ -0,0 +1,484 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include <algorithm> + +#include "app.hxx" +#include "cmdlineargs.hxx" +#include "desktopresid.hxx" +#include "desktop.hrc" +#include <com/sun/star/registry/XSimpleRegistry.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/XCurrentContext.hpp> +#include <com/sun/star/packages/zip/ZipIOException.hpp> + + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#include <com/sun/star/ucb/XContentProviderManager.hpp> +#include <com/sun/star/ucb/XContentProviderFactory.hpp> +#include <uno/current_context.hxx> +#include <cppuhelper/servicefactory.hxx> +#include <cppuhelper/bootstrap.hxx> +#include <osl/file.hxx> +#include <osl/module.h> +#include <vos/process.hxx> +#include <rtl/uri.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/bootstrap.hxx> +#include <comphelper/regpathhelper.hxx> +#include <tools/debug.hxx> +#include <tools/tempfile.hxx> +#include <ucbhelper/configurationkeys.hxx> + +#include <cppuhelper/bootstrap.hxx> +#include <tools/urlobj.hxx> +#include <tools/rcid.h> + +#include <rtl/logfile.hxx> +#include <rtl/instance.hxx> +#include <comphelper/processfactory.hxx> +#include <unotools/localfilehelper.hxx> +#include <unotools/ucbhelper.hxx> +#include <unotools/tempfile.hxx> +#include <ucbhelper/contentbroker.hxx> +#include <vcl/svapp.hxx> +#include <unotools/startoptions.hxx> +#include <unotools/pathoptions.hxx> +#include <unotools/internaloptions.hxx> + + +#define DEFINE_CONST_OUSTRING(CONSTASCII) OUString(RTL_CONSTASCII_USTRINGPARAM(CONSTASCII)) + +#define DESKTOP_TEMPDIRNAME "soffice.tmp" + +using namespace rtl; +using namespace vos; +using namespace desktop; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::registry; +using namespace ::com::sun::star::ucb; + +namespace desktop +{ + +// ----------------------------------------------------------------------------- + +static bool configureUcb(bool bServer, rtl::OUString const & rPortalConnect) +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (sb93797) ::configureUcb" ); + Reference< XMultiServiceFactory > + xServiceFactory( comphelper::getProcessServiceFactory() ); + if (!xServiceFactory.is()) + { + DBG_ERROR("configureUcb(): No XMultiServiceFactory"); + return false; + } + + rtl::OUString aPipe; + vos::OSecurity().getUserIdent(aPipe); + + rtl::OUStringBuffer aPortal; + if (rPortalConnect.getLength() != 0) + { + aPortal.append(sal_Unicode(',')); + aPortal.append(rPortalConnect); + } + + Sequence< Any > aArgs(6); + aArgs[0] + <<= rtl::OUString::createFromAscii(bServer ? + UCB_CONFIGURATION_KEY1_SERVER : + UCB_CONFIGURATION_KEY1_LOCAL); + aArgs[1] + <<= rtl::OUString::createFromAscii(UCB_CONFIGURATION_KEY2_OFFICE); + aArgs[2] <<= rtl::OUString::createFromAscii("PIPE"); + aArgs[3] <<= aPipe; + aArgs[4] <<= rtl::OUString::createFromAscii("PORTAL"); + aArgs[5] <<= aPortal.makeStringAndClear(); + + bool ret = + ::ucbhelper::ContentBroker::initialize( xServiceFactory, aArgs ) != false; + +#ifdef GNOME_VFS_ENABLED + // register GnomeUCP if necessary + ::ucbhelper::ContentBroker* cb = ::ucbhelper::ContentBroker::get(); + if(cb) { + try { + Reference< XCurrentContext > xCurrentContext( + getCurrentContext()); + if (xCurrentContext.is()) + { + Any aValue = xCurrentContext->getValueByName( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "system.desktop-environment" ) ) + ); + rtl::OUString aDesktopEnvironment; + if ((aValue >>= aDesktopEnvironment) + && aDesktopEnvironment.equalsAscii("GNOME")) + { + Reference<XContentProviderManager> xCPM = + cb->getContentProviderManagerInterface(); +#if 0 + try + { + + Reference<XContentProviderFactory> xCPF( + xServiceFactory->createInstance( + rtl::OUString::createFromAscii( + "com.sun.star.ucb.ContentProviderProxyFactory")), + UNO_QUERY); + if(xCPF.is()) + xCPM->registerContentProvider( + xCPF->createContentProvider( + rtl::OUString::createFromAscii( + "com.sun.star.ucb.GnomeVFSContentProvider" + ) + ), + rtl::OUString::createFromAscii(".*"), + false); + } catch (...) + { + } +#else + + // Workaround for P1 #124597#. Instanciate GNOME-VFS-UCP in the thread that initialized + // GNOME in order to avoid a deadlock that may occure in case UCP gets initialized from + // a different thread. The latter may happen when calling the Office remotely via UNO. + // THIS IS NOT A FIX, JUST A WORKAROUND! + + try + { + Reference<XContentProvider> xCP( + xServiceFactory->createInstance( + rtl::OUString::createFromAscii( + "com.sun.star.ucb.GnomeVFSContentProvider")), + UNO_QUERY); + if(xCP.is()) + xCPM->registerContentProvider( + xCP, + rtl::OUString::createFromAscii(".*"), + false); + } catch (...) + { + } + } +#endif + } + } catch (RuntimeException e) { + } + } +#endif // GNOME_VFS_ENABLED + + return ret;; +} + +Reference< XMultiServiceFactory > Desktop::CreateApplicationServiceManager() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::createApplicationServiceManager" ); + + try + { + Reference<XComponentContext> xComponentContext = ::cppu::defaultBootstrap_InitialComponentContext(); + Reference<XMultiServiceFactory> xMS(xComponentContext->getServiceManager(), UNO_QUERY); + + return xMS; + } + catch( ::com::sun::star::uno::Exception& ) + { + } + + return Reference< XMultiServiceFactory >(); +} + +void Desktop::DestroyApplicationServiceManager( Reference< XMultiServiceFactory >& xSMgr ) +{ + Reference< XPropertySet > xProps( xSMgr, UNO_QUERY ); + if ( xProps.is() ) + { + try + { + Reference< XComponent > xComp; + if (xProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xComp ) + { + xComp->dispose(); + } + } + catch ( UnknownPropertyException& ) + { + } + } +} + +void Desktop::RegisterServices( Reference< XMultiServiceFactory >& xSMgr ) +{ + if( !m_bServicesRegistered ) + { + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::registerServices" ); + + // read command line parameters + ::rtl::OUString conDcp; + ::rtl::OUString aClientDisplay; + ::rtl::OUString aTmpString; + sal_Bool bHeadlessMode = sal_False; + + // interpret command line arguments + CommandLineArgs* pCmdLine = GetCommandLineArgs(); + + // read accept string from configuration + conDcp = SvtStartOptions().GetConnectionURL(); + + if ( pCmdLine->GetAcceptString( aTmpString )) + conDcp = aTmpString; + + // Headless mode for FAT Office + bHeadlessMode = pCmdLine->IsHeadless(); + if ( bHeadlessMode ) + Application::EnableHeadlessMode(); + + if ( conDcp.getLength() > 0 ) + { + // accept incoming connections (scripting and one rvp) + RTL_LOGFILE_CONTEXT( aLog, "desktop (lo119109) desktop::Desktop::createAcceptor()" ); + createAcceptor(conDcp); + } + + // improves parallel processing on Sun ONE Webtop + // servicemanager up -> copy user installation + if ( pCmdLine->IsServer() ) + { + // Check some mandatory environment states if "-server" is possible. Otherwise ignore + // this parameter. + Reference< com::sun::star::container::XContentEnumerationAccess > rContent( xSMgr , UNO_QUERY ); + if( rContent.is() ) + { + OUString sPortalService = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.portal.InstallUser" ) ); + Reference < com::sun::star::container::XEnumeration > rEnum = rContent->createContentEnumeration( sPortalService ); + if ( !rEnum.is() ) + { + // Reset server parameter so it is ignored in the furthermore startup process + pCmdLine->SetBoolParam( CommandLineArgs::CMD_BOOLPARAM_SERVER, sal_False ); + } + } + } + + ::rtl::OUString aPortalConnect; + bool bServer = (bool)pCmdLine->IsServer(); + + pCmdLine->GetPortalConnectString( aPortalConnect ); + if ( !configureUcb( bServer, aPortalConnect ) ) + { + DBG_ERROR( "Can't configure UCB" ); + throw com::sun::star::uno::Exception(rtl::OUString::createFromAscii("RegisterServices, configureUcb"), NULL); + } + + CreateTemporaryDirectory(); + m_bServicesRegistered = true; + } +} + +namespace +{ + struct acceptorMap : public rtl::Static< AcceptorMap, acceptorMap > {}; + struct CurrentTempURL : public rtl::Static< String, CurrentTempURL > {}; +} + +static sal_Bool bAccept = sal_False; + +void Desktop::createAcceptor(const OUString& aAcceptString) +{ + // check whether the requested acceptor already exists + AcceptorMap &rMap = acceptorMap::get(); + AcceptorMap::const_iterator pIter = rMap.find(aAcceptString); + if (pIter == rMap.end() ) { + + Sequence< Any > aSeq( 2 ); + aSeq[0] <<= aAcceptString; + aSeq[1] <<= bAccept; + Reference<XInitialization> rAcceptor( + ::comphelper::getProcessServiceFactory()->createInstance( + OUString::createFromAscii( "com.sun.star.office.Acceptor" )), UNO_QUERY ); + if ( rAcceptor.is() ) { + try{ + rAcceptor->initialize( aSeq ); + rMap.insert(AcceptorMap::value_type(aAcceptString, rAcceptor)); + } catch (com::sun::star::uno::Exception&) { + // no error handling needed... + // acceptor just won't come up + OSL_ENSURE(sal_False, "Acceptor could not be created."); + } + } else { + // there is already an acceptor with this description + OSL_ENSURE(sal_False, "Acceptor already exists."); + } + + } +} + +class enable +{ + private: + Sequence<Any> m_aSeq; + public: + enable() : m_aSeq(1) { + m_aSeq[0] <<= sal_True; + } + void operator() (const AcceptorMap::value_type& val) { + if (val.second.is()) { + val.second->initialize(m_aSeq); + } + } +}; + +void Desktop::enableAcceptors() +{ + RTL_LOGFILE_CONTEXT(aLog, "desktop (lo119109) Desktop::enableAcceptors"); + if (!bAccept) + { + // from now on, all new acceptors are enabled + bAccept = sal_True; + // enable existing acceptors by calling initialize(true) + // on all existing acceptors + AcceptorMap &rMap = acceptorMap::get(); + std::for_each(rMap.begin(), rMap.end(), enable()); + } +} + +void Desktop::destroyAcceptor(const OUString& aAcceptString) +{ + // special case stop all acceptors + AcceptorMap &rMap = acceptorMap::get(); + if (aAcceptString.compareToAscii("all") == 0) { + rMap.clear(); + + } else { + // try to remove acceptor from map + AcceptorMap::const_iterator pIter = rMap.find(aAcceptString); + if (pIter != rMap.end() ) { + // remove reference from map + // this is the last reference and the acceptor will be destructed + rMap.erase(aAcceptString); + } else { + OSL_ENSURE(sal_False, "Found no acceptor to remove"); + } + } +} + + +void Desktop::DeregisterServices() +{ + // stop all acceptors by clearing the map + acceptorMap::get().clear(); +} + +void Desktop::CreateTemporaryDirectory() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::createTemporaryDirectory" ); + + ::rtl::OUString aTempBaseURL; + try + { + SvtPathOptions aOpt; + aTempBaseURL = aOpt.GetTempPath(); + } + catch ( RuntimeException& e ) + { + // Catch runtime exception here: We have to add language dependent info + // to the exception message. Fallback solution uses hard coded string. + OUString aMsg; + DesktopResId aResId( STR_BOOTSTRAP_ERR_NO_PATHSET_SERVICE ); + aResId.SetRT( RSC_STRING ); + if ( aResId.GetResMgr()->IsAvailable( aResId )) + aMsg = String( aResId ); + else + aMsg = OUString( RTL_CONSTASCII_USTRINGPARAM( "The path manager is not available.\n" )); + e.Message = aMsg + e.Message; + throw e; + } + + // remove possible old directory and base directory + SvtInternalOptions aInternalOpt; + + // set temp base directory + sal_Int32 nLength = aTempBaseURL.getLength(); + if ( aTempBaseURL.matchAsciiL( "/", 1, nLength-1 ) ) + aTempBaseURL = aTempBaseURL.copy( 0, nLength - 1 ); + + String aOldTempURL = aInternalOpt.GetCurrentTempURL(); + if ( aOldTempURL.Len() > 0 ) + { + // remove old temporary directory + ::utl::UCBContentHelper::Kill( aOldTempURL ); + } + + String aRet; + ::rtl::OUString aTempPath( aTempBaseURL ); + + // create new current temporary directory + ::utl::LocalFileHelper::ConvertURLToPhysicalName( aTempBaseURL, aRet ); + ::osl::FileBase::getFileURLFromSystemPath( aRet, aTempPath ); + aTempPath = ::utl::TempFile::SetTempNameBaseDirectory( aTempPath ); + if ( !aTempPath.getLength() ) + { + ::osl::File::getTempDirURL( aTempBaseURL ); + + nLength = aTempBaseURL.getLength(); + if ( aTempBaseURL.matchAsciiL( "/", 1, nLength-1 ) ) + aTempBaseURL = aTempBaseURL.copy( 0, nLength - 1 ); + + aTempPath = aTempBaseURL; + ::osl::FileBase::getFileURLFromSystemPath( aRet, aTempPath ); + aTempPath = ::utl::TempFile::SetTempNameBaseDirectory( aTempPath ); + } + + // set new current temporary directory + ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aTempPath, aRet ); + aInternalOpt.SetCurrentTempURL( aRet ); + CurrentTempURL::get() = aRet; +} + +void Desktop::RemoveTemporaryDirectory() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::removeTemporaryDirectory" ); + + // remove current temporary directory + String &rCurrentTempURL = CurrentTempURL::get(); + if ( rCurrentTempURL.Len() > 0 ) + { + if ( ::utl::UCBContentHelper::Kill( rCurrentTempURL ) ) + SvtInternalOptions().SetCurrentTempURL( String() ); + } +} + +} // namespace desktop diff --git a/desktop/source/app/appinit.hxx b/desktop/source/app/appinit.hxx new file mode 100644 index 000000000000..c5b48fd4a488 --- /dev/null +++ b/desktop/source/app/appinit.hxx @@ -0,0 +1,50 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _DESKTOP_APPINIT_HXX_ +#define _DESKTOP_APPINIT_HXX_ + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +namespace desktop +{ + +::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > createApplicationServiceManager(); + +sal_Bool InitializeInstallation( const rtl::OUString& rAppFilename ); +void registerServices( ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xSMgr ); +void deregisterServices(); + +void destroyApplicationServiceManager( ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xSMgr ); + +void createTemporaryDirectory(); +void removeTemporaryDirectory(); + +} + +#endif diff --git a/desktop/source/app/appsys.cxx b/desktop/source/app/appsys.cxx new file mode 100644 index 000000000000..4cff81e3bb54 --- /dev/null +++ b/desktop/source/app/appsys.cxx @@ -0,0 +1,69 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include "appsys.hxx" + +#ifdef WNT + +#include <rtl/ustring.hxx> +#include <tools/solar.h> +#include <tools/prewin.h> +#include <winreg.h> +#include <tools/postwin.h> +#include <tools/urlobj.hxx> + + +#define U2S(STRING) ::rtl::OUStringToOString(STRING, RTL_TEXTENCODING_UTF8) + +namespace desktop +{ + +void FATToVFat_Impl( String& aName ) +{ + INetURLObject aObj( aName ); + if ( aObj.GetProtocol() == INET_PROT_FILE ) + { + WIN32_FIND_DATA aData; + HANDLE h = FindFirstFile( U2S(aName).getStr(), &aData ); + if ( h ) + { + // FAT-Kurzname in VFAT-Langname wandeln + aObj.removeSegment(); + aObj.insertName( String::CreateFromAscii( aData.cFileName ) ); + aName = aObj.PathToFileName(); + FindClose( h ); + } + } +} + +} + +#endif // WNT + diff --git a/desktop/source/app/appsys.hxx b/desktop/source/app/appsys.hxx new file mode 100644 index 000000000000..5d1b06c1bbe7 --- /dev/null +++ b/desktop/source/app/appsys.hxx @@ -0,0 +1,42 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _DESKTOP_APPSYS_HXX_ +#define _DESKTOP_APPSYS_HXX_ + +#include <tools/string.hxx> + +namespace desktop +{ + +#ifdef WNT +void FATToVFat_Impl( String& aName ); +#endif + +} + +#endif // _DESKTOP_APPSYS_HXX_ diff --git a/desktop/source/app/check_ext_deps.cxx b/desktop/source/app/check_ext_deps.cxx new file mode 100755 index 000000000000..664e63c7f6ca --- /dev/null +++ b/desktop/source/app/check_ext_deps.cxx @@ -0,0 +1,431 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include "osl/file.hxx" +#include "osl/mutex.hxx" + +#include <rtl/bootstrap.hxx> +#include <rtl/ustring.hxx> +#include <rtl/logfile.hxx> +#include "cppuhelper/compbase3.hxx" + +#include "vcl/wrkwin.hxx" +#include "vcl/timer.hxx" + +#include <unotools/configmgr.hxx> +#include "toolkit/helper/vclunohelper.hxx" + +#include <comphelper/processfactory.hxx> +#include <comphelper/sequence.hxx> +#include <cppuhelper/bootstrap.hxx> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include "com/sun/star/deployment/XPackage.hpp" +#include "com/sun/star/deployment/ExtensionManager.hpp" +#include "com/sun/star/deployment/LicenseException.hpp" +#include "com/sun/star/deployment/ui/LicenseDialog.hpp" +#include <com/sun/star/task/XJob.hpp> +#include <com/sun/star/task/XJobExecutor.hpp> +#include <com/sun/star/task/XInteractionApprove.hpp> +#include <com/sun/star/task/XInteractionAbort.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include "com/sun/star/ui/dialogs/ExecutableDialogResults.hpp" +#include <com/sun/star/util/XChangesBatch.hpp> + +#include "app.hxx" + +#include "../deployment/inc/dp_misc.h" + +using rtl::OUString; +using namespace desktop; +using namespace com::sun::star; + +#define UNISTRING(s) OUString(RTL_CONSTASCII_USTRINGPARAM(s)) + +namespace +{ +//For use with XExtensionManager.synchronize +class SilentCommandEnv + : public ::cppu::WeakImplHelper3< ucb::XCommandEnvironment, + task::XInteractionHandler, + ucb::XProgressHandler > +{ + Desktop *mpDesktop; + sal_Int32 mnLevel; + sal_Int32 mnProgress; + +public: + SilentCommandEnv( Desktop* pDesktop ); + virtual ~SilentCommandEnv(); + + // XCommandEnvironment + virtual uno::Reference<task::XInteractionHandler > SAL_CALL + getInteractionHandler() throw (uno::RuntimeException); + virtual uno::Reference<ucb::XProgressHandler > + SAL_CALL getProgressHandler() throw (uno::RuntimeException); + + // XInteractionHandler + virtual void SAL_CALL handle( + uno::Reference<task::XInteractionRequest > const & xRequest ) + throw (uno::RuntimeException); + + // XProgressHandler + virtual void SAL_CALL push( uno::Any const & Status ) + throw (uno::RuntimeException); + virtual void SAL_CALL update( uno::Any const & Status ) + throw (uno::RuntimeException); + virtual void SAL_CALL pop() throw (uno::RuntimeException); +}; + +//----------------------------------------------------------------------------- +SilentCommandEnv::SilentCommandEnv( Desktop* pDesktop ) +{ + mpDesktop = pDesktop; + mnLevel = 0; + mnProgress = 25; +} + +//----------------------------------------------------------------------------- +SilentCommandEnv::~SilentCommandEnv() +{ + mpDesktop->SetSplashScreenText( OUString() ); +} + +//----------------------------------------------------------------------------- +Reference<task::XInteractionHandler> SilentCommandEnv::getInteractionHandler() + throw (uno::RuntimeException) +{ + return this; +} + +//----------------------------------------------------------------------------- +Reference<ucb::XProgressHandler> SilentCommandEnv::getProgressHandler() + throw (uno::RuntimeException) +{ + return this; +} + +//----------------------------------------------------------------------------- +// XInteractionHandler +void SilentCommandEnv::handle( Reference< task::XInteractionRequest> const & xRequest ) + throw (uno::RuntimeException) +{ + deployment::LicenseException licExc; + + uno::Any request( xRequest->getRequest() ); + bool bApprove = true; + + if ( request >>= licExc ) + { + uno::Reference< uno::XComponentContext > xContext = comphelper_getProcessComponentContext(); + uno::Reference< ui::dialogs::XExecutableDialog > xDialog( + deployment::ui::LicenseDialog::create( + xContext, VCLUnoHelper::GetInterface( NULL ), + licExc.ExtensionName, licExc.Text ) ); + sal_Int16 res = xDialog->execute(); + if ( res == ui::dialogs::ExecutableDialogResults::CANCEL ) + bApprove = false; + else if ( res == ui::dialogs::ExecutableDialogResults::OK ) + bApprove = true; + else + { + OSL_ASSERT(0); + } + } + + // We approve everything here + uno::Sequence< Reference< task::XInteractionContinuation > > conts( xRequest->getContinuations() ); + Reference< task::XInteractionContinuation > const * pConts = conts.getConstArray(); + sal_Int32 len = conts.getLength(); + + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + if ( bApprove ) + { + uno::Reference< task::XInteractionApprove > xInteractionApprove( pConts[ pos ], uno::UNO_QUERY ); + if ( xInteractionApprove.is() ) + xInteractionApprove->select(); + } + else + { + uno::Reference< task::XInteractionAbort > xInteractionAbort( pConts[ pos ], uno::UNO_QUERY ); + if ( xInteractionAbort.is() ) + xInteractionAbort->select(); + } + } +} + +//----------------------------------------------------------------------------- +// XProgressHandler +void SilentCommandEnv::push( uno::Any const & rStatus ) + throw (uno::RuntimeException) +{ + OUString sText; + mnLevel += 1; + + if ( rStatus.hasValue() && ( rStatus >>= sText) ) + { + if ( mnLevel <= 3 ) + mpDesktop->SetSplashScreenText( sText ); + else + mpDesktop->SetSplashScreenProgress( ++mnProgress ); + } +} + +//----------------------------------------------------------------------------- +void SilentCommandEnv::update( uno::Any const & rStatus ) + throw (uno::RuntimeException) +{ + OUString sText; + if ( rStatus.hasValue() && ( rStatus >>= sText) ) + { + mpDesktop->SetSplashScreenText( sText ); + } +} + +//----------------------------------------------------------------------------- +void SilentCommandEnv::pop() throw (uno::RuntimeException) +{ + mnLevel -= 1; +} + +} // end namespace + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +static const OUString sConfigSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) ); +static const OUString sAccessSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) ); +//------------------------------------------------------------------------------ +static sal_Int16 impl_showExtensionDialog( uno::Reference< uno::XComponentContext > &xContext ) +{ + rtl::OUString sServiceName = UNISTRING("com.sun.star.deployment.ui.UpdateRequiredDialog"); + uno::Reference< uno::XInterface > xService; + sal_Int16 nRet = 0; + + uno::Reference< lang::XMultiComponentFactory > xServiceManager( xContext->getServiceManager() ); + if( !xServiceManager.is() ) + throw uno::RuntimeException( + UNISTRING( "impl_showExtensionDialog(): unable to obtain service manager from component context" ), uno::Reference< uno::XInterface > () ); + + xService = xServiceManager->createInstanceWithContext( sServiceName, xContext ); + uno::Reference< ui::dialogs::XExecutableDialog > xExecuteable( xService, uno::UNO_QUERY ); + if ( xExecuteable.is() ) + nRet = xExecuteable->execute(); + + return nRet; +} + +//------------------------------------------------------------------------------ +// Check dependencies of all packages +//------------------------------------------------------------------------------ +static bool impl_checkDependencies( const uno::Reference< uno::XComponentContext > &xContext ) +{ + uno::Sequence< uno::Sequence< uno::Reference< deployment::XPackage > > > xAllPackages; + uno::Reference< deployment::XExtensionManager > xExtensionManager = deployment::ExtensionManager::get( xContext ); + + if ( !xExtensionManager.is() ) + { + OSL_ENSURE( 0, "Could not get the Extension Manager!" ); + return true; + } + + try { + xAllPackages = xExtensionManager->getAllExtensions( uno::Reference< task::XAbortChannel >(), + uno::Reference< ucb::XCommandEnvironment >() ); + } + catch ( deployment::DeploymentException & ) { return true; } + catch ( ucb::CommandFailedException & ) { return true; } + catch ( ucb::CommandAbortedException & ) { return true; } + catch ( lang::IllegalArgumentException & e ) { + throw uno::RuntimeException( e.Message, e.Context ); + } + + sal_Int32 nMax = 2; +#ifdef DEBUG + nMax = 3; +#endif + + for ( sal_Int32 i = 0; i < xAllPackages.getLength(); ++i ) + { + uno::Sequence< uno::Reference< deployment::XPackage > > xPackageList = xAllPackages[i]; + + for ( sal_Int32 j = 0; (j<nMax) && (j < xPackageList.getLength()); ++j ) + { + uno::Reference< deployment::XPackage > xPackage = xPackageList[j]; + if ( xPackage.is() ) + { + bool bRegistered = false; + try { + beans::Optional< beans::Ambiguous< sal_Bool > > option( xPackage->isRegistered( uno::Reference< task::XAbortChannel >(), + uno::Reference< ucb::XCommandEnvironment >() ) ); + if ( option.IsPresent ) + { + ::beans::Ambiguous< sal_Bool > const & reg = option.Value; + if ( reg.IsAmbiguous ) + bRegistered = false; + else + bRegistered = reg.Value ? true : false; + } + else + bRegistered = false; + } + catch ( uno::RuntimeException & ) { throw; } + catch ( uno::Exception & exc) { + (void) exc; + OSL_ENSURE( 0, ::rtl::OUStringToOString( exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + + if ( bRegistered ) + { + bool bDependenciesValid = false; + try { + bDependenciesValid = xPackage->checkDependencies( uno::Reference< ucb::XCommandEnvironment >() ); + } + catch ( deployment::DeploymentException & ) {} + if ( ! bDependenciesValid ) + { + return false; + } + } + } + } + } + return true; +} + +//------------------------------------------------------------------------------ +// resets the 'check needed' flag (needed, if aborted) +//------------------------------------------------------------------------------ +static void impl_setNeedsCompatCheck() +{ + try { + Reference < XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + // get configuration provider + Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >( + xFactory->createInstance(sConfigSrvc), UNO_QUERY_THROW); + + Sequence< Any > theArgs(1); + beans::NamedValue v( OUString::createFromAscii("NodePath"), + makeAny( OUString::createFromAscii("org.openoffice.Setup/Office") ) ); + theArgs[0] <<= v; + Reference< beans::XPropertySet > pset = Reference< beans::XPropertySet >( + theConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY_THROW ); + + Any value = makeAny( OUString::createFromAscii("never") ); + + pset->setPropertyValue( OUString::createFromAscii("LastCompatibilityCheckID"), value ); + Reference< util::XChangesBatch >( pset, UNO_QUERY_THROW )->commitChanges(); + } + catch (const Exception&) {} +} + +//------------------------------------------------------------------------------ +static bool impl_check() +{ + uno::Reference< uno::XComponentContext > xContext = comphelper_getProcessComponentContext(); + + bool bDependenciesValid = impl_checkDependencies( xContext ); + + short nRet = 0; + + if ( !bDependenciesValid ) + nRet = impl_showExtensionDialog( xContext ); + + if ( nRet == -1 ) + { + impl_setNeedsCompatCheck(); + return true; + } + else + return false; +} + +//------------------------------------------------------------------------------ +// to check if we need checking the dependencies of the extensions again, we compare +// the build id of the office with the one of the last check +//------------------------------------------------------------------------------ +static bool impl_needsCompatCheck() +{ + bool bNeedsCheck = false; + rtl::OUString aLastCheckBuildID; + rtl::OUString aCurrentBuildID( UNISTRING( "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}" ) ); + rtl::Bootstrap::expandMacros( aCurrentBuildID ); + + try { + Reference < XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory(); + // get configuration provider + Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >( + xFactory->createInstance(sConfigSrvc), UNO_QUERY_THROW); + + Sequence< Any > theArgs(1); + beans::NamedValue v( OUString::createFromAscii("NodePath"), + makeAny( OUString::createFromAscii("org.openoffice.Setup/Office") ) ); + theArgs[0] <<= v; + Reference< beans::XPropertySet > pset = Reference< beans::XPropertySet >( + theConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY_THROW ); + + Any result = pset->getPropertyValue( OUString::createFromAscii("LastCompatibilityCheckID") ); + + result >>= aLastCheckBuildID; + if ( aLastCheckBuildID != aCurrentBuildID ) + { + bNeedsCheck = true; + result <<= aCurrentBuildID; + pset->setPropertyValue( OUString::createFromAscii("LastCompatibilityCheckID"), result ); + Reference< util::XChangesBatch >( pset, UNO_QUERY_THROW )->commitChanges(); + } +#ifdef DEBUG + bNeedsCheck = true; +#endif + } + catch (const Exception&) {} + + return bNeedsCheck; +} + +//------------------------------------------------------------------------------ +// Do we need to check the dependencies of the extensions? +// When there are unresolved issues, we can't continue with startup +sal_Bool Desktop::CheckExtensionDependencies() +{ + sal_Bool bAbort = false; + + if ( impl_needsCompatCheck() ) + bAbort = impl_check(); + + return bAbort; +} + +void Desktop::SynchronizeExtensionRepositories() +{ + RTL_LOGFILE_CONTEXT(aLog,"desktop (jl) ::Desktop::SynchronizeExtensionRepositories"); + dp_misc::syncRepositories( new SilentCommandEnv( this ) ); +} diff --git a/desktop/source/app/checkinstall.cxx b/desktop/source/app/checkinstall.cxx new file mode 100644 index 000000000000..bb7258554cfe --- /dev/null +++ b/desktop/source/app/checkinstall.cxx @@ -0,0 +1,118 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include "checkinstall.hxx" +#include <com/sun/star/beans/XExactName.hpp> +#include <com/sun/star/beans/XMaterialHolder.hpp> +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <comphelper/processfactory.hxx> +#include <vcl/msgbox.hxx> +#include <tools/date.hxx> + +using namespace rtl; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; + +namespace desktop +{ + +sal_Bool CheckInstallation( OUString& rTitle ) +{ + try + { + Reference< XMultiServiceFactory > xSMgr = ::comphelper::getProcessServiceFactory(); + Reference< XExactName > xExactName( xSMgr->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.desktop.Evaluation" ))), + UNO_QUERY ); + if ( xExactName.is() ) + { + try + { + rTitle = xExactName->getExactName( rTitle ); + Reference< XMaterialHolder > xMaterialHolder( xExactName, UNO_QUERY ); + if ( xMaterialHolder.is() ) + { + com::sun::star::util::Date aExpirationDate; + Any a = xMaterialHolder->getMaterial(); + if ( a >>= aExpirationDate ) + { + Date aToday; + Date aTimeBombDate( aExpirationDate.Day, aExpirationDate.Month, aExpirationDate.Year ); + if ( aToday > aTimeBombDate ) + { + InfoBox aInfoBox( NULL, String::CreateFromAscii( "This version has expired" ) ); + aInfoBox.Execute(); + return sal_False; + } + } + + return sal_True; + } + else + { + InfoBox aInfoBox( NULL, rTitle ); + aInfoBox.Execute(); + return sal_False; + } + } + catch ( RuntimeException& ) + { + // Evaluation version expired! + return sal_False; + } + } + else + { + Reference< com::sun::star::container::XContentEnumerationAccess > rContent( xSMgr , UNO_QUERY ); + if( rContent.is() ) + { + OUString sEvalService = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.office.Evaluation" ) ); + Reference < com::sun::star::container::XEnumeration > rEnum = rContent->createContentEnumeration( sEvalService ); + if ( rEnum.is() ) + { + InfoBox aInfoBox( NULL, rTitle ); + aInfoBox.Execute(); + return sal_False; + } + } + } + } + catch(Exception) + { + } + + return sal_True; +} + +} // namespace desktop diff --git a/desktop/source/app/checkinstall.hxx b/desktop/source/app/checkinstall.hxx new file mode 100644 index 000000000000..495ea3161bd3 --- /dev/null +++ b/desktop/source/app/checkinstall.hxx @@ -0,0 +1,42 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _DESKTOP_CHECKINSTALL_HXX_ +#define _DESKTOP_CHECKINSTALL_HXX_ + +#include <sal/types.h> +#include <rtl/ustring.hxx> + + +namespace desktop +{ + +sal_Bool CheckInstallation( rtl::OUString& rTitle ); + +} + +#endif // _DESKTOP_CHECKINSTALL_HXX_ diff --git a/desktop/source/app/cmdlineargs.cxx b/desktop/source/app/cmdlineargs.cxx new file mode 100644 index 000000000000..0625191ee2ea --- /dev/null +++ b/desktop/source/app/cmdlineargs.cxx @@ -0,0 +1,900 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" +#include <cmdlineargs.hxx> +#include <vcl/svapp.hxx> +#include <rtl/uri.hxx> +#include <rtl/ustring.hxx> +#include "rtl/process.h" +#include <comphelper/processfactory.hxx> +#include <com/sun/star/uri/XExternalUriReferenceTranslator.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/uno/Reference.hxx> +#include "tools/getprocessworkingdir.hxx" + +#include <svl/documentlockfile.hxx> + +using namespace rtl; +using namespace com::sun::star::lang; +using namespace com::sun::star::uri; +using namespace com::sun::star::uno; + +namespace desktop +{ + +namespace { + +class ExtCommandLineSupplier: public CommandLineArgs::Supplier { +public: + explicit ExtCommandLineSupplier(): + m_count(rtl_getAppCommandArgCount()), + m_index(0) + { + rtl::OUString url; + if (tools::getProcessWorkingDir(&url)) { + m_cwdUrl.reset(url); + } + } + + virtual ~ExtCommandLineSupplier() {} + + virtual boost::optional< rtl::OUString > getCwdUrl() { return m_cwdUrl; } + + virtual bool next(rtl::OUString * argument) { + OSL_ASSERT(argument != NULL); + if (m_index < m_count) { + rtl_getAppCommandArg(m_index++, &argument->pData); + return true; + } else { + return false; + } + } + +private: + boost::optional< rtl::OUString > m_cwdUrl; + sal_uInt32 m_count; + sal_uInt32 m_index; +}; + +} + +static CommandLineArgs::BoolParam aModuleGroupDefinition[] = +{ + CommandLineArgs::CMD_BOOLPARAM_WRITER, + CommandLineArgs::CMD_BOOLPARAM_CALC, + CommandLineArgs::CMD_BOOLPARAM_DRAW, + CommandLineArgs::CMD_BOOLPARAM_IMPRESS, + CommandLineArgs::CMD_BOOLPARAM_GLOBAL, + CommandLineArgs::CMD_BOOLPARAM_MATH, + CommandLineArgs::CMD_BOOLPARAM_WEB, + CommandLineArgs::CMD_BOOLPARAM_BASE +}; + +CommandLineArgs::GroupDefinition CommandLineArgs::m_pGroupDefinitions[ CommandLineArgs::CMD_GRPID_COUNT ] = +{ + { 8, aModuleGroupDefinition } +}; + +CommandLineArgs::Supplier::Exception::Exception() {} + +CommandLineArgs::Supplier::Exception::Exception(Exception const &) {} + +CommandLineArgs::Supplier::Exception::~Exception() {} + +CommandLineArgs::Supplier::Exception & +CommandLineArgs::Supplier::Exception::operator =(Exception const &) +{ return *this; } + +CommandLineArgs::Supplier::~Supplier() {} + +// intialize class with command line parameters from process environment +CommandLineArgs::CommandLineArgs() +{ + ResetParamValues(); + ExtCommandLineSupplier s; + ParseCommandLine_Impl( s ); +} + +CommandLineArgs::CommandLineArgs( Supplier& supplier ) +{ + ResetParamValues(); + ParseCommandLine_Impl( supplier ); +} + +// ---------------------------------------------------------------------------- + +void CommandLineArgs::ParseCommandLine_Impl( Supplier& supplier ) +{ + m_cwdUrl = supplier.getCwdUrl(); + Reference<XMultiServiceFactory> xMS(comphelper::getProcessServiceFactory(), UNO_QUERY); + OSL_ENSURE(xMS.is(), "CommandLineArgs: no ProcessServiceFactory."); + + Reference< XExternalUriReferenceTranslator > xTranslator( + xMS->createInstance( + OUString::createFromAscii( + "com.sun.star.uri.ExternalUriReferenceTranslator")), + UNO_QUERY); + + // parse command line arguments + sal_Bool bPrintEvent = sal_False; + sal_Bool bOpenEvent = sal_True; + sal_Bool bViewEvent = sal_False; + sal_Bool bStartEvent = sal_False; + sal_Bool bPrintToEvent = sal_False; + sal_Bool bPrinterName = sal_False; + sal_Bool bForceOpenEvent = sal_False; + sal_Bool bForceNewEvent = sal_False; + sal_Bool bDisplaySpec = sal_False; + + m_eArgumentCount = NONE; + + for (;;) + { + ::rtl::OUString aArg; + if ( !supplier.next( &aArg ) ) + { + break; + } + // convert file URLs to internal form #112849# + if (aArg.indexOf(OUString::createFromAscii("file:"))==0 && + xTranslator.is()) + { + OUString tmp(xTranslator->translateToInternal(aArg)); + if (tmp.getLength() > 0) + aArg = tmp; + } + String aArgStr = aArg; + + if ( aArg.getLength() > 0 ) + { + m_eArgumentCount = m_eArgumentCount == NONE ? ONE : MANY; + if ( !InterpretCommandLineParameter( aArg )) + { + if ( aArgStr.GetChar(0) == '-' ) + { + // handle this argument as an option + if ( aArgStr.EqualsIgnoreCaseAscii( "-n" )) + { + // force new documents based on the following documents + bForceNewEvent = sal_True; + bOpenEvent = sal_False; + bForceOpenEvent = sal_False; + bPrintToEvent = sal_False; + bPrintEvent = sal_False; + bViewEvent = sal_False; + bStartEvent = sal_False; + bDisplaySpec = sal_False; + } + else if ( aArgStr.EqualsIgnoreCaseAscii( "-o" )) + { + // force open documents regards if they are templates or not + bForceOpenEvent = sal_True; + bOpenEvent = sal_False; + bForceNewEvent = sal_False; + bPrintToEvent = sal_False; + bPrintEvent = sal_False; + bViewEvent = sal_False; + bStartEvent = sal_False; + bDisplaySpec = sal_False; + } + else if ( aArgStr.EqualsIgnoreCaseAscii( "-pt" )) + { + // Print to special printer + bPrintToEvent = sal_True; + bPrinterName = sal_True; + bPrintEvent = sal_False; + bOpenEvent = sal_False; + bForceNewEvent = sal_False; + bViewEvent = sal_False; + bStartEvent = sal_False; + bDisplaySpec = sal_False; + bForceOpenEvent = sal_False; + } + else if ( aArgStr.EqualsIgnoreCaseAscii( "-p" )) + { + // Print to default printer + bPrintEvent = sal_True; + bPrintToEvent = sal_False; + bOpenEvent = sal_False; + bForceNewEvent = sal_False; + bForceOpenEvent = sal_False; + bViewEvent = sal_False; + bStartEvent = sal_False; + bDisplaySpec = sal_False; + } + else if ( aArgStr.EqualsIgnoreCaseAscii( "-view" )) + { + // open in viewmode + bOpenEvent = sal_False; + bPrintEvent = sal_False; + bPrintToEvent = sal_False; + bForceNewEvent = sal_False; + bForceOpenEvent = sal_False; + bViewEvent = sal_True; + bStartEvent = sal_False; + bDisplaySpec = sal_False; + } + else if ( aArgStr.EqualsIgnoreCaseAscii( "-show" )) + { + // open in viewmode + bOpenEvent = sal_False; + bViewEvent = sal_False; + bStartEvent = sal_True; + bPrintEvent = sal_False; + bPrintToEvent = sal_False; + bForceNewEvent = sal_False; + bForceOpenEvent = sal_False; + bDisplaySpec = sal_False; + } + else if ( aArgStr.EqualsIgnoreCaseAscii( "-display" )) + { + // set display + bOpenEvent = sal_False; + bPrintEvent = sal_False; + bForceOpenEvent = sal_False; + bPrintToEvent = sal_False; + bForceNewEvent = sal_False; + bViewEvent = sal_False; + bStartEvent = sal_False; + bDisplaySpec = sal_True; + } + else if ( aArgStr.EqualsIgnoreCaseAscii( "-language" )) + { + bOpenEvent = sal_False; + bPrintEvent = sal_False; + bForceOpenEvent = sal_False; + bPrintToEvent = sal_False; + bForceNewEvent = sal_False; + bViewEvent = sal_False; + bStartEvent = sal_False; + bDisplaySpec = sal_False; + } + + #ifdef MACOSX + /* #i84053# ignore -psn on Mac + Platform dependent #ifdef here is ugly, however this is currently + the only platform dependent parameter. Should more appear + we should find a better solution + */ + else if ( aArgStr.CompareToAscii( "-psn", 4 ) == COMPARE_EQUAL ) + { + // finder argument from MacOSX + bOpenEvent = sal_False; + bPrintEvent = sal_False; + bForceOpenEvent = sal_False; + bPrintToEvent = sal_False; + bForceNewEvent = sal_False; + bViewEvent = sal_False; + bStartEvent = sal_False; + bDisplaySpec = sal_False; + } + #endif + } + else + { + if ( bPrinterName && bPrintToEvent ) + { + // first argument after "-pt" this must be the printer name + AddStringListParam_Impl( CMD_STRINGPARAM_PRINTERNAME, aArgStr ); + bPrinterName = sal_False; + } + else + { + // handle this argument as a filename + if ( bOpenEvent ) + AddStringListParam_Impl( CMD_STRINGPARAM_OPENLIST, aArgStr ); + else if ( bViewEvent ) + AddStringListParam_Impl( CMD_STRINGPARAM_VIEWLIST, aArgStr ); + else if ( bStartEvent ) + AddStringListParam_Impl( CMD_STRINGPARAM_STARTLIST, aArgStr ); + else if ( bPrintEvent ) + AddStringListParam_Impl( CMD_STRINGPARAM_PRINTLIST, aArgStr ); + else if ( bPrintToEvent ) + AddStringListParam_Impl( CMD_STRINGPARAM_PRINTTOLIST, aArgStr ); + else if ( bForceNewEvent ) + AddStringListParam_Impl( CMD_STRINGPARAM_FORCENEWLIST, aArgStr ); + else if ( bForceOpenEvent ) + AddStringListParam_Impl( CMD_STRINGPARAM_FORCEOPENLIST, aArgStr ); + else if ( bDisplaySpec ){ + AddStringListParam_Impl( CMD_STRINGPARAM_DISPLAY, aArgStr ); + bDisplaySpec = sal_False; // only one display, not a lsit + bOpenEvent = sal_True; // set back to standard + } + } + } + } + } + } +} + +void CommandLineArgs::AddStringListParam_Impl( StringParam eParam, const rtl::OUString& aParam ) +{ + OSL_ASSERT( eParam >= 0 && eParam < CMD_STRINGPARAM_COUNT ); + if ( m_aStrParams[eParam].getLength() ) + m_aStrParams[eParam] += ::rtl::OUString::valueOf( (sal_Unicode)APPEVENT_PARAM_DELIMITER ); + m_aStrParams[eParam] += aParam; + m_aStrSetParams[eParam] = sal_True; +} + +void CommandLineArgs::SetBoolParam_Impl( BoolParam eParam, sal_Bool bValue ) +{ + OSL_ASSERT( eParam >= 0 && eParam < CMD_BOOLPARAM_COUNT ); + m_aBoolParams[eParam] = bValue; +} + +sal_Bool CommandLineArgs::InterpretCommandLineParameter( const ::rtl::OUString& aArg ) +{ + String aArgStr( aArg ); + + if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-minimized" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_MINIMIZED, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-invisible" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_INVISIBLE, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-norestore" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_NORESTORE, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-nodefault" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_NODEFAULT, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-bean" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_BEAN, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-plugin" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_PLUGIN, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-server" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_SERVER, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-headless" )) == sal_True ) + { + // Headless means also invisibile, so set this parameter to true! + SetBoolParam_Impl( CMD_BOOLPARAM_HEADLESS, sal_True ); + SetBoolParam_Impl( CMD_BOOLPARAM_INVISIBLE, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-quickstart" )) == sal_True ) + { +#if defined(WNT) || defined(OS2) || defined(QUARTZ) + SetBoolParam_Impl( CMD_BOOLPARAM_QUICKSTART, sal_True ); +#endif + SetBoolParam_Impl( CMD_BOOLPARAM_NOQUICKSTART, sal_False ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-quickstart=no" ))) + { + SetBoolParam_Impl( CMD_BOOLPARAM_NOQUICKSTART, sal_True ); + SetBoolParam_Impl( CMD_BOOLPARAM_QUICKSTART, sal_False ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-terminate_after_init" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_TERMINATEAFTERINIT, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-nofirststartwizard" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_NOFIRSTSTARTWIZARD, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-nologo" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_NOLOGO, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-nolockcheck" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_NOLOCKCHECK, sal_True ); + // Workaround for automated testing + ::svt::DocumentLockFile::AllowInteraction( sal_False ); + + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-help" )) + || aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-h" )) + || aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-?" ))) + { + SetBoolParam_Impl( CMD_BOOLPARAM_HELP, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-helpwriter" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_HELPWRITER, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-helpcalc" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_HELPCALC, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-helpdraw" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_HELPDRAW, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-helpimpress" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_HELPIMPRESS, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-helpbase" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_HELPBASE, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-helpbasic" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_HELPBASIC, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-helpmath" )) == sal_True ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_HELPMATH, sal_True ); + return sal_True; + } + #ifdef MACOSX + /* #i84053# ignore -psn on Mac + Platform dependent #ifdef here is ugly, however this is currently + the only platform dependent parameter. Should more appear + we should find a better solution + */ + else if ( aArg.compareToAscii( "-psn", 4 ) == 0 ) + { + SetBoolParam_Impl( CMD_BOOLPARAM_PSN, sal_True ); + return sal_True; + } + #endif + else if ( aArgStr.Copy(0, 8).EqualsIgnoreCaseAscii( "-accept=" )) + { + AddStringListParam_Impl( CMD_STRINGPARAM_ACCEPT, aArgStr.Copy( 8 ) ); + return sal_True; + } + else if ( aArgStr.Copy(0, 10).EqualsIgnoreCaseAscii( "-unaccept=" )) + { + AddStringListParam_Impl( CMD_STRINGPARAM_UNACCEPT, aArgStr.Copy( 10 ) ); + return sal_True; + } + else if ( aArgStr.CompareIgnoreCaseToAscii( "-portal," , + RTL_CONSTASCII_LENGTH( "-portal," )) == COMPARE_EQUAL ) + { + AddStringListParam_Impl( CMD_STRINGPARAM_PORTAL, aArgStr.Copy( RTL_CONSTASCII_LENGTH( "-portal," )) ); + return sal_True; + } + else if ( aArgStr.Copy( 0, 7 ).EqualsIgnoreCaseAscii( "-userid" )) + { + if ( aArgStr.Len() > 8 ) + { + rtl::OUString aUserDir = aArgStr; + AddStringListParam_Impl( + CMD_STRINGPARAM_USERDIR, + ::rtl::Uri::decode( aUserDir.copy( 8 ), + rtl_UriDecodeWithCharset, + RTL_TEXTENCODING_UTF8 ) ); + } + return sal_True; + } + else if ( aArgStr.Copy( 0, 15).EqualsIgnoreCaseAscii( "-clientdisplay=" )) + { + AddStringListParam_Impl( CMD_STRINGPARAM_CLIENTDISPLAY, aArgStr.Copy( 15 ) ); + return sal_True; + } + else if ( aArgStr.Copy(0, 9).EqualsIgnoreCaseAscii( "-version=" )) + { + AddStringListParam_Impl( CMD_STRINGPARAM_VERSION, aArgStr.Copy( 9 ) ); + return sal_True; + } + else if ( aArgStr.Copy(0, 10).EqualsIgnoreCaseAscii( "-language=" )) + { + AddStringListParam_Impl( CMD_STRINGPARAM_LANGUAGE, aArgStr.Copy( 10 ) ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-writer" )) == sal_True ) + { + sal_Bool bAlreadySet = CheckGroupMembers( CMD_GRPID_MODULE, CMD_BOOLPARAM_WRITER ); + if ( !bAlreadySet ) + SetBoolParam_Impl( CMD_BOOLPARAM_WRITER, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-calc" )) == sal_True ) + { + sal_Bool bAlreadySet = CheckGroupMembers( CMD_GRPID_MODULE, CMD_BOOLPARAM_CALC ); + if ( !bAlreadySet ) + SetBoolParam_Impl( CMD_BOOLPARAM_CALC, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-draw" )) == sal_True ) + { + sal_Bool bAlreadySet = CheckGroupMembers( CMD_GRPID_MODULE, CMD_BOOLPARAM_DRAW ); + if ( !bAlreadySet ) + SetBoolParam_Impl( CMD_BOOLPARAM_DRAW, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-impress" )) == sal_True ) + { + sal_Bool bAlreadySet = CheckGroupMembers( CMD_GRPID_MODULE, CMD_BOOLPARAM_IMPRESS ); + if ( !bAlreadySet ) + SetBoolParam_Impl( CMD_BOOLPARAM_IMPRESS, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-base" )) == sal_True ) + { + sal_Bool bAlreadySet = CheckGroupMembers( CMD_GRPID_MODULE, CMD_BOOLPARAM_BASE ); + if ( !bAlreadySet ) + SetBoolParam_Impl( CMD_BOOLPARAM_BASE, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-global" )) == sal_True ) + { + sal_Bool bAlreadySet = CheckGroupMembers( CMD_GRPID_MODULE, CMD_BOOLPARAM_GLOBAL ); + if ( !bAlreadySet ) + SetBoolParam_Impl( CMD_BOOLPARAM_GLOBAL, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-math" )) == sal_True ) + { + sal_Bool bAlreadySet = CheckGroupMembers( CMD_GRPID_MODULE, CMD_BOOLPARAM_MATH ); + if ( !bAlreadySet ) + SetBoolParam_Impl( CMD_BOOLPARAM_MATH, sal_True ); + return sal_True; + } + else if ( aArg.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-web" )) == sal_True ) + { + sal_Bool bAlreadySet = CheckGroupMembers( CMD_GRPID_MODULE, CMD_BOOLPARAM_WEB ); + if ( !bAlreadySet ) + SetBoolParam_Impl( CMD_BOOLPARAM_WEB, sal_True ); + return sal_True; + } + + return sal_False; +} + +sal_Bool CommandLineArgs::CheckGroupMembers( GroupParamId nGroupId, BoolParam nExcludeMember ) const +{ + // Check if at least one bool param out of a group is set. An exclude member can be provided. + for ( int i = 0; i < m_pGroupDefinitions[nGroupId].nCount; i++ ) + { + BoolParam nParam = m_pGroupDefinitions[nGroupId].pGroupMembers[i]; + if ( nParam != nExcludeMember && m_aBoolParams[nParam] ) + return sal_True; + } + + return sal_False; +} + +void CommandLineArgs::ResetParamValues() +{ + int i; + + for ( i = 0; i < CMD_BOOLPARAM_COUNT; i++ ) + m_aBoolParams[i] = sal_False; + for ( i = 0; i < CMD_STRINGPARAM_COUNT; i++ ) + m_aStrSetParams[i] = sal_False; + m_eArgumentCount = NONE; +} + +void CommandLineArgs::SetBoolParam( BoolParam eParam, sal_Bool bNewValue ) +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + + OSL_ASSERT( ( eParam >= 0 && eParam < CMD_BOOLPARAM_COUNT ) ); + m_aBoolParams[eParam] = bNewValue; +} + +sal_Bool CommandLineArgs::IsMinimized() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_MINIMIZED ]; +} + +sal_Bool CommandLineArgs::IsInvisible() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_INVISIBLE ]; +} + +sal_Bool CommandLineArgs::IsNoRestore() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_NORESTORE ]; +} + +sal_Bool CommandLineArgs::IsNoDefault() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_NODEFAULT ]; +} + +sal_Bool CommandLineArgs::IsBean() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_BEAN ]; +} + +sal_Bool CommandLineArgs::IsServer() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_SERVER ]; +} + +sal_Bool CommandLineArgs::IsHeadless() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_HEADLESS ]; +} + +sal_Bool CommandLineArgs::IsQuickstart() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_QUICKSTART ]; +} + +sal_Bool CommandLineArgs::IsNoQuickstart() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_NOQUICKSTART ]; +} + +sal_Bool CommandLineArgs::IsTerminateAfterInit() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_TERMINATEAFTERINIT ]; +} + +sal_Bool CommandLineArgs::IsNoFirstStartWizard() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_NOFIRSTSTARTWIZARD ]; +} + +sal_Bool CommandLineArgs::IsNoLogo() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_NOLOGO ]; +} + +sal_Bool CommandLineArgs::IsNoLockcheck() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_NOLOCKCHECK ]; +} + +sal_Bool CommandLineArgs::IsHelp() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_HELP ]; +} +sal_Bool CommandLineArgs::IsHelpWriter() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_HELPWRITER ]; +} + +sal_Bool CommandLineArgs::IsHelpCalc() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_HELPCALC ]; +} + +sal_Bool CommandLineArgs::IsHelpDraw() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_HELPDRAW ]; +} + +sal_Bool CommandLineArgs::IsHelpImpress() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_HELPIMPRESS ]; +} + +sal_Bool CommandLineArgs::IsHelpBase() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_HELPBASE ]; +} +sal_Bool CommandLineArgs::IsHelpMath() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_HELPMATH ]; +} +sal_Bool CommandLineArgs::IsHelpBasic() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_HELPBASIC ]; +} + +sal_Bool CommandLineArgs::IsWriter() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_WRITER ]; +} + +sal_Bool CommandLineArgs::IsCalc() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_CALC ]; +} + +sal_Bool CommandLineArgs::IsDraw() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_DRAW ]; +} + +sal_Bool CommandLineArgs::IsImpress() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_IMPRESS ]; +} + +sal_Bool CommandLineArgs::IsBase() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_BASE ]; +} + +sal_Bool CommandLineArgs::IsGlobal() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_GLOBAL ]; +} + +sal_Bool CommandLineArgs::IsMath() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_MATH ]; +} + +sal_Bool CommandLineArgs::IsWeb() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_aBoolParams[ CMD_BOOLPARAM_WEB ]; +} + +sal_Bool CommandLineArgs::HasModuleParam() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return CheckGroupMembers( CMD_GRPID_MODULE, CMD_BOOLPARAM_COUNT ); +} + +sal_Bool CommandLineArgs::GetPortalConnectString( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_PORTAL ]; + return m_aStrSetParams[ CMD_STRINGPARAM_PORTAL ]; +} + +sal_Bool CommandLineArgs::GetAcceptString( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_ACCEPT ]; + return m_aStrSetParams[ CMD_STRINGPARAM_ACCEPT ]; +} + +sal_Bool CommandLineArgs::GetUnAcceptString( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_UNACCEPT ]; + return m_aStrSetParams[ CMD_STRINGPARAM_UNACCEPT ]; +} + +sal_Bool CommandLineArgs::GetOpenList( ::rtl::OUString& rPara) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_OPENLIST ]; + return m_aStrSetParams[ CMD_STRINGPARAM_OPENLIST ]; +} + +sal_Bool CommandLineArgs::GetViewList( ::rtl::OUString& rPara) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_VIEWLIST ]; + return m_aStrSetParams[ CMD_STRINGPARAM_VIEWLIST ]; +} + +sal_Bool CommandLineArgs::GetStartList( ::rtl::OUString& rPara) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_STARTLIST ]; + return m_aStrSetParams[ CMD_STRINGPARAM_STARTLIST ]; +} + +sal_Bool CommandLineArgs::GetForceOpenList( ::rtl::OUString& rPara) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_FORCEOPENLIST ]; + return m_aStrSetParams[ CMD_STRINGPARAM_FORCEOPENLIST ]; +} + +sal_Bool CommandLineArgs::GetForceNewList( ::rtl::OUString& rPara) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_FORCENEWLIST ]; + return m_aStrSetParams[ CMD_STRINGPARAM_FORCENEWLIST ]; +} + +sal_Bool CommandLineArgs::GetPrintList( ::rtl::OUString& rPara) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_PRINTLIST ]; + return m_aStrSetParams[ CMD_STRINGPARAM_PRINTLIST ]; +} + +sal_Bool CommandLineArgs::GetPrintToList( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_PRINTTOLIST ]; + return m_aStrSetParams[ CMD_STRINGPARAM_PRINTTOLIST ]; +} + +sal_Bool CommandLineArgs::GetPrinterName( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_PRINTERNAME ]; + return m_aStrSetParams[ CMD_STRINGPARAM_PRINTERNAME ]; +} + +sal_Bool CommandLineArgs::GetLanguage( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_LANGUAGE ]; + return m_aStrSetParams[ CMD_STRINGPARAM_LANGUAGE ]; +} + +sal_Bool CommandLineArgs::IsEmpty() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + return m_eArgumentCount == NONE; +} + +sal_Bool CommandLineArgs::IsEmptyOrAcceptOnly() const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + + return m_eArgumentCount == NONE || + ( ( m_eArgumentCount == ONE ) && ( m_aStrParams[ CMD_STRINGPARAM_ACCEPT ].getLength() )) || + ( ( m_eArgumentCount == ONE ) && m_aBoolParams[ CMD_BOOLPARAM_PSN ] ); +} + +} // namespace desktop diff --git a/desktop/source/app/cmdlineargs.hxx b/desktop/source/app/cmdlineargs.hxx new file mode 100644 index 000000000000..615577098c2d --- /dev/null +++ b/desktop/source/app/cmdlineargs.hxx @@ -0,0 +1,212 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _DESKTOP_COMMANDLINEARGS_HXX_ +#define _DESKTOP_COMMANDLINEARGS_HXX_ + +#include <rtl/ustring.hxx> +#include <osl/mutex.hxx> +#include "boost/optional.hpp" + +namespace desktop +{ + +class CommandLineArgs +{ + public: + enum BoolParam // must be zero based! + { + CMD_BOOLPARAM_MINIMIZED, + CMD_BOOLPARAM_INVISIBLE, + CMD_BOOLPARAM_NORESTORE, + CMD_BOOLPARAM_BEAN, + CMD_BOOLPARAM_PLUGIN, + CMD_BOOLPARAM_SERVER, + CMD_BOOLPARAM_HEADLESS, + CMD_BOOLPARAM_QUICKSTART, + CMD_BOOLPARAM_NOQUICKSTART, + CMD_BOOLPARAM_TERMINATEAFTERINIT, + CMD_BOOLPARAM_NOFIRSTSTARTWIZARD, + CMD_BOOLPARAM_NOLOGO, + CMD_BOOLPARAM_NOLOCKCHECK, + CMD_BOOLPARAM_NODEFAULT, + CMD_BOOLPARAM_HELP, + CMD_BOOLPARAM_WRITER, + CMD_BOOLPARAM_CALC, + CMD_BOOLPARAM_DRAW, + CMD_BOOLPARAM_IMPRESS, + CMD_BOOLPARAM_GLOBAL, + CMD_BOOLPARAM_MATH, + CMD_BOOLPARAM_WEB, + CMD_BOOLPARAM_BASE, + CMD_BOOLPARAM_HELPWRITER, + CMD_BOOLPARAM_HELPCALC, + CMD_BOOLPARAM_HELPDRAW, + CMD_BOOLPARAM_HELPBASIC, + CMD_BOOLPARAM_HELPMATH, + CMD_BOOLPARAM_HELPIMPRESS, + CMD_BOOLPARAM_HELPBASE, + CMD_BOOLPARAM_PSN, + CMD_BOOLPARAM_COUNT // must be last element! + }; + + enum StringParam // must be zero based! + { + CMD_STRINGPARAM_PORTAL, + CMD_STRINGPARAM_ACCEPT, + CMD_STRINGPARAM_UNACCEPT, + CMD_STRINGPARAM_USERDIR, + CMD_STRINGPARAM_CLIENTDISPLAY, + CMD_STRINGPARAM_OPENLIST, + CMD_STRINGPARAM_VIEWLIST, + CMD_STRINGPARAM_STARTLIST, + CMD_STRINGPARAM_FORCEOPENLIST, + CMD_STRINGPARAM_FORCENEWLIST, + CMD_STRINGPARAM_PRINTLIST, + CMD_STRINGPARAM_VERSION, + CMD_STRINGPARAM_PRINTTOLIST, + CMD_STRINGPARAM_PRINTERNAME, + CMD_STRINGPARAM_DISPLAY, + CMD_STRINGPARAM_LANGUAGE, + CMD_STRINGPARAM_COUNT // must be last element! + }; + + enum GroupParamId + { + CMD_GRPID_MODULE, + CMD_GRPID_COUNT + }; + + struct Supplier { + // Thrown from constructors and next: + class Exception { + public: + Exception(); + Exception(Exception const &); + virtual ~Exception(); + Exception & operator =(Exception const &); + }; + + virtual ~Supplier(); + virtual boost::optional< rtl::OUString > getCwdUrl() = 0; + virtual bool next(rtl::OUString * argument) = 0; + }; + + CommandLineArgs(); + CommandLineArgs( Supplier& supplier ); + + boost::optional< rtl::OUString > getCwdUrl() const { return m_cwdUrl; } + + // generic methods to access parameter + void SetBoolParam( BoolParam eParam, sal_Bool bNewValue ); + + // Access to bool parameters + sal_Bool IsMinimized() const; + sal_Bool IsInvisible() const; + sal_Bool IsNoRestore() const; + sal_Bool IsNoDefault() const; + sal_Bool IsBean() const; + sal_Bool IsServer() const; + sal_Bool IsHeadless() const; + sal_Bool IsQuickstart() const; + sal_Bool IsNoQuickstart() const; + sal_Bool IsTerminateAfterInit() const; + sal_Bool IsNoFirstStartWizard() const; + sal_Bool IsNoLogo() const; + sal_Bool IsNoLockcheck() const; + sal_Bool IsHelp() const; + sal_Bool IsHelpWriter() const; + sal_Bool IsHelpCalc() const; + sal_Bool IsHelpDraw() const; + sal_Bool IsHelpImpress() const; + sal_Bool IsHelpBase() const; + sal_Bool IsHelpMath() const; + sal_Bool IsHelpBasic() const; + sal_Bool IsWriter() const; + sal_Bool IsCalc() const; + sal_Bool IsDraw() const; + sal_Bool IsImpress() const; + sal_Bool IsBase() const; + sal_Bool IsGlobal() const; + sal_Bool IsMath() const; + sal_Bool IsWeb() const; + sal_Bool HasModuleParam() const; + + // Access to string parameters + sal_Bool GetPortalConnectString( ::rtl::OUString& rPara) const; + sal_Bool GetAcceptString( ::rtl::OUString& rPara) const; + sal_Bool GetUnAcceptString( ::rtl::OUString& rPara) const; + sal_Bool GetOpenList( ::rtl::OUString& rPara) const; + sal_Bool GetViewList( ::rtl::OUString& rPara) const; + sal_Bool GetStartList( ::rtl::OUString& rPara) const; + sal_Bool GetForceOpenList( ::rtl::OUString& rPara) const; + sal_Bool GetForceNewList( ::rtl::OUString& rPara) const; + sal_Bool GetPrintList( ::rtl::OUString& rPara) const; + sal_Bool GetPrintToList( ::rtl::OUString& rPara ) const; + sal_Bool GetPrinterName( ::rtl::OUString& rPara ) const; + sal_Bool GetLanguage( ::rtl::OUString& rPara ) const; + + // Special analyzed states (does not match directly to a command line parameter!) + sal_Bool IsPrinting() const; + sal_Bool IsEmpty() const; + sal_Bool IsEmptyOrAcceptOnly() const; + + private: + enum Count { NONE, ONE, MANY }; + + struct GroupDefinition + { + sal_Int32 nCount; + BoolParam* pGroupMembers; + }; + + // no copy and operator= + CommandLineArgs( const CommandLineArgs& ); + CommandLineArgs operator=( const CommandLineArgs& ); + + sal_Bool InterpretCommandLineParameter( const ::rtl::OUString& ); + void ParseCommandLine_Impl( Supplier& supplier ); + void ResetParamValues(); + sal_Bool CheckGroupMembers( GroupParamId nGroup, BoolParam nExcludeMember ) const; + + void AddStringListParam_Impl( StringParam eParam, const rtl::OUString& aParam ); + void SetBoolParam_Impl( BoolParam eParam, sal_Bool bValue ); + + boost::optional< rtl::OUString > m_cwdUrl; + sal_Bool m_aBoolParams[ CMD_BOOLPARAM_COUNT ]; // Stores boolean parameters + rtl::OUString m_aStrParams[ CMD_STRINGPARAM_COUNT ]; // Stores string parameters + sal_Bool m_aStrSetParams[ CMD_STRINGPARAM_COUNT ]; // Stores if string parameters are provided on cmdline + Count m_eArgumentCount; // Number of Args + mutable ::osl::Mutex m_aMutex; + + // static definition for groups where only one member can be true + static GroupDefinition m_pGroupDefinitions[ CMD_GRPID_COUNT ]; +}; + +} + +#endif diff --git a/desktop/source/app/cmdlinehelp.cxx b/desktop/source/app/cmdlinehelp.cxx new file mode 100644 index 000000000000..c4530e9ce61c --- /dev/null +++ b/desktop/source/app/cmdlinehelp.cxx @@ -0,0 +1,173 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include <stdlib.h> +#ifdef UNX +#include <stdio.h> +#endif +#include <sal/types.h> +#include <tools/string.hxx> +#include <vcl/msgbox.hxx> +#include <rtl/bootstrap.hxx> +#include <app.hxx> + +#include "desktopresid.hxx" +#include "desktop.hrc" +#include "cmdlinehelp.hxx" + +namespace desktop +{ + // to be able to display the help nicely in a dialog box with propotional font, + // we need to split it in chunks... + // ___HEAD___ + // LEFT RIGHT + // LEFT RIGHT + // LEFT RIGHT + // __BOTTOM__ + // [OK] + + const char *aCmdLineHelp_head = + "%PRODUCTNAME %PRODUCTVERSION %PRODUCTEXTENSION %BUILDID\n"\ + "\n"\ + "Usage: %CMDNAME [options] [documents...]\n"\ + "\n"\ + "Options:\n"; + const char *aCmdLineHelp_left = + "-minimized \n"\ + "-invisible \n"\ + "-norestore \n"\ + "-quickstart \n"\ + "-nologo \n"\ + "-nolockcheck \n"\ + "-nodefault \n"\ + "-headless \n"\ + "-help/-h/-? \n"\ + "-writer \n"\ + "-calc \n"\ + "-draw \n"\ + "-impress \n"\ + "-base \n"\ + "-math \n"\ + "-global \n"\ + "-web \n"\ + "-o \n"\ + "-n \n"; + const char *aCmdLineHelp_right = + "keep startup bitmap minimized.\n"\ + "no startup screen, no default document and no UI.\n"\ + "suppress restart/restore after fatal errors.\n"\ + "starts the quickstart service (only available on windows and OS/2 platform)\n"\ + "don't show startup screen.\n"\ + "don't check for remote instances using the installation\n"\ + "don't start with an empty document\n"\ + "like invisible but no userinteraction at all.\n"\ + "show this message and exit.\n"\ + "create new text document.\n"\ + "create new spreadsheet document.\n"\ + "create new drawing.\n"\ + "create new presentation.\n"\ + "create new database.\n"\ + "create new formula.\n"\ + "create new global document.\n"\ + "create new HTML document.\n"\ + "open documents regardless whether they are templates or not.\n"\ + "always open documents as new files (use as template).\n"; + const char *aCmdLineHelp_bottom = + "-display <display>\n"\ + " Specify X-Display to use in Unix/X11 versions.\n" + "-p <documents...>\n"\ + " print the specified documents on the default printer.\n"\ + "-pt <printer> <documents...>\n"\ + " print the specified documents on the specified printer.\n"\ + "-view <documents...>\n"\ + " open the specified documents in viewer-(readonly-)mode.\n"\ + "-show <presentation>\n"\ + " open the specified presentation and start it immediately\n"\ + "-accept=<accept-string>\n"\ + " Specify an UNO connect-string to create an UNO acceptor through which\n"\ + " other programs can connect to access the API\n"\ + "-unaccept=<accept-string>\n"\ + " Close an acceptor that was created with -accept=<accept-string>\n"\ + " Use -unnaccept=all to close all open acceptors\n"\ + "Remaining arguments will be treated as filenames or URLs of documents to open.\n"; + + void ReplaceStringHookProc( UniString& rStr ); + + void displayCmdlineHelp() + { + // if you put variables in other chunks don't forget to call the replace routines + // for those chunks... + String aHelpMessage_head(aCmdLineHelp_head, RTL_TEXTENCODING_ASCII_US); + String aHelpMessage_left(aCmdLineHelp_left, RTL_TEXTENCODING_ASCII_US); + String aHelpMessage_right(aCmdLineHelp_right, RTL_TEXTENCODING_ASCII_US); + String aHelpMessage_bottom(aCmdLineHelp_bottom, RTL_TEXTENCODING_ASCII_US); + ReplaceStringHookProc(aHelpMessage_head); + ::rtl::OUString aDefault; + String aVerId( ::utl::Bootstrap::getBuildIdData( aDefault )); + aHelpMessage_head.SearchAndReplaceAscii( "%BUILDID", aVerId ); + aHelpMessage_head.SearchAndReplaceAscii( "%CMDNAME", String( "soffice", RTL_TEXTENCODING_ASCII_US) ); +#ifdef UNX + // on unix use console for output + fprintf(stderr, "%s\n", ByteString(aHelpMessage_head, + RTL_TEXTENCODING_ASCII_US).GetBuffer()); + // merge left and right column + int n = aHelpMessage_left.GetTokenCount ('\n'); + ByteString bsLeft(aHelpMessage_left, RTL_TEXTENCODING_ASCII_US); + ByteString bsRight(aHelpMessage_right, RTL_TEXTENCODING_ASCII_US); + for ( int i = 0; i < n; i++ ) + { + fprintf(stderr, "%s", bsLeft.GetToken(i, '\n').GetBuffer()); + fprintf(stderr, "%s\n", bsRight.GetToken(i, '\n').GetBuffer()); + } + fprintf(stderr, "%s", ByteString(aHelpMessage_bottom, + RTL_TEXTENCODING_ASCII_US).GetBuffer()); +#else + // rest gets a dialog box + CmdlineHelpDialog aDlg; + aDlg.m_ftHead.SetText(aHelpMessage_head); + aDlg.m_ftLeft.SetText(aHelpMessage_left); + aDlg.m_ftRight.SetText(aHelpMessage_right); + aDlg.m_ftBottom.SetText(aHelpMessage_bottom); + aDlg.Execute(); +#endif + } +#ifndef UNX + CmdlineHelpDialog::CmdlineHelpDialog (void) + : ModalDialog( NULL, DesktopResId( DLG_CMDLINEHELP ) ) + , m_ftHead( this, DesktopResId( TXT_DLG_CMDLINEHELP_HEADER ) ) + , m_ftLeft( this, DesktopResId( TXT_DLG_CMDLINEHELP_LEFT ) ) + , m_ftRight( this, DesktopResId( TXT_DLG_CMDLINEHELP_RIGHT ) ) + , m_ftBottom( this, DesktopResId( TXT_DLG_CMDLINEHELP_BOTTOM ) ) + , m_btOk( this, DesktopResId( BTN_DLG_CMDLINEHELP_OK ) ) + { + FreeResource(); + } +#endif +} diff --git a/desktop/source/app/cmdlinehelp.hxx b/desktop/source/app/cmdlinehelp.hxx new file mode 100644 index 000000000000..4bca6e7e7d1a --- /dev/null +++ b/desktop/source/app/cmdlinehelp.hxx @@ -0,0 +1,23 @@ +#include <vcl/dialog.hxx> +#include <vcl/fixed.hxx> +#ifndef _SV_BUTTON_HXX +#include <vcl/button.hxx> +#endif + +namespace desktop +{ + void displayCmdlineHelp( void ); +#ifndef UNX + class CmdlineHelpDialog : public ModalDialog + { + public: + CmdlineHelpDialog ( void ); + + FixedText m_ftHead; + FixedText m_ftLeft; + FixedText m_ftRight; + FixedText m_ftBottom; + OKButton m_btOk; + }; +#endif +} diff --git a/desktop/source/app/configinit.cxx b/desktop/source/app/configinit.cxx new file mode 100644 index 000000000000..bd722a136e8a --- /dev/null +++ b/desktop/source/app/configinit.cxx @@ -0,0 +1,303 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include "configinit.hxx" + +#include "desktop.hrc" +#include "app.hxx" +#include <comphelper/processfactory.hxx> +#include <uno/current_context.hxx> +#include <cppuhelper/implbase1.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <stdio.h> +#include <map> +#include <com/sun/star/lang/ServiceNotRegisteredException.hpp> +#include <com/sun/star/configuration/CannotLoadConfigurationException.hpp> +#include <com/sun/star/configuration/InvalidBootstrapFileException.hpp> +#include <com/sun/star/configuration/backend/BackendSetupException.hpp> +#include <com/sun/star/configuration/backend/CannotConnectException.hpp> + +// ---------------------------------------------------------------------------- + +namespace uno = ::com::sun::star::uno; +namespace lang = ::com::sun::star::lang; +namespace configuration = ::com::sun::star::configuration; +namespace backend = ::com::sun::star::configuration::backend; +using rtl::OUString; +using uno::UNO_QUERY; +using desktop::Desktop; + +// ---------------------------------------------------------------------------- +static char const CONFIGURATION_PROVIDER[] = "com.sun.star.configuration.ConfigurationProvider"; + +static char const CONFIGURATION_ERROR_HANDLER[] = "com.sun.star.configuration.backend.InteractionHandler"; + +// must be aligned with configmgr/source/misc/configinteractionhandler +static char const CONFIG_ERROR_HANDLER[] = "configuration.interaction-handler"; +// ---------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- +#define arraysize( arr ) ( sizeof (arr)/sizeof *(arr) ) + +typedef uno::Reference< lang::XMultiServiceFactory > ConfigurationProvider; + +#define OUSTRING( constascii ) OUString( RTL_CONSTASCII_USTRINGPARAM( constascii ) ) + +#define OU2O( ustr, enc ) rtl::OUStringToOString( (ustr), RTL_TEXTENCODING_ ## enc ) + +#define k_PROVIDER OUSTRING( CONFIGURATION_PROVIDER ) +#define k_ERRORHANDLER OUSTRING( CONFIGURATION_ERROR_HANDLER ) +// ---------------------------------------------------------------------------- +// Get a message string securely. There is a fallback string if the resource +// is not available. Adapted from Desktop::GetMsgString() + +OUString getMsgString( USHORT nId, char const * aFallBackMsg ) +{ + ResMgr* pResMgr = Desktop::GetDesktopResManager(); + if ( !pResMgr || !nId ) + return OUString::createFromAscii(aFallBackMsg); + else + return OUString( String(ResId( nId, *pResMgr ))); +} +// ---------------------------------------------------------------------------- +/** Creates the normal configuration provider. + +*/ +static +ConfigurationProvider createDefaultConfigurationProvider( ) +{ + uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); + + OSL_ENSURE( xServiceManager.is(),"No ServiceManager set for CreateApplicationConfigurationProvider"); + + ConfigurationProvider xProvider; + + if (xServiceManager.is()) + { + + xProvider.set( xServiceManager->createInstance(k_PROVIDER), UNO_QUERY); + } + + if (!xProvider.is()) + { + OUString const sMsg = OUSTRING("Service \"") + k_PROVIDER + + OUSTRING("\" is not available at the service manager."); + + throw lang::ServiceNotRegisteredException(sMsg, xServiceManager); + } + + return xProvider; +} +// ---------------------------------------------------------------------------- +/// @attention this method must be called from a catch statement! +static void handleGeneralException(uno::Exception& aException, + const rtl::OUString& aMessage) +{ + aException.Message = aMessage ; + throw ; +} +// ---------------------------------------------------------------------------- + +uno::Reference< lang::XMultiServiceFactory > CreateApplicationConfigurationProvider( ) +{ + uno::Reference< lang::XMultiServiceFactory > xProvider; + + try + { + xProvider = createDefaultConfigurationProvider( ); + } + catch (configuration::InvalidBootstrapFileException & exception) + { + handleGeneralException(exception, + getMsgString( STR_CONFIG_ERR_SETTINGS_INCOMPLETE, + "The startup settings for your configuration settings are incomplete. ")); + } + catch (backend::CannotConnectException & exception) + { + handleGeneralException(exception, + getMsgString( STR_CONFIG_ERR_CANNOT_CONNECT, + "A connection to your configuration settings could not be established. ")); + } + catch (backend::BackendSetupException & exception) + { + handleGeneralException(exception, + getMsgString( STR_CONFIG_ERR_CANNOT_CONNECT, + "A connection to your configuration settings could not be established. ")); + } + catch (configuration::CannotLoadConfigurationException & exception) + { + handleGeneralException(exception, + getMsgString( STR_CONFIG_ERR_CANNOT_CONNECT, + "A connection to your configuration settings could not be established. ")); + } + catch (uno::Exception & exception) + { + handleGeneralException(exception, + getMsgString( STR_CONFIG_ERR_ACCESS_GENERAL, + "A general error occurred while accessing your configuration settings.")); + } + + + return xProvider ; +} +// ---------------------------------------------------------------------------- + + + + +// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- +// ConfigurationErrorHandler +// ---------------------------------------------------------------------------- + +namespace +{ + typedef uno::Reference< uno::XCurrentContext > CurrentContext; + class SimpleCurrentContext : public cppu::WeakImplHelper1< uno::XCurrentContext > + { + CurrentContext m_xChainedContext; + public: + explicit + SimpleCurrentContext(const CurrentContext & xChainedContext) + : m_xChainedContext(xChainedContext) + {} + + void install() { uno::setCurrentContext(this); } + void deinstall() { uno::setCurrentContext(m_xChainedContext); } + + uno::Any getChainedValueByName( OUString const & aName) const + { + return m_xChainedContext.is() + ? m_xChainedContext->getValueByName(aName) + : uno::Any(); + } + + // XCurrentContext + virtual uno::Any SAL_CALL + getValueByName( OUString const & aName) + throw (uno::RuntimeException); + }; + + uno::Any SAL_CALL + SimpleCurrentContext::getValueByName( OUString const & aName) + throw (uno::RuntimeException) + { + return getChainedValueByName(aName); + } + +} + +// ---------------------------------------------------------------------------- +class ConfigurationErrorHandler::Context : public SimpleCurrentContext +{ +public: + Context() + : SimpleCurrentContext( uno::getCurrentContext() ) + { + } + + ~Context() + { + } + + // XCurrentContext + virtual uno::Any SAL_CALL + getValueByName( OUString const & aName) + throw (uno::RuntimeException); + +private: + InteractionHandler m_xHandler; +}; + +//------------------------------------------------------------------------------ +uno::Any SAL_CALL ConfigurationErrorHandler::Context::getValueByName( OUString const & aName) + throw (uno::RuntimeException) +{ + if ( aName.equalsAscii( CONFIG_ERROR_HANDLER ) ) + { + if ( !m_xHandler.is() ) + m_xHandler = ConfigurationErrorHandler::getDefaultInteractionHandler(); + return uno::Any( m_xHandler ); + } + return SimpleCurrentContext::getValueByName( aName ); +} + +//------------------------------------------------------------------------------ +ConfigurationErrorHandler::~ConfigurationErrorHandler() +{ + deactivate(); +} + +//------------------------------------------------------------------------------ +/// installs the handler into the current context +void ConfigurationErrorHandler::activate() +{ + if (!m_pContext) + { + m_pContext = new Context; + m_pContext->acquire(); + } + m_pContext->install(); +} + +//------------------------------------------------------------------------------ +/// deinstalls the handler from the current context, restoring the previous context +void ConfigurationErrorHandler::deactivate() +{ + if (m_pContext) + { + m_pContext->deinstall(); + m_pContext->release(); + m_pContext = 0; + } +} +//------------------------------------------------------------------------------ + +ConfigurationErrorHandler::InteractionHandler ConfigurationErrorHandler::getDefaultInteractionHandler() +{ + uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory(); + + OSL_ENSURE( xServiceManager.is(),"No ServiceManager set for ConfigurationErrorHandler"); + + InteractionHandler xHandler; + + if (xServiceManager.is()) + { + xHandler.set( xServiceManager->createInstance(k_ERRORHANDLER), UNO_QUERY ); + } + + return xHandler; +} +//------------------------------------------------------------------------------ + + + diff --git a/desktop/source/app/configinit.hxx b/desktop/source/app/configinit.hxx new file mode 100644 index 000000000000..68df86656bea --- /dev/null +++ b/desktop/source/app/configinit.hxx @@ -0,0 +1,71 @@ +#ifndef _DESKTOP_CONFIGINIT_HXX_ +#define _DESKTOP_CONFIGINIT_HXX_ + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <rtl/ustring.hxx> + +/** creates a ConfigurationProvider instance +Important: exceptions thrown from that method will contain a readily +displayable message. + + @return + The default configuration provider for the application or<br/> + <NULL/>, if startup was canceled + + @throw com::sun::star::configuration::CannotLoadConfigurationException + if the configuration provider can't be created + + @throw com::sun::star::lang::ServiceNotRegisteredException + if the ConfigurationProvider service is unknwon + + @throw com::sun::star::lang::WrappedTargetException + if the configuration backend could be created, + but incurred a failure later + +*/ +extern +com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > + CreateApplicationConfigurationProvider( ); + +//----------------------------------------------------------------------------- +#include <com/sun/star/task/XInteractionHandler.hpp> + +/** + sets an InteractionHandler for configuration errors in the current context. + + */ + class ConfigurationErrorHandler + { + public: + typedef com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > InteractionHandler; + + /// Constructor: Uses the default interaction handler + ConfigurationErrorHandler() + : m_pContext(0), m_xHandler() + {} + + /// Constructor: Uses an externally provided interaction handler + ConfigurationErrorHandler(const InteractionHandler & xHandler) + : m_pContext(0), m_xHandler( xHandler ) + {} + + ~ConfigurationErrorHandler(); + + static InteractionHandler getDefaultInteractionHandler(); + + /// installs the handler into the current context + void activate(); + /// deinstalls the handler from the current context, restoring the previous context + void deactivate(); + private: + class Context; + Context * m_pContext; + InteractionHandler m_xHandler; + private: + // not implemented - suppress copy + ConfigurationErrorHandler(const ConfigurationErrorHandler&); + void operator=(const ConfigurationErrorHandler&); + }; + +//----------------------------------------------------------------------------- +#endif diff --git a/desktop/source/app/copyright_ascii_ooo.c b/desktop/source/app/copyright_ascii_ooo.c new file mode 100644 index 000000000000..7439547f62b4 --- /dev/null +++ b/desktop/source/app/copyright_ascii_ooo.c @@ -0,0 +1,10 @@ + + /* + * copyright text to see as text in the soffice binary + * + */ + +extern const char copyright_text_1[]; + +const char copyright_text_1[] = "Copyright © 2000, 2010 Oracle and/or its affiliates, All rights reserved."; + diff --git a/desktop/source/app/copyright_ascii_sun.c b/desktop/source/app/copyright_ascii_sun.c new file mode 100644 index 000000000000..c7de54e98fba --- /dev/null +++ b/desktop/source/app/copyright_ascii_sun.c @@ -0,0 +1,8 @@ + + /* + * copyright text to see as text in the soffice binary + * + */ + +const char copyright_text_1[] = "Copyright © 2000, 2010 Oracle and/or its affiliates, All rights reserved."; + diff --git a/desktop/source/app/desktop.hrc b/desktop/source/app/desktop.hrc new file mode 100644 index 000000000000..9c68d7b9fd2d --- /dev/null +++ b/desktop/source/app/desktop.hrc @@ -0,0 +1,91 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _DESKTOP_HRC_ +#define _DESKTOP_HRC_ + +#ifndef _SOLAR_HRC +#include <svl/solar.hrc> +#endif + +#define RID_DESKTOP_DIALOG_START 2000 +#define RID_FIRSTSTSTART_START 3000 +#define RID_DESKTOP_STRING_START 10000 + + +#define INFOBOX_CMDLINEHELP (RID_DESKTOP_DIALOG_START+51) +#define INFOBOX_EXPIRED (RID_DESKTOP_DIALOG_START+52) + +#define QBX_USERDATALOCKED (RID_DESKTOP_DIALOG_START+100) + +#define DLG_CMDLINEHELP (RID_DESKTOP_DIALOG_START+101) +#define TXT_DLG_CMDLINEHELP_HEADER (RID_DESKTOP_DIALOG_START+102) +#define TXT_DLG_CMDLINEHELP_LEFT (RID_DESKTOP_DIALOG_START+103) +#define TXT_DLG_CMDLINEHELP_RIGHT (RID_DESKTOP_DIALOG_START+104) +#define TXT_DLG_CMDLINEHELP_BOTTOM (RID_DESKTOP_DIALOG_START+105) +#define BTN_DLG_CMDLINEHELP_OK (RID_DESKTOP_DIALOG_START+106) + +#define QBX_CONFIG_IMPORTSETTINGS (RID_DESKTOP_DIALOG_START+180) + +#define EBX_ERR_PRINTDISABLED (RID_DESKTOP_DIALOG_START+190) + +#define STR_RECOVER_QUERY (RID_DESKTOP_STRING_START+0) +#define STR_RECOVER_TITLE (RID_DESKTOP_STRING_START+1) +#define STR_RECOVER_PREPARED (RID_DESKTOP_STRING_START+2) + +#define STR_BOOTSTRAP_ERR_CANNOT_START (RID_DESKTOP_STRING_START+100) +#define STR_BOOTSTRAP_ERR_DIR_MISSING (RID_DESKTOP_STRING_START+101) +#define STR_BOOTSTRAP_ERR_PATH_INVALID (RID_DESKTOP_STRING_START+102) +#define STR_BOOTSTRAP_ERR_NO_PATH (RID_DESKTOP_STRING_START+103) +#define STR_BOOTSTRAP_ERR_INTERNAL (RID_DESKTOP_STRING_START+104) +#define STR_BOOTSTRAP_ERR_FILE_CORRUPT (RID_DESKTOP_STRING_START+105) +#define STR_BOOTSTRAP_ERR_FILE_MISSING (RID_DESKTOP_STRING_START+106) +#define STR_BOOTSTRAP_ERR_NO_SUPPORT (RID_DESKTOP_STRING_START+107) +#define STR_BOOTSTRAP_ERR_LANGUAGE_MISSING (RID_DESKTOP_STRING_START+108) + +#define STR_BOOTSTRAP_ERR_NO_SERVICE (RID_DESKTOP_STRING_START+120) +#define STR_BOOTSTRAP_ERR_NO_CFG_SERVICE (RID_DESKTOP_STRING_START+121) +#define STR_BOOTSTRAP_ERR_CFG_DATAACCESS (RID_DESKTOP_STRING_START+122) +#define STR_BOOTSTRAP_ERR_NO_PATHSET_SERVICE (RID_DESKTOP_STRING_START+123) + +#define STR_ASK_START_SETUP_MANUALLY (RID_DESKTOP_STRING_START+152) + +#define STR_INTERNAL_ERRMSG (RID_DESKTOP_STRING_START+161) + +#define STR_CONFIG_ERR_SETTINGS_INCOMPLETE (RID_DESKTOP_STRING_START+182) +#define STR_CONFIG_ERR_CANNOT_CONNECT (RID_DESKTOP_STRING_START+183) +#define STR_CONFIG_ERR_RIGHTS_MISSING (RID_DESKTOP_STRING_START+184) +#define STR_CONFIG_ERR_ACCESS_GENERAL (RID_DESKTOP_STRING_START+187) +#define STR_CONFIG_ERR_NO_WRITE_ACCESS (RID_DESKTOP_STRING_START+188) + +#define STR_BOOSTRAP_ERR_NOTENOUGHDISKSPACE (RID_DESKTOP_STRING_START+189) +#define STR_BOOSTRAP_ERR_NOACCESSRIGHTS (RID_DESKTOP_STRING_START+190) + +#define STR_TITLE_USERDATALOCKED (RID_DESKTOP_STRING_START+206) +#define STR_TITLE_EXPIRED (RID_DESKTOP_STRING_START+207) + +#endif // _DESKTOP_HRC_ diff --git a/desktop/source/app/desktop.src b/desktop/source/app/desktop.src new file mode 100644 index 000000000000..2f6897adf80e --- /dev/null +++ b/desktop/source/app/desktop.src @@ -0,0 +1,234 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "desktop.hrc" + + +String STR_RECOVER_QUERY +{ + Text [ en-US ] = "Should the file \"$1\" be restored?" ; +}; + +String STR_RECOVER_TITLE +{ + Text [ en-US ] = "File Recovery" ; +}; + +WarningBox STR_RECOVER_PREPARED +{ + Message [ en-US ] = "An unrecoverable error has occurred.\n\nAll modified files have been saved and can\nprobably be recovered at program restart." ; +}; + +String STR_BOOTSTRAP_ERR_CANNOT_START +{ + Text [ en-US ] = "The application cannot be started. "; +}; + +String STR_BOOTSTRAP_ERR_DIR_MISSING +{ + Text [ en-US ] = "The configuration directory \"$1\" could not be found."; +}; + +String STR_BOOTSTRAP_ERR_PATH_INVALID +{ + Text [ en-US ] = "The installation path is invalid."; +}; + +String STR_BOOTSTRAP_ERR_NO_PATH +{ + Text [ en-US ] = "The installation path is not available."; +}; + +String STR_BOOTSTRAP_ERR_INTERNAL +{ + Text [ en-US ] = "An internal error occurred."; +}; + +String STR_BOOTSTRAP_ERR_FILE_CORRUPT +{ + Text [ en-US ] = "The configuration file \"$1\" is corrupt."; +}; + +String STR_BOOTSTRAP_ERR_FILE_MISSING +{ + Text [ en-US ] = "The configuration file \"$1\" was not found."; +}; + +String STR_BOOTSTRAP_ERR_NO_SUPPORT +{ + Text [ en-US ] = "The configuration file \"$1\" does not support the current version."; +}; + +String STR_BOOTSTRAP_ERR_LANGUAGE_MISSING +{ + Text [ en-US ] = "The user interface language cannot be determined."; +}; + +String STR_BOOTSTRAP_ERR_NO_SERVICE +{ + Text [ en-US ] = "The component manager is not available."; +}; + +String STR_BOOTSTRAP_ERR_NO_CFG_SERVICE +{ + Text [ en-US ] = "The configuration service is not available."; +}; + +String STR_ASK_START_SETUP_MANUALLY +{ + Text [ en-US ] = "Start the setup application to repair the installation from the CD or the folder containing the installation packages."; +}; + +String STR_CONFIG_ERR_SETTINGS_INCOMPLETE +{ + Text [ en-US ] = "The startup settings for accessing the central configuration are incomplete. "; +}; + +String STR_CONFIG_ERR_CANNOT_CONNECT +{ + Text [ en-US ] = "A connection to the central configuration could not be established. "; +}; + +String STR_CONFIG_ERR_RIGHTS_MISSING +{ + Text [ en-US ] = "You cannot access the central configuration because of missing access rights. "; +}; + +String STR_CONFIG_ERR_ACCESS_GENERAL +{ + Text [ en-US ] = "A general error occurred while accessing your central configuration. "; +}; + +String STR_CONFIG_ERR_NO_WRITE_ACCESS +{ + Text [ en-US ] = "The changes to your personal settings cannot be stored centrally because of missing access rights. "; +}; + +String STR_BOOTSTRAP_ERR_CFG_DATAACCESS +{ + Text [ en-US ] = "%PRODUCTNAME cannot be started due to an error in accessing the %PRODUCTNAME configuration data.\n\nPlease contact your system administrator." ; +}; + +String STR_INTERNAL_ERRMSG +{ + Text [ en-US ] = "The following internal error has occurred: " ; +}; + +QueryBox QBX_USERDATALOCKED +{ + Buttons = WB_YES_NO ; + DefButton = WB_DEF_NO ; + Message [ en-US ] = "Either another instance of %PRODUCTNAME is accessing your personal settings or your personal settings are locked.\nSimultaneous access can lead to inconsistencies in your personal settings. Before continuing, you should make sure user '$u' closes %PRODUCTNAME on host '$h'.\n\nDo you really want to continue?"; +}; + +String STR_TITLE_USERDATALOCKED +{ + Text [ en-US ] = "%PRODUCTNAME %PRODUCTVERSION"; +}; + +InfoBox INFOBOX_CMDLINEHELP +{ + Buttons = WB_OK ; + DefButton = WB_DEF_OK ; + Message = ""; +}; + +ModalDialog DLG_CMDLINEHELP +{ + Text = "Help Message..."; + Size = MAP_APPFONT(250, 365); + Border = True; + SVLook = True; + Moveable = True; + + FixedText TXT_DLG_CMDLINEHELP_HEADER + { + Size = MAP_APPFONT(240, 50); + Pos = MAP_APPFONT(5, 5); + Text = "HEADER"; + }; + FixedText TXT_DLG_CMDLINEHELP_LEFT + { + Size = MAP_APPFONT(50, 150); + Pos = MAP_APPFONT(5, 50); + Text = "LEFT"; + }; + FixedText TXT_DLG_CMDLINEHELP_RIGHT + { + Size = MAP_APPFONT(190, 150); + Pos = MAP_APPFONT(60, 50); + Text = "RIGHT"; + }; + FixedText TXT_DLG_CMDLINEHELP_BOTTOM + { + Size = MAP_APPFONT(240, 145); + Pos = MAP_APPFONT(5, 200); + Text = "BOTTOM"; + }; + OKButton BTN_DLG_CMDLINEHELP_OK + { + Size = MAP_APPFONT ( 50 , 14 ) ; + Pos = MAP_APPFONT(95, 345); + TabStop = TRUE ; + DefButton = TRUE ; + }; +}; + +ErrorBox EBX_ERR_PRINTDISABLED +{ + Buttons = WB_OK ; + DefButton = WB_DEF_OK ; + Message [ en-US ] = "Printing is disabled. No documents can be printed."; +}; + +InfoBox INFOBOX_EXPIRED +{ + Buttons = WB_OK ; + DefButton = WB_DEF_OK ; + Message [ en-US ] = "This Evaluation Version has expired. To find out more about %PRODUCTNAME,\nvisit http://www.oracle.com/us/products/applications/open-office."; +}; + +String STR_TITLE_EXPIRED +{ + Text [ en-US ] = "%PRODUCTNAME %PRODUCTVERSION"; +}; + +String STR_BOOTSTRAP_ERR_NO_PATHSET_SERVICE +{ + Text [ en-US ] = "The path manager is not available.\n"; +}; + +String STR_BOOSTRAP_ERR_NOTENOUGHDISKSPACE +{ + Text [ en-US ] = "%PRODUCTNAME user installation could not be completed due to insufficient free disk space. Please free more disc space at the following location and restart %PRODUCTNAME:\n\n"; +}; + +String STR_BOOSTRAP_ERR_NOACCESSRIGHTS +{ + Text [ en-US ] = "%PRODUCTNAME user installation could not be processed due to missing access rights. Please make sure that you have sufficient access rights for the following location and restart %PRODUCTNAME:\n\n"; +}; + diff --git a/desktop/source/app/desktopcontext.cxx b/desktop/source/app/desktopcontext.cxx new file mode 100644 index 000000000000..e516b5eadd46 --- /dev/null +++ b/desktop/source/app/desktopcontext.cxx @@ -0,0 +1,63 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" +#include "desktopcontext.hxx" + +#include <vcl/svapp.hxx> +#include <svtools/javainteractionhandler.hxx> + +using namespace rtl; +using namespace com::sun::star::uno; +using namespace com::sun::star::task; + +namespace desktop +{ + +DesktopContext::DesktopContext( const Reference< XCurrentContext > & ctx ) + : m_xNextContext( ctx ) +{ +} + +Any SAL_CALL DesktopContext::getValueByName( const OUString& Name) throw (RuntimeException) +{ + Any retVal; + + if ( 0 == Name.compareToAscii( JAVA_INTERACTION_HANDLER_NAME )) + { + retVal = makeAny( Reference< XInteractionHandler >( new svt::JavaInteractionHandler()) ); + } + else if( m_xNextContext.is() ) + { + // Call next context in chain if found + retVal = m_xNextContext->getValueByName( Name ); + } + return retVal; +} + +} diff --git a/desktop/source/app/desktopcontext.hxx b/desktop/source/app/desktopcontext.hxx new file mode 100644 index 000000000000..88948e753af5 --- /dev/null +++ b/desktop/source/app/desktopcontext.hxx @@ -0,0 +1,50 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _DESKTOP_DESKTOPCONTEXT_HXX_ +#define _DESKTOP_DESKTOPCONTEXT_HXX_ + +#include <cppuhelper/implbase1.hxx> +#include <uno/current_context.hxx> + +namespace desktop +{ + class DesktopContext: public cppu::WeakImplHelper1< com::sun::star::uno::XCurrentContext > + { + public: + DesktopContext( const com::sun::star::uno::Reference< com::sun::star::uno::XCurrentContext > & ctx); + + // XCurrentContext + virtual com::sun::star::uno::Any SAL_CALL getValueByName( const rtl::OUString& Name ) + throw (com::sun::star::uno::RuntimeException); + + private: + com::sun::star::uno::Reference< com::sun::star::uno::XCurrentContext > m_xNextContext; + }; +} + +#endif // _DESKTOP_DESKTOPCONTEXT_HXX_ diff --git a/desktop/source/app/desktopresid.cxx b/desktop/source/app/desktopresid.cxx new file mode 100644 index 000000000000..90cc8e220fba --- /dev/null +++ b/desktop/source/app/desktopresid.cxx @@ -0,0 +1,44 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + + +#include "desktopresid.hxx" +#include "app.hxx" + +// ----------------------------------------------------------------------- +namespace desktop +{ + +DesktopResId::DesktopResId( USHORT nId ) : + ResId( nId, *Desktop::GetDesktopResManager() ) +{ +} + +} diff --git a/desktop/source/app/desktopresid.hxx b/desktop/source/app/desktopresid.hxx new file mode 100644 index 000000000000..410ca429f5ad --- /dev/null +++ b/desktop/source/app/desktopresid.hxx @@ -0,0 +1,44 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _DESKTOP_RESID_HXX_ +#define _DESKTOP_RESID_HXX_ + +#include <tools/resid.hxx> + +namespace desktop +{ + +class DesktopResId : public ResId +{ + public: + DesktopResId( USHORT nId ); +}; + +} + +#endif // _DESKTOP_RESID_HXX_ diff --git a/desktop/source/app/dispatchwatcher.cxx b/desktop/source/app/dispatchwatcher.cxx new file mode 100644 index 000000000000..db7f3c45964f --- /dev/null +++ b/desktop/source/app/dispatchwatcher.cxx @@ -0,0 +1,514 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include "dispatchwatcher.hxx" +#include <rtl/ustring.hxx> +#include <tools/string.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/synchronousdispatch.hxx> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/util/CloseVetoException.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/util/URL.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/frame/XFramesSupplier.hpp> +#include <com/sun/star/frame/XDispatch.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/view/XPrintable.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/document/MacroExecMode.hpp> +#include <com/sun/star/document/UpdateDocMode.hpp> + +#include <tools/urlobj.hxx> +#include <comphelper/mediadescriptor.hxx> + +#include <vector> + +using namespace ::rtl; +using namespace ::osl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::view; + +namespace desktop +{ + +String GetURL_Impl( + const String& rName, boost::optional< rtl::OUString > const & cwdUrl ); + +struct DispatchHolder +{ + DispatchHolder( const URL& rURL, Reference< XDispatch >& rDispatch ) : + aURL( rURL ), xDispatch( rDispatch ) {} + + URL aURL; + rtl::OUString cwdUrl; + Reference< XDispatch > xDispatch; +}; + +Mutex* DispatchWatcher::pWatcherMutex = NULL; + +Mutex& DispatchWatcher::GetMutex() +{ + if ( !pWatcherMutex ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !pWatcherMutex ) + pWatcherMutex = new osl::Mutex(); + } + + return *pWatcherMutex; +} + +// Create or get the dispatch watcher implementation. This implementation must be +// a singleton to prevent access to the framework after it wants to terminate. +DispatchWatcher* DispatchWatcher::GetDispatchWatcher() +{ + static Reference< XInterface > xDispatchWatcher; + static DispatchWatcher* pDispatchWatcher = NULL; + + if ( !xDispatchWatcher.is() ) + { + ::osl::MutexGuard aGuard( GetMutex() ); + + if ( !xDispatchWatcher.is() ) + { + pDispatchWatcher = new DispatchWatcher(); + + // We have to hold a reference to ourself forever to prevent our own destruction. + xDispatchWatcher = static_cast< cppu::OWeakObject *>( pDispatchWatcher ); + } + } + + return pDispatchWatcher; +} + + +DispatchWatcher::DispatchWatcher() + : m_nRequestCount(0) +{ +} + + +DispatchWatcher::~DispatchWatcher() +{ +} + + +sal_Bool DispatchWatcher::executeDispatchRequests( const DispatchList& aDispatchRequestsList, bool bNoTerminate ) +{ + Reference< XComponentLoader > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + UNO_QUERY ); + + DispatchList::const_iterator p; + std::vector< DispatchHolder > aDispatches; + ::rtl::OUString aAsTemplateArg( RTL_CONSTASCII_USTRINGPARAM( "AsTemplate")); + + for ( p = aDispatchRequestsList.begin(); p != aDispatchRequestsList.end(); p++ ) + { + String aPrinterName; + const DispatchRequest& aDispatchRequest = *p; + + // create parameter array + sal_Int32 nCount = 4; + if ( aDispatchRequest.aPreselectedFactory.getLength() ) + nCount++; + + // we need more properties for a print/print to request + if ( aDispatchRequest.aRequestType == REQUEST_PRINT || + aDispatchRequest.aRequestType == REQUEST_PRINTTO ) + nCount++; + + Sequence < PropertyValue > aArgs( nCount ); + + // mark request as user interaction from outside + aArgs[0].Name = ::rtl::OUString::createFromAscii("Referer"); + aArgs[0].Value <<= ::rtl::OUString::createFromAscii("private:OpenEvent"); + + if ( aDispatchRequest.aRequestType == REQUEST_PRINT || + aDispatchRequest.aRequestType == REQUEST_PRINTTO ) + { + aArgs[1].Name = ::rtl::OUString::createFromAscii("ReadOnly"); + aArgs[2].Name = ::rtl::OUString::createFromAscii("OpenNewView"); + aArgs[3].Name = ::rtl::OUString::createFromAscii("Hidden"); + aArgs[4].Name = ::rtl::OUString::createFromAscii("Silent"); + } + else + { + Reference < com::sun::star::task::XInteractionHandler > xInteraction( + ::comphelper::getProcessServiceFactory()->createInstance( OUString::createFromAscii("com.sun.star.task.InteractionHandler") ), + com::sun::star::uno::UNO_QUERY ); + + aArgs[1].Name = OUString::createFromAscii( "InteractionHandler" ); + aArgs[1].Value <<= xInteraction; + + sal_Int16 nMacroExecMode = ::com::sun::star::document::MacroExecMode::USE_CONFIG; + aArgs[2].Name = OUString::createFromAscii( "MacroExecutionMode" ); + aArgs[2].Value <<= nMacroExecMode; + + sal_Int16 nUpdateDoc = ::com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG; + aArgs[3].Name = OUString::createFromAscii( "UpdateDocMode" ); + aArgs[3].Value <<= nUpdateDoc; + } + + if ( aDispatchRequest.aPreselectedFactory.getLength() ) + { + aArgs[nCount-1].Name = ::comphelper::MediaDescriptor::PROP_DOCUMENTSERVICE(); + aArgs[nCount-1].Value <<= aDispatchRequest.aPreselectedFactory; + } + + String aName( GetURL_Impl( aDispatchRequest.aURL, aDispatchRequest.aCwdUrl ) ); + ::rtl::OUString aTarget( RTL_CONSTASCII_USTRINGPARAM("_default") ); + + if ( aDispatchRequest.aRequestType == REQUEST_PRINT || + aDispatchRequest.aRequestType == REQUEST_PRINTTO ) + { + // documents opened for printing are opened readonly because they must be opened as a new document and this + // document could be open already + aArgs[1].Value <<= sal_True; + + // always open a new document for printing, because it must be disposed afterwards + aArgs[2].Value <<= sal_True; + + // printing is done in a hidden view + aArgs[3].Value <<= sal_True; + + // load document for printing without user interaction + aArgs[4].Value <<= sal_True; + + // hidden documents should never be put into open tasks + aTarget = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_blank") ); + } + + // load the document ... if they are loadable! + // Otherwise try to dispatch it ... + Reference < XPrintable > xDoc; + if( + ( aName.CompareToAscii( ".uno" , 4 ) == COMPARE_EQUAL ) || + ( aName.CompareToAscii( "slot:" , 5 ) == COMPARE_EQUAL ) || + ( aName.CompareToAscii( "macro:", 6 ) == COMPARE_EQUAL ) || + ( aName.CompareToAscii("vnd.sun.star.script", 19) == COMPARE_EQUAL) + ) + { + // Attention: URL must be parsed full. Otherwise some detections on it will fail! + // It doesnt matter, if parser isn't available. Because; We try loading of URL then ... + URL aURL ; + aURL.Complete = aName; + + Reference < XDispatch > xDispatcher ; + Reference < XDispatchProvider > xProvider ( xDesktop, UNO_QUERY ); + Reference < XURLTransformer > xParser ( ::comphelper::getProcessServiceFactory()->createInstance( OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer")) ), ::com::sun::star::uno::UNO_QUERY ); + + if( xParser.is() == sal_True ) + xParser->parseStrict( aURL ); + + if( xProvider.is() == sal_True ) + xDispatcher = xProvider->queryDispatch( aURL, ::rtl::OUString(), 0 ); + + if( xDispatcher.is() == sal_True ) + { + { + ::osl::ClearableMutexGuard aGuard( GetMutex() ); + // Remember request so we can find it in statusChanged! + m_aRequestContainer.insert( DispatchWatcherHashMap::value_type( aURL.Complete, (sal_Int32)1 ) ); + m_nRequestCount++; + } + + // Use local vector to store dispatcher because we have to fill our request container before + // we can dispatch. Otherwise it would be possible that statusChanged is called before we dispatched all requests!! + aDispatches.push_back( DispatchHolder( aURL, xDispatcher )); + } + } + else if ( ( aName.CompareToAscii( "service:" , 8 ) == COMPARE_EQUAL ) ) + { + // TODO: the dispatch has to be done for loadComponentFromURL as well. Please ask AS for more details. + URL aURL ; + aURL.Complete = aName; + + Reference < XDispatch > xDispatcher ; + Reference < XDispatchProvider > xProvider ( xDesktop, UNO_QUERY ); + Reference < XURLTransformer > xParser ( ::comphelper::getProcessServiceFactory()->createInstance( OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer")) ), ::com::sun::star::uno::UNO_QUERY ); + + if( xParser.is() == sal_True ) + xParser->parseStrict( aURL ); + + if( xProvider.is() == sal_True ) + xDispatcher = xProvider->queryDispatch( aURL, ::rtl::OUString(), 0 ); + + if( xDispatcher.is() == sal_True ) + { + try + { + // We have to be listener to catch errors during dispatching URLs. + // Otherwise it would be possible to have an office running without an open + // window!! + Sequence < PropertyValue > aArgs2(1); + aArgs2[0].Name = ::rtl::OUString::createFromAscii("SynchronMode"); + aArgs2[0].Value <<= sal_True; + Reference < XNotifyingDispatch > xDisp( xDispatcher, UNO_QUERY ); + if ( xDisp.is() ) + xDisp->dispatchWithNotification( aURL, aArgs2, DispatchWatcher::GetDispatchWatcher() ); + else + xDispatcher->dispatch( aURL, aArgs2 ); + } + catch ( ::com::sun::star::uno::Exception& ) + { + OUString aMsg = OUString::createFromAscii( + "Desktop::OpenDefault() IllegalArgumentException while calling XNotifyingDispatch: "); + OSL_ENSURE( sal_False, OUStringToOString(aMsg, RTL_TEXTENCODING_ASCII_US).getStr()); + } + } + } + else + { + INetURLObject aObj( aName ); + if ( aObj.GetProtocol() == INET_PROT_PRIVATE ) + aTarget = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_default") ); + + // Set "AsTemplate" argument according to request type + if ( aDispatchRequest.aRequestType == REQUEST_FORCENEW || + aDispatchRequest.aRequestType == REQUEST_FORCEOPEN ) + { + sal_Int32 nIndex = aArgs.getLength(); + aArgs.realloc( nIndex+1 ); + aArgs[nIndex].Name = aAsTemplateArg; + if ( aDispatchRequest.aRequestType == REQUEST_FORCENEW ) + aArgs[nIndex].Value <<= sal_True; + else + aArgs[nIndex].Value <<= sal_False; + } + + // if we are called in viewmode, open document read-only + // #95425# + if(aDispatchRequest.aRequestType == REQUEST_VIEW) { + sal_Int32 nIndex = aArgs.getLength(); + aArgs.realloc(nIndex+1); + aArgs[nIndex].Name = OUString::createFromAscii("ReadOnly"); + aArgs[nIndex].Value <<= sal_True; + } + + // if we are called with -start set Start in mediadescriptor + if(aDispatchRequest.aRequestType == REQUEST_START) { + sal_Int32 nIndex = aArgs.getLength(); + aArgs.realloc(nIndex+1); + aArgs[nIndex].Name = OUString::createFromAscii("StartPresentation"); + aArgs[nIndex].Value <<= sal_True; + } + + // This is a synchron loading of a component so we don't have to deal with our statusChanged listener mechanism. + + try + { + xDoc = Reference < XPrintable >( ::comphelper::SynchronousDispatch::dispatch( xDesktop, aName, aTarget, 0, aArgs ), UNO_QUERY ); + //xDoc = Reference < XPrintable >( xDesktop->loadComponentFromURL( aName, aTarget, 0, aArgs ), UNO_QUERY ); + } + catch ( ::com::sun::star::lang::IllegalArgumentException& iae) + { + OUString aMsg = OUString::createFromAscii( + "Dispatchwatcher IllegalArgumentException while calling loadComponentFromURL: ") + + iae.Message; + OSL_ENSURE( sal_False, OUStringToOString(aMsg, RTL_TEXTENCODING_ASCII_US).getStr()); + } + catch (com::sun::star::io::IOException& ioe) + { + OUString aMsg = OUString::createFromAscii( + "Dispatchwatcher IOException while calling loadComponentFromURL: ") + + ioe.Message; + OSL_ENSURE( sal_False, OUStringToOString(aMsg, RTL_TEXTENCODING_ASCII_US).getStr()); + } + if ( aDispatchRequest.aRequestType == REQUEST_OPEN || + aDispatchRequest.aRequestType == REQUEST_VIEW || + aDispatchRequest.aRequestType == REQUEST_START || + aDispatchRequest.aRequestType == REQUEST_FORCEOPEN || + aDispatchRequest.aRequestType == REQUEST_FORCENEW ) + { + // request is completed + OfficeIPCThread::RequestsCompleted( 1 ); + } + else if ( aDispatchRequest.aRequestType == REQUEST_PRINT || + aDispatchRequest.aRequestType == REQUEST_PRINTTO ) + { + if ( xDoc.is() ) + { + if ( aDispatchRequest.aRequestType == REQUEST_PRINTTO ) + { + // create the printer + Sequence < PropertyValue > aPrinterArgs( 1 ); + aPrinterArgs[0].Name = ::rtl::OUString::createFromAscii("Name"); + aPrinterArgs[0].Value <<= ::rtl::OUString( aDispatchRequest.aPrinterName ); + xDoc->setPrinter( aPrinterArgs ); + } + + // print ( also without user interaction ) + Sequence < PropertyValue > aPrinterArgs( 1 ); + aPrinterArgs[0].Name = ::rtl::OUString::createFromAscii("Wait"); + aPrinterArgs[0].Value <<= ( sal_Bool ) sal_True; + xDoc->print( aPrinterArgs ); + } + else + { + // place error message here ... + } + + // remove the document + try + { + Reference < XCloseable > xClose( xDoc, UNO_QUERY ); + if ( xClose.is() ) + xClose->close( sal_True ); + else + { + Reference < XComponent > xComp( xDoc, UNO_QUERY ); + if ( xComp.is() ) + xComp->dispose(); + } + } + catch ( com::sun::star::util::CloseVetoException& ) + { + } + + // request is completed + OfficeIPCThread::RequestsCompleted( 1 ); + } + } + } + + if ( aDispatches.size() > 0 ) + { + // Execute all asynchronous dispatches now after we placed them into our request container! + Sequence < PropertyValue > aArgs( 2 ); + aArgs[0].Name = ::rtl::OUString::createFromAscii("Referer"); + aArgs[0].Value <<= ::rtl::OUString::createFromAscii("private:OpenEvent"); + aArgs[1].Name = ::rtl::OUString::createFromAscii("SynchronMode"); + aArgs[1].Value <<= sal_True; + + for ( sal_uInt32 n = 0; n < aDispatches.size(); n++ ) + { + Reference< XDispatch > xDispatch = aDispatches[n].xDispatch; + Reference < XNotifyingDispatch > xDisp( xDispatch, UNO_QUERY ); + if ( xDisp.is() ) + xDisp->dispatchWithNotification( aDispatches[n].aURL, aArgs, this ); + else + { + ::osl::ClearableMutexGuard aGuard( GetMutex() ); + m_nRequestCount--; + aGuard.clear(); + xDispatch->dispatch( aDispatches[n].aURL, aArgs ); + } + } + } + + ::osl::ClearableMutexGuard aGuard( GetMutex() ); + bool bEmpty = (m_nRequestCount == 0); + aGuard.clear(); + + // No more asynchronous requests? + // The requests are removed from the request container after they called back to this + // implementation via statusChanged!! + if ( bEmpty && !bNoTerminate /*m_aRequestContainer.empty()*/ ) + { + // We have to check if we have an open task otherwise we have to shutdown the office. + Reference< XFramesSupplier > xTasksSupplier( xDesktop, UNO_QUERY ); + aGuard.clear(); + + Reference< XElementAccess > xList( xTasksSupplier->getFrames(), UNO_QUERY ); + + if ( !xList->hasElements() ) + { + // We don't have any task open so we have to shutdown ourself!! + Reference< XDesktop > xDesktop2( xTasksSupplier, UNO_QUERY ); + if ( xDesktop2.is() ) + return xDesktop2->terminate(); + } + } + + return sal_False; +} + + +void SAL_CALL DispatchWatcher::disposing( const ::com::sun::star::lang::EventObject& ) +throw(::com::sun::star::uno::RuntimeException) +{ +} + + +void SAL_CALL DispatchWatcher::dispatchFinished( const DispatchResultEvent& ) throw( RuntimeException ) +{ + osl::ClearableMutexGuard aGuard( GetMutex() ); + sal_Int16 nCount = --m_nRequestCount; + aGuard.clear(); + OfficeIPCThread::RequestsCompleted( 1 ); +/* + // Find request in our hash map and remove it as a pending request + DispatchWatcherHashMap::iterator pDispatchEntry = m_aRequestContainer.find( rEvent.FeatureURL.Complete ) ; + if ( pDispatchEntry != m_aRequestContainer.end() ) + { + m_aRequestContainer.erase( pDispatchEntry ); + aGuard.clear(); + OfficeIPCThread::RequestsCompleted( 1 ); + } + else + aGuard.clear(); +*/ + if ( !nCount && !OfficeIPCThread::AreRequestsPending() ) + { + // We have to check if we have an open task otherwise we have to shutdown the office. + Reference< XFramesSupplier > xTasksSupplier( ::comphelper::getProcessServiceFactory()->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), + UNO_QUERY ); + Reference< XElementAccess > xList( xTasksSupplier->getFrames(), UNO_QUERY ); + + if ( !xList->hasElements() ) + { + // We don't have any task open so we have to shutdown ourself!! + Reference< XDesktop > xDesktop( xTasksSupplier, UNO_QUERY ); + if ( xDesktop.is() ) + xDesktop->terminate(); + } + } +} + +} + + + + + + + + diff --git a/desktop/source/app/dispatchwatcher.hxx b/desktop/source/app/dispatchwatcher.hxx new file mode 100644 index 000000000000..2b3f1ab54680 --- /dev/null +++ b/desktop/source/app/dispatchwatcher.hxx @@ -0,0 +1,124 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _DESKTOP_DISPATCHWATCHER_HXX +#define _DESKTOP_DISPATCHWATCHER_HXX + +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/frame/XNotifyingDispatch.hpp> +#include <com/sun/star/frame/XDispatchResultListener.hpp> + +#include "officeipcthread.hxx" +#include <hash_map> +#include <vector> + +namespace desktop +{ + +/* + Class for controlls dispatching of command URL through office command line. There + are "dangerous" command URLs, that can result in a running office without UI. To prevent + this situation the implementation surveile all dispatches and looks for an open task if + there is arose a problem. If there is none the office will be shutdown to prevent a + running office without UI. +*/ + +struct OUStringHashCode +{ + size_t operator()( const ::rtl::OUString& sString ) const + { + return sString.hashCode(); + } +}; + +class DispatchWatcherHashMap : public ::std::hash_map< ::rtl::OUString, sal_Int32, OUStringHashCode, ::std::equal_to< ::rtl::OUString > > +{ + public: + inline void free() + { + DispatchWatcherHashMap().swap( *this ); + } +}; + +class DispatchWatcher : public ::cppu::WeakImplHelper1< ::com::sun::star::frame::XDispatchResultListener > +{ + public: + enum RequestType + { + REQUEST_OPEN, + REQUEST_VIEW, + REQUEST_START, + REQUEST_PRINT, + REQUEST_PRINTTO, + REQUEST_FORCEOPEN, + REQUEST_FORCENEW + }; + + struct DispatchRequest + { + DispatchRequest( RequestType aType, const ::rtl::OUString& aFile, boost::optional< rtl::OUString > const & cwdUrl, const ::rtl::OUString& aPrinter, const ::rtl::OUString& aFact ) : + aRequestType( aType ), aURL( aFile ), aCwdUrl( cwdUrl ), aPrinterName( aPrinter ), aPreselectedFactory( aFact ) {} + + RequestType aRequestType; + rtl::OUString aURL; + boost::optional< rtl::OUString > aCwdUrl; + rtl::OUString aPrinterName; + rtl::OUString aPreselectedFactory; + }; + + typedef std::vector< DispatchRequest > DispatchList; + + virtual ~DispatchWatcher(); + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) + throw(::com::sun::star::uno::RuntimeException); + + // XDispachResultListener + virtual void SAL_CALL dispatchFinished( const com::sun::star::frame::DispatchResultEvent& aEvent ) throw( com::sun::star::uno::RuntimeException ); + + // Access function to get a dispatcher watcher reference. There must be a global reference holder + static DispatchWatcher* GetDispatchWatcher(); + + // execute new dispatch request + sal_Bool executeDispatchRequests( const DispatchList& aDispatches, bool bNoTerminate = false ); + + private: + DispatchWatcher(); + + static ::osl::Mutex& GetMutex(); + + DispatchWatcherHashMap m_aRequestContainer; + + static ::osl::Mutex* pWatcherMutex; + + sal_Int16 m_nRequestCount; +}; + +} + +#endif // _DESKTOP_DISPATCHWATCHER_HXX diff --git a/desktop/source/app/exports.dxp b/desktop/source/app/exports.dxp new file mode 100644 index 000000000000..9630d7e06768 --- /dev/null +++ b/desktop/source/app/exports.dxp @@ -0,0 +1,3 @@ +component_getImplementationEnvironment +component_writeInfo +component_getFactory diff --git a/desktop/source/app/langselect.cxx b/desktop/source/app/langselect.cxx new file mode 100644 index 000000000000..9df8d82a37ff --- /dev/null +++ b/desktop/source/app/langselect.cxx @@ -0,0 +1,558 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include "app.hxx" +#include "langselect.hxx" +#include "cmdlineargs.hxx" +#include <stdio.h> + +#include <rtl/string.hxx> +#include <rtl/bootstrap.hxx> +#include <unotools/pathoptions.hxx> +#include <tools/resid.hxx> +#include <tools/config.hxx> +#include <i18npool/mslangid.hxx> +#include <comphelper/processfactory.hxx> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/lang/XLocalizable.hpp> +#include <com/sun/star/lang/Locale.hpp> +#include "com/sun/star/util/XFlushable.hpp" +#include <rtl/locale.hxx> +#include <rtl/instance.hxx> +#include <osl/process.h> +#include <osl/file.hxx> + +using namespace rtl; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; +using namespace com::sun::star::beans; +using namespace com::sun::star::util; + +namespace desktop { + +static char const SOFFICE_BOOTSTRAP[] = "Bootstrap"; +static char const SOFFICE_STARTLANG[] = "STARTLANG"; + +sal_Bool LanguageSelection::bFoundLanguage = sal_False; +OUString LanguageSelection::aFoundLanguage; +LanguageSelection::LanguageSelectionStatus LanguageSelection::m_eStatus = LS_STATUS_OK; + +const OUString LanguageSelection::usFallbackLanguage = OUString::createFromAscii("en-US"); + +static sal_Bool existsURL( OUString const& sURL ) +{ + using namespace osl; + DirectoryItem aDirItem; + + if (sURL.getLength() != 0) + return ( DirectoryItem::get( sURL, aDirItem ) == DirectoryItem::E_None ); + + return sal_False; +} + +// locate soffice.ini/.rc file +static OUString locateSofficeIniFile() +{ + OUString aUserDataPath; + OUString aSofficeIniFileURL; + + // Retrieve the default file URL for the soffice.ini/rc + rtl::Bootstrap().getIniName( aSofficeIniFileURL ); + + if ( utl::Bootstrap::locateUserData( aUserDataPath ) == utl::Bootstrap::PATH_EXISTS ) + { + const char CONFIG_DIR[] = "/config"; + + sal_Int32 nIndex = aSofficeIniFileURL.lastIndexOf( '/'); + if ( nIndex > 0 ) + { + OUString aUserSofficeIniFileURL; + OUStringBuffer aBuffer( aUserDataPath ); + aBuffer.appendAscii( CONFIG_DIR ); + aBuffer.append( aSofficeIniFileURL.copy( nIndex )); + aUserSofficeIniFileURL = aBuffer.makeStringAndClear(); + + if ( existsURL( aUserSofficeIniFileURL )) + return aUserSofficeIniFileURL; + } + } + // Fallback try to use the soffice.ini/rc from program folder + return aSofficeIniFileURL; +} + +Locale LanguageSelection::IsoStringToLocale(const OUString& str) +{ + Locale l; + sal_Int32 index=0; + l.Language = str.getToken(0, '-', index); + if (index >= 0) l.Country = str.getToken(0, '-', index); + if (index >= 0) l.Variant = str.getToken(0, '-', index); + return l; +} + +bool LanguageSelection::prepareLanguage() +{ + m_eStatus = LS_STATUS_OK; + OUString sConfigSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider"); + Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory(); + Reference< XLocalizable > theConfigProvider; + try + { + theConfigProvider = Reference< XLocalizable >(theMSF->createInstance( sConfigSrvc ),UNO_QUERY_THROW ); + } + catch(const Exception&) + { + m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN; + } + + if(!theConfigProvider.is()) + return false; + + sal_Bool bSuccess = sal_False; + + // #i42730#get the windows 16Bit locale - it should be preferred over the UI language + try + { + Reference< XPropertySet > xProp(getConfigAccess("org.openoffice.System/L10N/", sal_False), UNO_QUERY_THROW); + Any aWin16SysLocale = xProp->getPropertyValue(OUString::createFromAscii("SystemLocale")); + ::rtl::OUString sWin16SysLocale; + aWin16SysLocale >>= sWin16SysLocale; + if( sWin16SysLocale.getLength()) + setDefaultLanguage(sWin16SysLocale); + } + catch(const Exception&) + { + m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN; + } + + // #i32939# use system locale to set document default locale + try + { + OUString usLocale; + Reference< XPropertySet > xLocaleProp(getConfigAccess( + "org.openoffice.System/L10N", sal_True), UNO_QUERY_THROW); + xLocaleProp->getPropertyValue(OUString::createFromAscii("Locale")) >>= usLocale; + setDefaultLanguage(usLocale); + } + catch (Exception&) + { + m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN; + } + + // get the selected UI language as string + bool bCmdLanguage( false ); + bool bIniLanguage( false ); + OUString aEmpty; + OUString aLocaleString = getUserUILanguage(); + + if ( aLocaleString.getLength() == 0 ) + { + CommandLineArgs* pCmdLineArgs = Desktop::GetCommandLineArgs(); + if ( pCmdLineArgs ) + { + pCmdLineArgs->GetLanguage(aLocaleString); + if (isInstalledLanguage(aLocaleString, sal_False)) + { + bCmdLanguage = true; + bFoundLanguage = true; + aFoundLanguage = aLocaleString; + } + else + aLocaleString = aEmpty; + } + + if ( !bCmdLanguage ) + { + OUString aSOfficeIniURL = locateSofficeIniFile(); + Config aConfig(aSOfficeIniURL); + aConfig.SetGroup( SOFFICE_BOOTSTRAP ); + OString sLang = aConfig.ReadKey( SOFFICE_STARTLANG ); + aLocaleString = OUString( sLang.getStr(), sLang.getLength(), RTL_TEXTENCODING_ASCII_US ); + if (isInstalledLanguage(aLocaleString, sal_False)) + { + bIniLanguage = true; + bFoundLanguage = true; + aFoundLanguage = aLocaleString; + } + else + aLocaleString = aEmpty; + } + } + + // user further fallbacks for the UI language + if ( aLocaleString.getLength() == 0 ) + aLocaleString = getLanguageString(); + + if ( aLocaleString.getLength() > 0 ) + { + try + { + // prepare default config provider by localizing it to the selected locale + // this will ensure localized configuration settings to be selected accoring to the + // UI language. + Locale loc = LanguageSelection::IsoStringToLocale(aLocaleString); + // flush any data already written to the configuration (which + // currently uses independent caches for different locales and thus + // would ignore data written to another cache): + Reference< XFlushable >(theConfigProvider, UNO_QUERY_THROW)-> + flush(); + theConfigProvider->setLocale(loc); + + Reference< XPropertySet > xProp(getConfigAccess("org.openoffice.Setup/L10N/", sal_True), UNO_QUERY_THROW); + if ( !bCmdLanguage ) + { + // Store language only + xProp->setPropertyValue(OUString::createFromAscii("ooLocale"), makeAny(aLocaleString)); + Reference< XChangesBatch >(xProp, UNO_QUERY_THROW)->commitChanges(); + } + + if ( bIniLanguage ) + { + // Store language only + Reference< XPropertySet > xProp2(getConfigAccess("org.openoffice.Office.Linguistic/General/", sal_True), UNO_QUERY_THROW); + xProp2->setPropertyValue(OUString::createFromAscii("UILocale"), makeAny(aLocaleString)); + Reference< XChangesBatch >(xProp2, UNO_QUERY_THROW)->commitChanges(); + } + + MsLangId::setConfiguredSystemUILanguage( MsLangId::convertLocaleToLanguage(loc) ); + + OUString sLocale; + xProp->getPropertyValue(OUString::createFromAscii("ooSetupSystemLocale")) >>= sLocale; + if ( sLocale.getLength() ) + { + loc = LanguageSelection::IsoStringToLocale(sLocale); + MsLangId::setConfiguredSystemLanguage( MsLangId::convertLocaleToLanguage(loc) ); + } + else + MsLangId::setConfiguredSystemLanguage( MsLangId::getSystemLanguage() ); + + bSuccess = sal_True; + } + catch ( PropertyVetoException& ) + { + // we are not allowed to change this + } + catch (Exception& e) + { + OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US); + OSL_ENSURE(sal_False, aMsg.getStr()); + + } + } + + // #i32939# setting of default document locale + // #i32939# this should not be based on the UI language + setDefaultLanguage(aLocaleString); + + return bSuccess; +} + +void LanguageSelection::setDefaultLanguage(const OUString& sLocale) +{ + // #i32939# setting of default document language + // + // See #i42730# for rules for determining source of settings + + // determine script type of locale + LanguageType nLang = MsLangId::convertIsoStringToLanguage(sLocale); + sal_uInt16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage(nLang); + + switch (nScriptType) + { + case SCRIPTTYPE_ASIAN: + MsLangId::setConfiguredAsianFallback( nLang ); + break; + case SCRIPTTYPE_COMPLEX: + MsLangId::setConfiguredComplexFallback( nLang ); + break; + default: + MsLangId::setConfiguredWesternFallback( nLang ); + break; + } +} + +OUString LanguageSelection::getUserUILanguage() +{ + // check whether the user has selected a specific language + OUString aUserLanguage = getUserLanguage(); + if (aUserLanguage.getLength() > 0 ) + { + if (isInstalledLanguage(aUserLanguage)) + { + // all is well + bFoundLanguage = sal_True; + aFoundLanguage = aUserLanguage; + return aFoundLanguage; + } + else + { + // selected language is not/no longer installed + resetUserLanguage(); + } + } + + return aUserLanguage; +} + +OUString LanguageSelection::getLanguageString() +{ + // did we already find a language? + if (bFoundLanguage) + return aFoundLanguage; + + // check whether the user has selected a specific language + OUString aUserLanguage = getUserUILanguage(); + if (aUserLanguage.getLength() > 0 ) + return aUserLanguage ; + + // try to use system default + aUserLanguage = getSystemLanguage(); + if (aUserLanguage.getLength() > 0 ) + { + if (isInstalledLanguage(aUserLanguage, sal_False)) + { + // great, system default language is available + bFoundLanguage = sal_True; + aFoundLanguage = aUserLanguage; + return aFoundLanguage; + } + } + // fallback 1: en-US + OUString usFB = usFallbackLanguage; + if (isInstalledLanguage(usFB)) + { + bFoundLanguage = sal_True; + aFoundLanguage = usFallbackLanguage; + return aFoundLanguage; + } + + // fallback didn't work use first installed language + aUserLanguage = getFirstInstalledLanguage(); + + bFoundLanguage = sal_True; + aFoundLanguage = aUserLanguage; + return aFoundLanguage; +} + +Reference< XNameAccess > LanguageSelection::getConfigAccess(const sal_Char* pPath, sal_Bool bUpdate) +{ + Reference< XNameAccess > xNameAccess; + try{ + OUString sConfigSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider"); + OUString sAccessSrvc; + if (bUpdate) + sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess"); + else + sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationAccess"); + + OUString sConfigURL = OUString::createFromAscii(pPath); + + // get configuration provider + Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory(); + if (theMSF.is()) { + Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory > ( + theMSF->createInstance( sConfigSrvc ),UNO_QUERY_THROW ); + + // access the provider + Sequence< Any > theArgs(1); + theArgs[ 0 ] <<= sConfigURL; + xNameAccess = Reference< XNameAccess > ( + theConfigProvider->createInstanceWithArguments( + sAccessSrvc, theArgs ), UNO_QUERY_THROW ); + } + } catch (com::sun::star::uno::Exception& e) + { + OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US); + OSL_ENSURE(sal_False, aMsg.getStr()); + } + return xNameAccess; +} + +Sequence< OUString > LanguageSelection::getInstalledLanguages() +{ + Sequence< OUString > seqLanguages; + Reference< XNameAccess > xAccess = getConfigAccess("org.openoffice.Setup/Office/InstalledLocales", sal_False); + if (!xAccess.is()) return seqLanguages; + seqLanguages = xAccess->getElementNames(); + return seqLanguages; +} + +// FIXME +// it's not very clever to handle language fallbacks here, but +// right now, there is no place that handles those fallbacks globally +static Sequence< OUString > _getFallbackLocales(const OUString& aIsoLang) +{ + Sequence< OUString > seqFallbacks; + if (aIsoLang.equalsAscii("zh-HK")) { + seqFallbacks = Sequence< OUString >(1); + seqFallbacks[0] = OUString::createFromAscii("zh-TW"); + } + return seqFallbacks; +} + +sal_Bool LanguageSelection::isInstalledLanguage(OUString& usLocale, sal_Bool bExact) +{ + sal_Bool bInstalled = sal_False; + Sequence< OUString > seqLanguages = getInstalledLanguages(); + for (sal_Int32 i=0; i<seqLanguages.getLength(); i++) + { + if (usLocale.equals(seqLanguages[i])) + { + bInstalled = sal_True; + break; + } + } + + if (!bInstalled && !bExact) + { + // try fallback locales + Sequence< OUString > seqFallbacks = _getFallbackLocales(usLocale); + for (sal_Int32 j=0; j<seqFallbacks.getLength(); j++) + { + for (sal_Int32 i=0; i<seqLanguages.getLength(); i++) + { + if (seqFallbacks[j].equals(seqLanguages[i])) + { + bInstalled = sal_True; + usLocale = seqFallbacks[j]; + break; + } + } + } + } + + if (!bInstalled && !bExact) + { + // no exact match was found, well try to find a substitute + OUString aInstalledLocale; + for (sal_Int32 i=0; i<seqLanguages.getLength(); i++) + { + if (usLocale.indexOf(seqLanguages[i]) == 0) + { + // requested locale starts with the installed locale + // (i.e. installed locale has index 0 in requested locale) + bInstalled = sal_True; + usLocale = seqLanguages[i]; + break; + } + } + } + return bInstalled; +} + +OUString LanguageSelection::getFirstInstalledLanguage() +{ + OUString aLanguage; + Sequence< OUString > seqLanguages = getInstalledLanguages(); + if (seqLanguages.getLength() > 0) + aLanguage = seqLanguages[0]; + return aLanguage; +} + +OUString LanguageSelection::getUserLanguage() +{ + OUString aUserLanguage; + Reference< XNameAccess > xAccess(getConfigAccess("org.openoffice.Office.Linguistic/General", sal_False)); + if (xAccess.is()) + { + try + { + xAccess->getByName(OUString::createFromAscii("UILocale")) >>= aUserLanguage; + } + catch ( NoSuchElementException const & ) + { + m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN; + return OUString(); + } + catch ( WrappedTargetException const & ) + { + m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN; + return OUString(); + } + } + return aUserLanguage; +} + +OUString LanguageSelection::getSystemLanguage() +{ + OUString aUserLanguage; + Reference< XNameAccess > xAccess(getConfigAccess("org.openoffice.System/L10N", sal_False)); + if (xAccess.is()) + { + try + { + xAccess->getByName(OUString::createFromAscii("UILocale")) >>= aUserLanguage; + } + catch ( NoSuchElementException const & ) + { + m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN; + return OUString(); + } + catch ( WrappedTargetException const & ) + { + m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN; + return OUString(); + } + } + return aUserLanguage; +} + + +void LanguageSelection::resetUserLanguage() +{ + try + { + Reference< XPropertySet > xProp(getConfigAccess("org.openoffice.Office.Linguistic/General", sal_True), UNO_QUERY_THROW); + xProp->setPropertyValue(OUString::createFromAscii("UILocale"), makeAny(OUString::createFromAscii(""))); + Reference< XChangesBatch >(xProp, UNO_QUERY_THROW)->commitChanges(); + } + catch ( PropertyVetoException& ) + { + // we are not allowed to change this + } + catch ( Exception& e) + { + OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US); + OSL_ENSURE(sal_False, aMsg.getStr()); + m_eStatus = LS_STATUS_CONFIGURATIONACCESS_BROKEN; + } +} + +LanguageSelection::LanguageSelectionStatus LanguageSelection::getStatus() +{ + return m_eStatus; +} + +} // namespace desktop diff --git a/desktop/source/app/langselect.hxx b/desktop/source/app/langselect.hxx new file mode 100644 index 000000000000..bdf3cd6364de --- /dev/null +++ b/desktop/source/app/langselect.hxx @@ -0,0 +1,74 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <list> +#include <sal/types.h> +#include <tools/string.hxx> +#include <rtl/ustring.hxx> +#include <tools/resid.hxx> +#include <com/sun/star/lang/Locale.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <svl/languageoptions.hxx> + +namespace desktop +{ + +class LanguageSelection +{ +public: + enum LanguageSelectionStatus + { + LS_STATUS_OK, + LS_STATUS_CANNOT_DETERMINE_LANGUAGE, + LS_STATUS_CONFIGURATIONACCESS_BROKEN + }; + + static com::sun::star::lang::Locale IsoStringToLocale(const rtl::OUString& str); + static rtl::OUString getLanguageString(); + static bool prepareLanguage(); + static LanguageSelectionStatus getStatus(); + +private: + static const rtl::OUString usFallbackLanguage; + static rtl::OUString aFoundLanguage; + static sal_Bool bFoundLanguage; + static LanguageSelectionStatus m_eStatus; + + static com::sun::star::uno::Reference< com::sun::star::container::XNameAccess > + getConfigAccess(const sal_Char* pPath, sal_Bool bUpdate=sal_False); + static com::sun::star::uno::Sequence< rtl::OUString > getInstalledLanguages(); + static sal_Bool isInstalledLanguage(rtl::OUString& usLocale, sal_Bool bExact=sal_False); + static rtl::OUString getFirstInstalledLanguage(); + static rtl::OUString getUserUILanguage(); + static rtl::OUString getUserLanguage(); + static rtl::OUString getSystemLanguage(); + static void resetUserLanguage(); + static void setDefaultLanguage(const rtl::OUString&); +}; + +} //namespace desktop diff --git a/desktop/source/app/lockfile.cxx b/desktop/source/app/lockfile.cxx new file mode 100644 index 000000000000..9cc447a6c56b --- /dev/null +++ b/desktop/source/app/lockfile.cxx @@ -0,0 +1,256 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" +#include <stdlib.h> +#include <time.h> +#ifdef WNT +#include <tools/prewin.h> +#include <windows.h> +#include <tools/postwin.h> +#endif +#include <sal/types.h> +#include <osl/file.hxx> +#include <osl/socket.hxx> +#include <osl/security.hxx> +#include <unotools/bootstrap.hxx> +#include <tools/string.hxx> +#include <tools/config.hxx> + +#include "lockfile.hxx" + + +using namespace ::osl; +using namespace ::rtl; +using namespace ::utl; + + +namespace desktop { + + // initialize static members... + // lock suffix + const OUString Lockfile::Suffix() + { return OUString::createFromAscii( "/.lock" ); } + // values for datafile + const ByteString Lockfile::Group() + { return ByteString( "Lockdata" ); } + const ByteString Lockfile::Userkey() + { return ByteString( "User" ); } + const ByteString Lockfile::Hostkey() + { return ByteString( "Host" ); } + const ByteString Lockfile::Stampkey() + { return ByteString( "Stamp" ); } + const ByteString Lockfile::Timekey() + { return ByteString( "Time" ); } + const ByteString Lockfile::IPCkey() + { return ByteString( "IPCServer" ); } + + Lockfile::Lockfile( bool bIPCserver ) + :m_bIPCserver(bIPCserver) + ,m_bRemove(sal_False) + ,m_bIsLocked(sal_False) + { + // build the file-url to use for the lock + OUString aUserPath; + utl::Bootstrap::locateUserInstallation( aUserPath ); + m_aLockname = aUserPath + Suffix(); + + // generate ID + const int nIdBytes = 16; + char tmpId[nIdBytes*2+1]; + time_t t; + srand( (unsigned)(t = time( NULL )) ); + int tmpByte = 0; + for (int i = 0; i<nIdBytes; i++) { + tmpByte = rand( ) % 0xFF; + sprintf( tmpId+i*2, "%02X", tmpByte ); // #100211# - checked + } + tmpId[nIdBytes*2]=0x00; + m_aId = OUString::createFromAscii( tmpId ); + + // generate date string + char *tmpTime = ctime( &t ); + if (tmpTime != NULL) { + m_aDate = OUString::createFromAscii( tmpTime ); + sal_Int32 i = m_aDate.indexOf('\n'); + if (i > 0) + m_aDate = m_aDate.copy(0, i); + } + + + // try to create file + File aFile(m_aLockname); + if (aFile.open( OpenFlag_Create ) == File::E_EXIST) { + m_bIsLocked = sal_True; + } else { + // new lock created + aFile.close( ); + syncToFile( ); + m_bRemove = sal_True; + } + } + + sal_Bool Lockfile::check( fpExecWarning execWarning ) + { + + if (m_bIsLocked) { + // lock existed, ask user what to do + if (isStale() || + (execWarning != 0 && (*execWarning)( this ))) { + // remove file and create new + File::remove( m_aLockname ); + File aFile(m_aLockname); + aFile.open( OpenFlag_Create ); + aFile.close( ); + syncToFile( ); + m_bRemove = sal_True; + return sal_True; + } else { + //leave alone and return false + m_bRemove = sal_False; + return sal_False; + } + } else { + // lock was created by us + return sal_True; + } + } + + sal_Bool Lockfile::isStale( void ) const + { + // this checks whether the lockfile was created on the same + // host by the same user. Should this be the case it is safe + // to assume that it is a stale lockfile which can be overwritten + String aLockname = m_aLockname; + Config aConfig(aLockname); + aConfig.SetGroup(Group()); + ByteString aIPCserver = aConfig.ReadKey( IPCkey() ); + if (! aIPCserver.EqualsIgnoreCaseAscii( "true" )) + return false; + + ByteString aHost = aConfig.ReadKey( Hostkey() ); + ByteString aUser = aConfig.ReadKey( Userkey() ); + // lockfile from same host? + ByteString myHost; +#ifdef WNT + /* + prevent windows from connecting to the net to get it's own + hostname by using the netbios name + */ + sal_Int32 sz = MAX_COMPUTERNAME_LENGTH + 1; + char* szHost = new char[sz]; + if (GetComputerName(szHost, (LPDWORD)&sz)) + myHost = OString(szHost); + else + myHost = OString("UNKNOWN"); + delete[] szHost; +#else + oslSocketResult sRes; + myHost = OUStringToOString( + SocketAddr::getLocalHostname( &sRes ), RTL_TEXTENCODING_ASCII_US ); +#endif + if (aHost == myHost) { + // lockfile by same UID + OUString myUserName; + Security aSecurity; + aSecurity.getUserName( myUserName ); + ByteString myUser = OUStringToOString( myUserName, RTL_TEXTENCODING_ASCII_US ); + if (aUser == myUser) + return sal_True; + } + return sal_False; + } + + void Lockfile::syncToFile( void ) const + { + String aLockname = m_aLockname; + Config aConfig(aLockname); + aConfig.SetGroup(Group()); + + // get information + ByteString aHost; +#ifdef WNT + /* + prevent windows from connecting to the net to get it's own + hostname by using the netbios name + */ + sal_Int32 sz = MAX_COMPUTERNAME_LENGTH + 1; + char* szHost = new char[sz]; + if (GetComputerName(szHost, (LPDWORD)&sz)) + aHost = OString(szHost); + else + aHost = OString("UNKNOWN"); + delete[] szHost; +#else + oslSocketResult sRes; + aHost = OUStringToOString( + SocketAddr::getLocalHostname( &sRes ), RTL_TEXTENCODING_ASCII_US ); +#endif + OUString aUserName; + Security aSecurity; + aSecurity.getUserName( aUserName ); + ByteString aUser = OUStringToOString( aUserName, RTL_TEXTENCODING_ASCII_US ); + ByteString aTime = OUStringToOString( m_aDate, RTL_TEXTENCODING_ASCII_US ); + ByteString aStamp = OUStringToOString( m_aId, RTL_TEXTENCODING_ASCII_US ); + + // write information + aConfig.WriteKey( Userkey(), aUser ); + aConfig.WriteKey( Hostkey(), aHost ); + aConfig.WriteKey( Stampkey(), aStamp ); + aConfig.WriteKey( Timekey(), aTime ); + aConfig.WriteKey( + IPCkey(), + m_bIPCserver ? ByteString("true") : ByteString("false") ); + aConfig.Flush( ); + } + + void Lockfile::clean( void ) + { + if ( m_bRemove ) + { + File::remove( m_aLockname ); + m_bRemove = sal_False; + } + } + + Lockfile::~Lockfile( void ) + { + // unlock userdata by removing file + if ( m_bRemove ) + File::remove( m_aLockname ); + } +} + + + + + + + + + diff --git a/desktop/source/app/lockfile.hxx b/desktop/source/app/lockfile.hxx new file mode 100644 index 000000000000..248e44c52160 --- /dev/null +++ b/desktop/source/app/lockfile.hxx @@ -0,0 +1,99 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +/* Information: + * This class implements a mechanism to lock a users installation directory, + * which is necessesary because instances of staroffice could be running on + * different hosts while using the same directory thus causing data + * inconsistency. + * When an existing lock is detected, the user will be asked whether he wants + * to continue anyway, thus removing the lock and replacing it with a new one + * + * ideas: + * - store information about user and host and time in the lockfile and display + * these when asking whether to remove the lockfile. + * - periodically check the lockfile and warn the user when it gets replaced + * + */ + +#include "sal/types.h" +#include "rtl/ustring.hxx" + +class ByteString; + +namespace desktop { + + class Lockfile; + bool Lockfile_execWarning( Lockfile * that ); + + class Lockfile + { + public: + + // contructs a new lockfile onject + Lockfile( bool bIPCserver = true ); + + // separating GUI code: + typedef bool (* fpExecWarning)( Lockfile * that ); + + // checks the lockfile, asks user when lockfile is + // found (iff gui) and returns false when we may not continue + sal_Bool check( fpExecWarning execWarning ); + + // removes the lockfile. should only be called in exceptional situations + void clean(void); + + // removes the lockfile + ~Lockfile(void); + + private: + // data in lockfile + static const ByteString Group(); + static const ByteString Userkey(); + static const ByteString Hostkey(); + static const ByteString Stampkey(); + static const ByteString Timekey(); + static const ByteString IPCkey(); + // lockfilename + static const rtl::OUString Suffix(); + bool m_bIPCserver; + // full qualified name (file://-url) of the lockfile + rtl::OUString m_aLockname; + // flag whether the d'tor should delete the lock + sal_Bool m_bRemove; + sal_Bool m_bIsLocked; + // ID + rtl::OUString m_aId; + rtl::OUString m_aDate; + // access to data in file + void syncToFile(void) const; + sal_Bool isStale(void) const; + friend bool Lockfile_execWarning( Lockfile * that ); + + }; + +} diff --git a/desktop/source/app/lockfile2.cxx b/desktop/source/app/lockfile2.cxx new file mode 100644 index 000000000000..c155d9e6a3cd --- /dev/null +++ b/desktop/source/app/lockfile2.cxx @@ -0,0 +1,70 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include "vcl/msgbox.hxx" +#include "desktopresid.hxx" +#include "desktop.hrc" +#include "tools/config.hxx" +#include "lockfile.hxx" + + +namespace desktop { + +bool Lockfile_execWarning( Lockfile * that ) +{ + // read information from lock + String aLockname = that->m_aLockname; + Config aConfig(aLockname); + aConfig.SetGroup(that->Group()); + ByteString aHost = aConfig.ReadKey( that->Hostkey() ); + ByteString aUser = aConfig.ReadKey( that->Userkey() ); + ByteString aStamp = aConfig.ReadKey( that->Stampkey() ); + ByteString aTime = aConfig.ReadKey( that->Timekey() ); + + // display warning and return response + QueryBox aBox( NULL, DesktopResId( QBX_USERDATALOCKED ) ); + // set box title + String aTitle = String( DesktopResId( STR_TITLE_USERDATALOCKED )); + aBox.SetText( aTitle ); + // insert values... + String aMsgText = aBox.GetMessText( ); + aMsgText.SearchAndReplaceAscii( + "$u", String( aUser, RTL_TEXTENCODING_ASCII_US) ); + aMsgText.SearchAndReplaceAscii( + "$h", String( aHost, RTL_TEXTENCODING_ASCII_US) ); + aMsgText.SearchAndReplaceAscii( + "$t", String( aTime, RTL_TEXTENCODING_ASCII_US) ); + aBox.SetMessText(aMsgText); + // do it + return aBox.Execute( ) == RET_YES; +} + +} + diff --git a/desktop/source/app/main.c b/desktop/source/app/main.c new file mode 100644 index 000000000000..dceaf1a3fba1 --- /dev/null +++ b/desktop/source/app/main.c @@ -0,0 +1,36 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "sal/config.h" + +#include "sal/main.h" + +#include "sofficemain.h" + +SAL_IMPLEMENT_MAIN() { + return soffice_main(); +} diff --git a/desktop/source/app/makefile.mk b/desktop/source/app/makefile.mk new file mode 100644 index 000000000000..085d8520e7ad --- /dev/null +++ b/desktop/source/app/makefile.mk @@ -0,0 +1,115 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=desktop +TARGET=dkt +AUTOSEG=true +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : ../deployment/inc/dp_misc.mk + +.IF "$(ENABLE_GNOMEVFS)"=="TRUE" +CFLAGS+=-DGNOME_VFS_ENABLED +.ENDIF + +# .IF "$(OS)" == "WNT" +# .IF "$(COM)" == "GCC" +# DEPLOYMENTMISCLIB = -ldeploymentmisc$(DLLPOSTFIX) +# .ELSE +# DEPLOYMENTMISCLIB = ideploymentmisc$(DLLPOSTFIX).lib +# .ENDIF +# .ELIF "$(OS)" == "OS2" +# DEPLOYMENTMISCLIB = ideploymentmisc$(DLLPOSTFIX).lib +# .ELSE +# DEPLOYMENTMISCLIB = -ldeploymentmisc$(DLLPOSTFIX) +# .ENDIF + +SHL1TARGET = sofficeapp +SHL1OBJS = \ + $(SLO)$/app.obj \ + $(SLO)$/appfirststart.obj \ + $(SLO)$/appinit.obj \ + $(SLO)$/appsys.obj \ + $(SLO)$/checkinstall.obj \ + $(SLO)$/check_ext_deps.obj \ + $(SLO)$/cmdlineargs.obj \ + $(SLO)$/cmdlinehelp.obj \ + $(SLO)$/configinit.obj \ + $(SLO)$/desktopcontext.obj \ + $(SLO)$/desktopresid.obj \ + $(SLO)$/dispatchwatcher.obj \ + $(SLO)$/langselect.obj \ + $(SLO)$/lockfile.obj \ + $(SLO)$/lockfile2.obj \ + $(SLO)$/officeipcthread.obj \ + $(SLO)$/sofficemain.obj \ + $(SLO)$/userinstall.obj + +SHL1LIBS = $(SLB)$/mig.lib + +SHL1STDLIBS = \ + $(COMPHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(DEPLOYMENTMISCLIB) \ + $(I18NISOLANGLIB) \ + $(SALLIB) \ + $(SFXLIB) \ + $(SVLLIB) \ + $(SVTOOLLIB) \ + $(TKLIB) \ + $(TOOLSLIB) \ + $(UCBHELPERLIB) \ + $(UNOTOOLSLIB) \ + $(VCLLIB) \ + $(VOSLIB) +SHL1VERSIONMAP = version.map +SHL1IMPLIB = i$(SHL1TARGET) +DEF1NAME = $(SHL1TARGET) + +OBJFILES = \ + $(OBJ)$/copyright_ascii_ooo.obj \ + $(OBJ)$/main.obj +.IF "$(GUI)" != "OS2" +OBJFILES += \ + $(OBJ)$/copyright_ascii_sun.obj +.ENDIF + +SLOFILES = $(SHL1OBJS) + +SRS1NAME= desktop +SRC1FILES= desktop.src + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/desktop/source/app/officeipcthread.cxx b/desktop/source/app/officeipcthread.cxx new file mode 100644 index 000000000000..fc74c3fb4504 --- /dev/null +++ b/desktop/source/app/officeipcthread.cxx @@ -0,0 +1,996 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include "app.hxx" +#include "officeipcthread.hxx" +#include "cmdlineargs.hxx" +#include "dispatchwatcher.hxx" +#include <memory> +#include <stdio.h> +#include <vos/process.hxx> +#include <unotools/bootstrap.hxx> +#include <vcl/svapp.hxx> +#include <vcl/help.hxx> +#include <unotools/configmgr.hxx> +#include <osl/thread.hxx> +#include <rtl/digest.h> +#include <rtl/ustrbuf.hxx> +#include <rtl/instance.hxx> +#include <osl/conditn.hxx> +#include <unotools/moduleoptions.hxx> +#include <rtl/bootstrap.hxx> +#include <rtl/strbuf.hxx> +#include <comphelper/processfactory.hxx> +#include "osl/file.hxx" +#include "rtl/process.h" +#include "tools/getprocessworkingdir.hxx" + +using namespace vos; +using namespace rtl; +using namespace desktop; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; + +const char *OfficeIPCThread::sc_aTerminationSequence = "InternalIPC::TerminateThread"; +const int OfficeIPCThread::sc_nTSeqLength = 28; +const char *OfficeIPCThread::sc_aShowSequence = "-tofront"; +const int OfficeIPCThread::sc_nShSeqLength = 5; +const char *OfficeIPCThread::sc_aConfirmationSequence = "InternalIPC::ProcessingDone"; +const int OfficeIPCThread::sc_nCSeqLength = 27; + +namespace { static char const ARGUMENT_PREFIX[] = "InternalIPC::Arguments"; } + +// Type of pipe we use +enum PipeMode +{ + PIPEMODE_DONTKNOW, + PIPEMODE_CREATED, + PIPEMODE_CONNECTED +}; + +namespace desktop +{ + +namespace { + +class Parser: public CommandLineArgs::Supplier { +public: + explicit Parser(rtl::OString const & input): m_input(input) { + if (!m_input.match(ARGUMENT_PREFIX) || + m_input.getLength() == RTL_CONSTASCII_LENGTH(ARGUMENT_PREFIX)) + { + throw CommandLineArgs::Supplier::Exception(); + } + m_index = RTL_CONSTASCII_LENGTH(ARGUMENT_PREFIX); + switch (m_input[m_index++]) { + case '0': + break; + case '1': + { + rtl::OUString url; + if (!next(&url, false)) { + throw CommandLineArgs::Supplier::Exception(); + } + m_cwdUrl.reset(url); + break; + } + case '2': + { + rtl::OUString path; + if (!next(&path, false)) { + throw CommandLineArgs::Supplier::Exception(); + } + rtl::OUString url; + if (osl::FileBase::getFileURLFromSystemPath(path, url) == + osl::FileBase::E_None) + { + m_cwdUrl.reset(url); + } + break; + } + default: + throw CommandLineArgs::Supplier::Exception(); + } + } + + virtual ~Parser() {} + + virtual boost::optional< rtl::OUString > getCwdUrl() { return m_cwdUrl; } + + virtual bool next(rtl::OUString * argument) { return next(argument, true); } + +private: + virtual bool next(rtl::OUString * argument, bool prefix) { + OSL_ASSERT(argument != NULL); + if (m_index < m_input.getLength()) { + if (prefix) { + if (m_input[m_index] != ',') { + throw CommandLineArgs::Supplier::Exception(); + } + ++m_index; + } + rtl::OStringBuffer b; + while (m_index < m_input.getLength()) { + char c = m_input[m_index]; + if (c == ',') { + break; + } + ++m_index; + if (c == '\\') { + if (m_index < m_input.getLength()) { + c = m_input[m_index++]; + switch (c) { + case '0': + c = '\0'; + break; + case ',': + case '\\': + break; + default: + throw CommandLineArgs::Supplier::Exception(); + } + } else { + throw CommandLineArgs::Supplier::Exception(); + } + } + b.append(c); + } + rtl::OString b2(b.makeStringAndClear()); + if (!rtl_convertStringToUString( + &argument->pData, b2.getStr(), b2.getLength(), + RTL_TEXTENCODING_UTF8, + (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR | + RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR | + RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR))) + { + throw CommandLineArgs::Supplier::Exception(); + } + return true; + } else { + return false; + } + } + + boost::optional< rtl::OUString > m_cwdUrl; + rtl::OString m_input; + sal_Int32 m_index; +}; + +bool addArgument( + ByteString * arguments, char prefix, rtl::OUString const & argument) +{ + rtl::OString utf8; + if (!argument.convertToString( + &utf8, RTL_TEXTENCODING_UTF8, + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | + RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))) + { + return false; + } + *arguments += prefix; + for (sal_Int32 i = 0; i < utf8.getLength(); ++i) { + char c = utf8[i]; + switch (c) { + case '\0': + *arguments += "\\0"; + break; + case ',': + *arguments += "\\,"; + break; + case '\\': + *arguments += "\\\\"; + break; + default: + *arguments += c; + break; + } + } + return true; +} + +} + +OfficeIPCThread* OfficeIPCThread::pGlobalOfficeIPCThread = 0; +namespace { struct Security : public rtl::Static<OSecurity, Security> {}; } +::osl::Mutex* OfficeIPCThread::pOfficeIPCThreadMutex = 0; + + +String CreateMD5FromString( const OUString& aMsg ) +{ + // PRE: aStr "file" + // BACK: Str "ababab....0f" Hexcode String + + rtlDigest handle = rtl_digest_create( rtl_Digest_AlgorithmMD5 ); + if ( handle > 0 ) + { + const sal_uInt8* pData = (const sal_uInt8*)aMsg.getStr(); + sal_uInt32 nSize = ( aMsg.getLength() * sizeof( sal_Unicode )); + sal_uInt32 nMD5KeyLen = rtl_digest_queryLength( handle ); + sal_uInt8* pMD5KeyBuffer = new sal_uInt8[ nMD5KeyLen ]; + + rtl_digest_init( handle, pData, nSize ); + rtl_digest_update( handle, pData, nSize ); + rtl_digest_get( handle, pMD5KeyBuffer, nMD5KeyLen ); + rtl_digest_destroy( handle ); + + // Create hex-value string from the MD5 value to keep the string size minimal + OUStringBuffer aBuffer( nMD5KeyLen * 2 + 1 ); + for ( sal_uInt32 i = 0; i < nMD5KeyLen; i++ ) + aBuffer.append( (sal_Int32)pMD5KeyBuffer[i], 16 ); + + delete [] pMD5KeyBuffer; + return aBuffer.makeStringAndClear(); + } + + return String(); +} + +class ProcessEventsClass_Impl +{ +public: + DECL_STATIC_LINK( ProcessEventsClass_Impl, CallEvent, void* pEvent ); + DECL_STATIC_LINK( ProcessEventsClass_Impl, ProcessDocumentsEvent, void* pEvent ); +}; + +IMPL_STATIC_LINK_NOINSTANCE( ProcessEventsClass_Impl, CallEvent, void*, pEvent ) +{ + // Application events are processed by the Desktop::HandleAppEvent implementation. + Desktop::HandleAppEvent( *((ApplicationEvent*)pEvent) ); + delete (ApplicationEvent*)pEvent; + return 0; +} + +IMPL_STATIC_LINK_NOINSTANCE( ProcessEventsClass_Impl, ProcessDocumentsEvent, void*, pEvent ) +{ + // Documents requests are processed by the OfficeIPCThread implementation + ProcessDocumentsRequest* pDocsRequest = (ProcessDocumentsRequest*)pEvent; + + if ( pDocsRequest ) + { + OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest ); + delete pDocsRequest; + } + return 0; +} + +void ImplPostForeignAppEvent( ApplicationEvent* pEvent ) +{ + Application::PostUserEvent( STATIC_LINK( NULL, ProcessEventsClass_Impl, CallEvent ), pEvent ); +} + +void ImplPostProcessDocumentsEvent( ProcessDocumentsRequest* pEvent ) +{ + Application::PostUserEvent( STATIC_LINK( NULL, ProcessEventsClass_Impl, ProcessDocumentsEvent ), pEvent ); +} + +OSignalHandler::TSignalAction SAL_CALL SalMainPipeExchangeSignalHandler::signal(TSignalInfo *pInfo) +{ + if( pInfo->Signal == osl_Signal_Terminate ) + OfficeIPCThread::DisableOfficeIPCThread(); + return (TAction_CallNextHandler); +} + +// ---------------------------------------------------------------------------- + +// The OfficeIPCThreadController implementation is a bookkeeper for all pending requests +// that were created by the OfficeIPCThread. The requests are waiting to be processed by +// our framework loadComponentFromURL function (e.g. open/print request). +// During shutdown the framework is asking OfficeIPCThreadController about pending requests. +// If there are pending requests framework has to stop the shutdown process. It is waiting +// for these requests because framework is not able to handle shutdown and open a document +// concurrently. + + +// XServiceInfo +OUString SAL_CALL OfficeIPCThreadController::getImplementationName() +throw ( RuntimeException ) +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.OfficeIPCThreadController" )); +} + +sal_Bool SAL_CALL OfficeIPCThreadController::supportsService( const OUString& ) +throw ( RuntimeException ) +{ + return sal_False; +} + +Sequence< OUString > SAL_CALL OfficeIPCThreadController::getSupportedServiceNames() +throw ( RuntimeException ) +{ + Sequence< OUString > aSeq( 0 ); + return aSeq; +} + +// XEventListener +void SAL_CALL OfficeIPCThreadController::disposing( const EventObject& ) +throw( RuntimeException ) +{ +} + +// XTerminateListener +void SAL_CALL OfficeIPCThreadController::queryTermination( const EventObject& ) +throw( TerminationVetoException, RuntimeException ) +{ + // Desktop ask about pending request through our office ipc pipe. We have to + // be sure that no pending request is waiting because framework is not able to + // handle shutdown and open a document concurrently. + + if ( OfficeIPCThread::AreRequestsPending() ) + throw TerminationVetoException(); + else + OfficeIPCThread::SetDowning(); +} + +void SAL_CALL OfficeIPCThreadController::notifyTermination( const EventObject& ) +throw( RuntimeException ) +{ +} + +// ---------------------------------------------------------------------------- + +::osl::Mutex& OfficeIPCThread::GetMutex() +{ + // Get or create our mutex for thread-saftey + if ( !pOfficeIPCThreadMutex ) + { + ::osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ); + if ( !pOfficeIPCThreadMutex ) + pOfficeIPCThreadMutex = new osl::Mutex; + } + + return *pOfficeIPCThreadMutex; +} + +void OfficeIPCThread::SetDowning() +{ + // We have the order to block all incoming requests. Framework + // wants to shutdown and we have to make sure that no loading/printing + // requests are executed anymore. + ::osl::MutexGuard aGuard( GetMutex() ); + + if ( pGlobalOfficeIPCThread ) + pGlobalOfficeIPCThread->mbDowning = true; +} + +static bool s_bInEnableRequests = false; + +void OfficeIPCThread::EnableRequests( bool i_bEnable ) +{ + // switch between just queueing the requests and executing them + ::osl::MutexGuard aGuard( GetMutex() ); + + if ( pGlobalOfficeIPCThread ) + { + s_bInEnableRequests = true; + pGlobalOfficeIPCThread->mbRequestsEnabled = i_bEnable; + if( i_bEnable ) + { + // hit the compiler over the head + ProcessDocumentsRequest aEmptyReq = ProcessDocumentsRequest( boost::optional< rtl::OUString >() ); + // trigger already queued requests + OfficeIPCThread::ExecuteCmdLineRequests( aEmptyReq ); + } + s_bInEnableRequests = false; + } +} + +sal_Bool OfficeIPCThread::AreRequestsPending() +{ + // Give info about pending requests + ::osl::MutexGuard aGuard( GetMutex() ); + if ( pGlobalOfficeIPCThread ) + return ( pGlobalOfficeIPCThread->mnPendingRequests > 0 ); + else + return sal_False; +} + +void OfficeIPCThread::RequestsCompleted( int nCount ) +{ + // Remove nCount pending requests from our internal counter + ::osl::MutexGuard aGuard( GetMutex() ); + if ( pGlobalOfficeIPCThread ) + { + if ( pGlobalOfficeIPCThread->mnPendingRequests > 0 ) + pGlobalOfficeIPCThread->mnPendingRequests -= nCount; + } +} + +OfficeIPCThread::Status OfficeIPCThread::EnableOfficeIPCThread() +{ + ::osl::MutexGuard aGuard( GetMutex() ); + + if( pGlobalOfficeIPCThread ) + return IPC_STATUS_OK; + + ::rtl::OUString aUserInstallPath; + ::rtl::OUString aDummy; + + ::vos::OStartupInfo aInfo; + OfficeIPCThread* pThread = new OfficeIPCThread; + + pThread->maPipeIdent = OUString( RTL_CONSTASCII_USTRINGPARAM( "SingleOfficeIPC_" ) ); + + // The name of the named pipe is created with the hashcode of the user installation directory (without /user). We have to retrieve + // this information from a unotools implementation. + ::utl::Bootstrap::PathStatus aLocateResult = ::utl::Bootstrap::locateUserInstallation( aUserInstallPath ); + if ( aLocateResult == ::utl::Bootstrap::PATH_EXISTS || aLocateResult == ::utl::Bootstrap::PATH_VALID) + aDummy = aUserInstallPath; + else + { + delete pThread; + return IPC_STATUS_BOOTSTRAP_ERROR; + } + + // Try to determine if we are the first office or not! This should prevent multiple + // access to the user directory ! + // First we try to create our pipe if this fails we try to connect. We have to do this + // in a loop because the the other office can crash or shutdown between createPipe + // and connectPipe!! + + OUString aIniName; + + aInfo.getExecutableFile( aIniName ); + sal_uInt32 lastIndex = aIniName.lastIndexOf('/'); + if ( lastIndex > 0 ) + { + aIniName = aIniName.copy( 0, lastIndex+1 ); + aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( "perftune" )); +#if defined(WNT) || defined(OS2) + aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( ".ini" )); +#else + aIniName += OUString( RTL_CONSTASCII_USTRINGPARAM( "rc" )); +#endif + } + + ::rtl::Bootstrap aPerfTuneIniFile( aIniName ); + + OUString aDefault( RTL_CONSTASCII_USTRINGPARAM( "0" )); + OUString aPreloadData; + + aPerfTuneIniFile.getFrom( OUString( RTL_CONSTASCII_USTRINGPARAM( "FastPipeCommunication" )), aPreloadData, aDefault ); + + + OUString aUserInstallPathHashCode; + + if ( aPreloadData.equalsAscii( "1" )) + { + sal_Char szBuffer[32]; + sprintf( szBuffer, "%d", SUPD ); + aUserInstallPathHashCode = OUString( szBuffer, strlen(szBuffer), osl_getThreadTextEncoding() ); + } + else + aUserInstallPathHashCode = CreateMD5FromString( aDummy ); + + + // Check result to create a hash code from the user install path + if ( aUserInstallPathHashCode.getLength() == 0 ) + return IPC_STATUS_BOOTSTRAP_ERROR; // Something completely broken, we cannot create a valid hash code! + + pThread->maPipeIdent = pThread->maPipeIdent + aUserInstallPathHashCode; + + PipeMode nPipeMode = PIPEMODE_DONTKNOW; + do + { + OSecurity &rSecurity = Security::get(); + // Try to create pipe + if ( pThread->maPipe.create( pThread->maPipeIdent.getStr(), OPipe::TOption_Create, rSecurity )) + { + // Pipe created + nPipeMode = PIPEMODE_CREATED; + } + else if( pThread->maPipe.create( pThread->maPipeIdent.getStr(), OPipe::TOption_Open, rSecurity )) // Creation not successfull, now we try to connect + { + // Pipe connected to first office + nPipeMode = PIPEMODE_CONNECTED; + } + else + { + OPipe::TPipeError eReason = pThread->maPipe.getError(); + if ((eReason == OPipe::E_ConnectionRefused) || (eReason == OPipe::E_invalidError)) + return IPC_STATUS_BOOTSTRAP_ERROR; + + // Wait for second office to be ready + TimeValue aTimeValue; + aTimeValue.Seconds = 0; + aTimeValue.Nanosec = 10000000; // 10ms + osl::Thread::wait( aTimeValue ); + } + + } while ( nPipeMode == PIPEMODE_DONTKNOW ); + + if ( nPipeMode == PIPEMODE_CREATED ) + { + // Seems we are the one and only, so start listening thread + pGlobalOfficeIPCThread = pThread; + pThread->create(); // starts thread + } + else + { + // Seems another office is running. Pipe arguments to it and self terminate + pThread->maStreamPipe = pThread->maPipe; + + sal_Bool bWaitBeforeClose = sal_False; + ByteString aArguments(RTL_CONSTASCII_STRINGPARAM(ARGUMENT_PREFIX)); + rtl::OUString cwdUrl; + if (!(tools::getProcessWorkingDir(&cwdUrl) && + addArgument(&aArguments, '1', cwdUrl))) + { + aArguments += '0'; + } + sal_uInt32 nCount = rtl_getAppCommandArgCount(); + for( sal_uInt32 i=0; i < nCount; i++ ) + { + rtl_getAppCommandArg( i, &aDummy.pData ); + if( aDummy.indexOf('-',0) != 0 ) + { + bWaitBeforeClose = sal_True; + } + if (!addArgument(&aArguments, ',', aDummy)) { + return IPC_STATUS_BOOTSTRAP_ERROR; + } + } + // finaly, write the string onto the pipe + pThread->maStreamPipe.write( aArguments.GetBuffer(), aArguments.Len() ); + pThread->maStreamPipe.write( "\0", 1 ); + + // wait for confirmation #95361# #95425# + ByteString aToken(sc_aConfirmationSequence); + char *aReceiveBuffer = new char[aToken.Len()+1]; + int n = pThread->maStreamPipe.read( aReceiveBuffer, aToken.Len() ); + aReceiveBuffer[n]='\0'; + + delete pThread; + if (aToken.CompareTo(aReceiveBuffer)!= COMPARE_EQUAL) { + // something went wrong + delete[] aReceiveBuffer; + return IPC_STATUS_BOOTSTRAP_ERROR; + } else { + delete[] aReceiveBuffer; + return IPC_STATUS_2ND_OFFICE; + } + } + + return IPC_STATUS_OK; +} + +void OfficeIPCThread::DisableOfficeIPCThread() +{ + osl::ClearableMutexGuard aMutex( GetMutex() ); + + if( pGlobalOfficeIPCThread ) + { + OfficeIPCThread *pOfficeIPCThread = pGlobalOfficeIPCThread; + pGlobalOfficeIPCThread = 0; + + // send thread a termination message + // this is done so the subsequent join will not hang + // because the thread hangs in accept of pipe + OPipe Pipe( pOfficeIPCThread->maPipeIdent, OPipe::TOption_Open, Security::get() ); + //Pipe.send( TERMINATION_SEQUENCE, TERMINATION_LENGTH ); + if (Pipe.isValid()) + { + Pipe.send( sc_aTerminationSequence, sc_nTSeqLength+1 ); // also send 0-byte + + // close the pipe so that the streampipe on the other + // side produces EOF + Pipe.close(); + } + + // release mutex to avoid deadlocks + aMutex.clear(); + + OfficeIPCThread::SetReady(pOfficeIPCThread); + + // exit gracefully and join + pOfficeIPCThread->join(); + delete pOfficeIPCThread; + + + } +} + +OfficeIPCThread::OfficeIPCThread() : + mbDowning( false ), + mbRequestsEnabled( false ), + mnPendingRequests( 0 ), + mpDispatchWatcher( 0 ) +{ +} + +OfficeIPCThread::~OfficeIPCThread() +{ + ::osl::ClearableMutexGuard aGuard( GetMutex() ); + + if ( mpDispatchWatcher ) + mpDispatchWatcher->release(); + maPipe.close(); + maStreamPipe.close(); + pGlobalOfficeIPCThread = 0; +} + +static void AddURLToStringList( const rtl::OUString& aURL, rtl::OUString& aStringList ) +{ + if ( aStringList.getLength() ) + aStringList += ::rtl::OUString::valueOf( (sal_Unicode)APPEVENT_PARAM_DELIMITER ); + aStringList += aURL; +} + +void OfficeIPCThread::SetReady(OfficeIPCThread* pThread) +{ + if (pThread == NULL) pThread = pGlobalOfficeIPCThread; + if (pThread != NULL) + { + pThread->cReady.set(); + } +} + +void SAL_CALL OfficeIPCThread::run() +{ + do + { + OPipe::TPipeError + nError = maPipe.accept( maStreamPipe ); + + + if( nError == OStreamPipe::E_None ) + { + + // #111143# and others: + // if we receive a request while the office is displaying some dialog or error during + // bootstrap, that dialogs event loop might get events that are dispatched by this thread + // we have to wait for cReady to be set by the real main loop. + // only reqests that dont dispatch events may be processed before cReady is set. + cReady.wait(); + + // we might have decided to shutdown while we were sleeping + if (!pGlobalOfficeIPCThread) return; + + // only lock the mutex when processing starts, othewise we deadlock when the office goes + // down during wait + osl::ClearableMutexGuard aGuard( GetMutex() ); + + ByteString aArguments; + // test byte by byte + const int nBufSz = 2048; + char pBuf[nBufSz]; + int nBytes = 0; + int nResult = 0; + // read into pBuf until '\0' is read or read-error + while ((nResult=maStreamPipe.recv( pBuf+nBytes, nBufSz-nBytes))>0) { + nBytes += nResult; + if (pBuf[nBytes-1]=='\0') { + aArguments += pBuf; + break; + } + } + // don't close pipe ... + + // #90717# Is this a lookup message from another application? if so, ignore + if ( aArguments.Len() == 0 ) + continue; + + // is this a termination message ? if so, terminate + if(( aArguments.CompareTo( sc_aTerminationSequence, sc_nTSeqLength ) == COMPARE_EQUAL ) || + mbDowning ) return; + String aEmpty; + std::auto_ptr< CommandLineArgs > aCmdLineArgs; + try + { + Parser p( aArguments ); + aCmdLineArgs.reset( new CommandLineArgs( p ) ); + } + catch ( CommandLineArgs::Supplier::Exception & ) + { +#if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL + fprintf( stderr, "Error in received command line arguments\n" ); +#endif + continue; + } + CommandLineArgs *pCurrentCmdLineArgs = Desktop::GetCommandLineArgs(); + + if ( aCmdLineArgs->IsQuickstart() ) + { + // we have to use application event, because we have to start quickstart service in main thread!! + ApplicationEvent* pAppEvent = + new ApplicationEvent( aEmpty, aEmpty, + "QUICKSTART", aEmpty ); + ImplPostForeignAppEvent( pAppEvent ); + } + + // handle request for acceptor + sal_Bool bAcceptorRequest = sal_False; + OUString aAcceptString; + if ( aCmdLineArgs->GetAcceptString(aAcceptString) && Desktop::CheckOEM()) { + ApplicationEvent* pAppEvent = + new ApplicationEvent( aEmpty, aEmpty, + "ACCEPT", aAcceptString ); + ImplPostForeignAppEvent( pAppEvent ); + bAcceptorRequest = sal_True; + } + // handle acceptor removal + OUString aUnAcceptString; + if ( aCmdLineArgs->GetUnAcceptString(aUnAcceptString) ) { + ApplicationEvent* pAppEvent = + new ApplicationEvent( aEmpty, aEmpty, + "UNACCEPT", aUnAcceptString ); + ImplPostForeignAppEvent( pAppEvent ); + bAcceptorRequest = sal_True; + } + +#ifndef UNX + // only in non-unix version, we need to handle a -help request + // in a running instance in order to display the command line help + if ( aCmdLineArgs->IsHelp() ) { + ApplicationEvent* pAppEvent = + new ApplicationEvent( aEmpty, aEmpty, "HELP", aEmpty ); + ImplPostForeignAppEvent( pAppEvent ); + } +#endif + + sal_Bool bDocRequestSent = sal_False; + ProcessDocumentsRequest* pRequest = new ProcessDocumentsRequest( + aCmdLineArgs->getCwdUrl()); + cProcessed.reset(); + pRequest->pcProcessed = &cProcessed; + + // Print requests are not dependent on the -invisible cmdline argument as they are + // loaded with the "hidden" flag! So they are always checked. + bDocRequestSent |= aCmdLineArgs->GetPrintList( pRequest->aPrintList ); + bDocRequestSent |= ( aCmdLineArgs->GetPrintToList( pRequest->aPrintToList ) && + aCmdLineArgs->GetPrinterName( pRequest->aPrinterName ) ); + + if ( !pCurrentCmdLineArgs->IsInvisible() ) + { + // Read cmdline args that can open/create documents. As they would open a window + // they are only allowed if the "-invisible" is currently not used! + bDocRequestSent |= aCmdLineArgs->GetOpenList( pRequest->aOpenList ); + bDocRequestSent |= aCmdLineArgs->GetViewList( pRequest->aViewList ); + bDocRequestSent |= aCmdLineArgs->GetStartList( pRequest->aStartList ); + bDocRequestSent |= aCmdLineArgs->GetForceOpenList( pRequest->aForceOpenList ); + bDocRequestSent |= aCmdLineArgs->GetForceNewList( pRequest->aForceNewList ); + + // Special command line args to create an empty document for a given module + + // #i18338# (lo) + // we only do this if no document was specified on the command line, + // since this would be inconsistent with the the behaviour of + // the first process, see OpenClients() (call to OpenDefault()) in app.cxx + if ( aCmdLineArgs->HasModuleParam() && Desktop::CheckOEM() && (!bDocRequestSent)) + { + SvtModuleOptions aOpt; + SvtModuleOptions::EFactory eFactory = SvtModuleOptions::E_WRITER; + if ( aCmdLineArgs->IsWriter() ) + eFactory = SvtModuleOptions::E_WRITER; + else if ( aCmdLineArgs->IsCalc() ) + eFactory = SvtModuleOptions::E_CALC; + else if ( aCmdLineArgs->IsDraw() ) + eFactory = SvtModuleOptions::E_DRAW; + else if ( aCmdLineArgs->IsImpress() ) + eFactory = SvtModuleOptions::E_IMPRESS; + else if ( aCmdLineArgs->IsBase() ) + eFactory = SvtModuleOptions::E_DATABASE; + else if ( aCmdLineArgs->IsMath() ) + eFactory = SvtModuleOptions::E_MATH; + else if ( aCmdLineArgs->IsGlobal() ) + eFactory = SvtModuleOptions::E_WRITERGLOBAL; + else if ( aCmdLineArgs->IsWeb() ) + eFactory = SvtModuleOptions::E_WRITERWEB; + + if ( pRequest->aOpenList.getLength() ) + pRequest->aModule = aOpt.GetFactoryName( eFactory ); + else + AddURLToStringList( aOpt.GetFactoryEmptyDocumentURL( eFactory ), pRequest->aOpenList ); + bDocRequestSent = sal_True; + } + } + + if (!aCmdLineArgs->IsQuickstart() && Desktop::CheckOEM()) { + sal_Bool bShowHelp = sal_False; + rtl::OUStringBuffer aHelpURLBuffer; + if (aCmdLineArgs->IsHelpWriter()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://swriter/start"); + } else if (aCmdLineArgs->IsHelpCalc()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://scalc/start"); + } else if (aCmdLineArgs->IsHelpDraw()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdraw/start"); + } else if (aCmdLineArgs->IsHelpImpress()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://simpress/start"); + } else if (aCmdLineArgs->IsHelpBase()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdatabase/start"); + } else if (aCmdLineArgs->IsHelpBasic()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://sbasic/start"); + } else if (aCmdLineArgs->IsHelpMath()) { + bShowHelp = sal_True; + aHelpURLBuffer.appendAscii("vnd.sun.star.help://smath/start"); + } + if (bShowHelp) { + Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::LOCALE ); + rtl::OUString aTmp; + aRet >>= aTmp; + aHelpURLBuffer.appendAscii("?Language="); + aHelpURLBuffer.append(aTmp); +#if defined UNX + aHelpURLBuffer.appendAscii("&System=UNX"); +#elif defined WNT + aHelpURLBuffer.appendAscii("&System=WIN"); +#elif defined MAC + aHelpURLBuffer.appendAscii("&System=MAC"); +#elif defined OS2 + aHelpURLBuffer.appendAscii("&System=OS2"); +#endif + ApplicationEvent* pAppEvent = + new ApplicationEvent( aEmpty, aEmpty, + "OPENHELPURL", aHelpURLBuffer.makeStringAndClear()); + ImplPostForeignAppEvent( pAppEvent ); + } + } + + if ( bDocRequestSent && Desktop::CheckOEM()) + { + // Send requests to dispatch watcher if we have at least one. The receiver + // is responsible to delete the request after processing it. + if ( aCmdLineArgs->HasModuleParam() ) + { + SvtModuleOptions aOpt; + + // Support command line parameters to start a module (as preselection) + if ( aCmdLineArgs->IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + pRequest->aModule = aOpt.GetFactoryName( SvtModuleOptions::E_WRITER ); + else if ( aCmdLineArgs->IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) ) + pRequest->aModule = aOpt.GetFactoryName( SvtModuleOptions::E_CALC ); + else if ( aCmdLineArgs->IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) ) + pRequest->aModule= aOpt.GetFactoryName( SvtModuleOptions::E_IMPRESS ); + else if ( aCmdLineArgs->IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) ) + pRequest->aModule= aOpt.GetFactoryName( SvtModuleOptions::E_DRAW ); + } + + + ImplPostProcessDocumentsEvent( pRequest ); + } + else + { + // delete not used request again + delete pRequest; + pRequest = NULL; + } + if (( aArguments.CompareTo( sc_aShowSequence, sc_nShSeqLength ) == COMPARE_EQUAL ) || + aCmdLineArgs->IsEmpty() ) + { + // no document was sent, just bring Office to front + ApplicationEvent* pAppEvent = + new ApplicationEvent( aEmpty, aEmpty, "APPEAR", aEmpty ); + ImplPostForeignAppEvent( pAppEvent ); + } + + // we don't need the mutex any longer... + aGuard.clear(); + // wait for processing to finish + if (bDocRequestSent) + cProcessed.wait(); + // processing finished, inform the requesting end + nBytes = 0; + while ( + (nResult = maStreamPipe.send(sc_aConfirmationSequence+nBytes, sc_nCSeqLength-nBytes))>0 && + ((nBytes += nResult) < sc_nCSeqLength) ) ; + // now we can close, don't we? + // maStreamPipe.close(); + + } + else + { +#if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL + fprintf( stderr, "Error on accept: %d\n", (int)nError ); +#endif + TimeValue tval; + tval.Seconds = 1; + tval.Nanosec = 0; + sleep( tval ); + } + } while( schedule() ); +} + +static void AddToDispatchList( + DispatchWatcher::DispatchList& rDispatchList, + boost::optional< rtl::OUString > const & cwdUrl, + const OUString& aRequestList, + DispatchWatcher::RequestType nType, + const OUString& aParam, + const OUString& aFactory ) +{ + if ( aRequestList.getLength() > 0 ) + { + sal_Int32 nIndex = 0; + do + { + OUString aToken = aRequestList.getToken( 0, APPEVENT_PARAM_DELIMITER, nIndex ); + if ( aToken.getLength() > 0 ) + rDispatchList.push_back( + DispatchWatcher::DispatchRequest( nType, aToken, cwdUrl, aParam, aFactory )); + } + while ( nIndex >= 0 ); + } +} + +sal_Bool OfficeIPCThread::ExecuteCmdLineRequests( ProcessDocumentsRequest& aRequest ) +{ + // protect the dispatch list + osl::ClearableMutexGuard aGuard( GetMutex() ); + + static DispatchWatcher::DispatchList aDispatchList; + + rtl::OUString aEmpty; + // Create dispatch list for dispatch watcher + AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aOpenList, DispatchWatcher::REQUEST_OPEN, aEmpty, aRequest.aModule ); + AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aViewList, DispatchWatcher::REQUEST_VIEW, aEmpty, aRequest.aModule ); + AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aStartList, DispatchWatcher::REQUEST_START, aEmpty, aRequest.aModule ); + AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aPrintList, DispatchWatcher::REQUEST_PRINT, aEmpty, aRequest.aModule ); + AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aPrintToList, DispatchWatcher::REQUEST_PRINTTO, aRequest.aPrinterName, aRequest.aModule ); + AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aForceOpenList, DispatchWatcher::REQUEST_FORCEOPEN, aEmpty, aRequest.aModule ); + AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aForceNewList, DispatchWatcher::REQUEST_FORCENEW, aEmpty, aRequest.aModule ); + + sal_Bool bShutdown( sal_False ); + + if ( pGlobalOfficeIPCThread ) + { + if( ! pGlobalOfficeIPCThread->AreRequestsEnabled() ) + return bShutdown; + + pGlobalOfficeIPCThread->mnPendingRequests += aDispatchList.size(); + if ( !pGlobalOfficeIPCThread->mpDispatchWatcher ) + { + pGlobalOfficeIPCThread->mpDispatchWatcher = DispatchWatcher::GetDispatchWatcher(); + pGlobalOfficeIPCThread->mpDispatchWatcher->acquire(); + } + + // copy for execute + DispatchWatcher::DispatchList aTempList( aDispatchList ); + aDispatchList.clear(); + + aGuard.clear(); + + // Execute dispatch requests + bShutdown = pGlobalOfficeIPCThread->mpDispatchWatcher->executeDispatchRequests( aTempList, s_bInEnableRequests ); + + // set processed flag + if (aRequest.pcProcessed != NULL) + aRequest.pcProcessed->set(); + } + + return bShutdown; +} + +} diff --git a/desktop/source/app/officeipcthread.hxx b/desktop/source/app/officeipcthread.hxx new file mode 100644 index 000000000000..2cbcab0fce2a --- /dev/null +++ b/desktop/source/app/officeipcthread.hxx @@ -0,0 +1,165 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _DESKTOP_OFFICEIPCTHREAD_HXX_ +#define _DESKTOP_OFFICEIPCTHREAD_HXX_ + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/frame/XTerminateListener.hpp> +#include <vos/pipe.hxx> +#include <vos/security.hxx> +#include <vos/thread.hxx> +#include <vos/signal.hxx> +#include <rtl/ustring.hxx> +#ifndef _CPPUHELPER_WEAKBASE2_HXX_ +#include <cppuhelper/implbase2.hxx> +#endif +#include <osl/conditn.hxx> +#include "boost/optional.hpp" + +namespace desktop +{ + +class SalMainPipeExchangeSignalHandler : public vos::OSignalHandler +{ + virtual TSignalAction SAL_CALL signal(TSignalInfo *pInfo); +}; + +// A request for the current office +// that was given by command line or by IPC pipe communication. +struct ProcessDocumentsRequest +{ + ProcessDocumentsRequest(boost::optional< rtl::OUString > const & cwdUrl): + aCwdUrl(cwdUrl), pcProcessed( NULL ) {} + + boost::optional< ::rtl::OUString > aCwdUrl; + ::rtl::OUString aModule; + ::rtl::OUString aOpenList; // Documents that should be opened in the default way + ::rtl::OUString aViewList; // Documents that should be opened in viewmode + ::rtl::OUString aStartList; // Documents/Presentations that should be started + ::rtl::OUString aPrintList; // Documents that should be printed on default printer + ::rtl::OUString aForceOpenList; // Documents that should be forced to open for editing (even templates) + ::rtl::OUString aForceNewList; // Documents that should be forced to create a new document + ::rtl::OUString aPrinterName; // The printer name that should be used for printing + ::rtl::OUString aPrintToList; // Documents that should be printed on the given printer + ::osl::Condition *pcProcessed; // pointer condition to be set when the request has been processed +}; + +class DispatchWatcher; +class OfficeIPCThread : public vos::OThread +{ + private: + static OfficeIPCThread* pGlobalOfficeIPCThread; + static ::osl::Mutex* pOfficeIPCThreadMutex; + + vos::OPipe maPipe; + vos::OStreamPipe maStreamPipe; + rtl::OUString maPipeIdent; + bool mbDowning; + bool mbRequestsEnabled; + int mnPendingRequests; + DispatchWatcher* mpDispatchWatcher; + + /* condition to be set when the request has been processed */ + ::osl::Condition cProcessed; + + /* condition to be set when the main event loop is ready + otherwise an error dialogs event loop could eat away + requests from a 2nd office */ + ::osl::Condition cReady; + + static ::osl::Mutex& GetMutex(); + static const char *sc_aTerminationSequence; + static const int sc_nTSeqLength; + static const char *sc_aShowSequence; + static const int sc_nShSeqLength; + static const char *sc_aConfirmationSequence; + static const int sc_nCSeqLength; + + OfficeIPCThread(); + + protected: + /// Working method which should be overridden + virtual void SAL_CALL run(); + + public: + enum Status + { + IPC_STATUS_OK, + IPC_STATUS_2ND_OFFICE, + IPC_STATUS_BOOTSTRAP_ERROR + }; + + virtual ~OfficeIPCThread(); + + // controlling pipe communication during shutdown + static void SetDowning(); + static void EnableRequests( bool i_bEnable = true ); + static sal_Bool AreRequestsPending(); + static void RequestsCompleted( int n = 1 ); + static sal_Bool ExecuteCmdLineRequests( ProcessDocumentsRequest& ); + + // return FALSE if second office + static Status EnableOfficeIPCThread(); + static void DisableOfficeIPCThread(); + // start dispatching events... + static void SetReady(OfficeIPCThread* pThread = NULL); + + bool AreRequestsEnabled() const { return mbRequestsEnabled && ! mbDowning; } +}; + + +class OfficeIPCThreadController : public ::cppu::WeakImplHelper2< + ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::frame::XTerminateListener > +{ + public: + OfficeIPCThreadController() {} + virtual ~OfficeIPCThreadController() {} + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw ( ::com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw ( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() + throw ( ::com::sun::star::uno::RuntimeException ); + + // XEventListener + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) + throw( ::com::sun::star::uno::RuntimeException ); + + // XTerminateListener + virtual void SAL_CALL queryTermination( const ::com::sun::star::lang::EventObject& aEvent ) + throw( ::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL notifyTermination( const ::com::sun::star::lang::EventObject& aEvent ) + throw( ::com::sun::star::uno::RuntimeException ); +}; + +} + +#endif // _DESKTOP_OFFICEIPCTHREAD_HXX_ diff --git a/desktop/source/app/omutexmember.hxx b/desktop/source/app/omutexmember.hxx new file mode 100644 index 000000000000..1edb90fec8c6 --- /dev/null +++ b/desktop/source/app/omutexmember.hxx @@ -0,0 +1,61 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef __FRAMEWORK_OMUTEXMEMBER_HXX_ +#define __FRAMEWORK_OMUTEXMEMBER_HXX_ + +//_________________________________________________________________________________________________________________ +// includes +//_________________________________________________________________________________________________________________ + +#include <osl/mutex.hxx> + +//_________________________________________________________________________________________________________________ +// namespace +//_________________________________________________________________________________________________________________ + +//_________________________________________________________________________________________________________________ +// definitions +//_________________________________________________________________________________________________________________ + +/*-************************************************************************************************************//** + @short definition of a public mutex member + @descr You can use this struct as baseclass to get a public mutex member for right initialization. + Don't use it as member. You can't guarantee the right order of initialization of baseclasses then! + And some other helper classes share the mutex with an implementation and must have a valid one. + + @seealso See implementation of constructors in derived classes for further informations! + + @devstatus ready +*//*-*************************************************************************************************************/ + +struct OMutexMember +{ + ::osl::Mutex m_aMutex; +}; + +#endif // #ifndef __FRAMEWORK_OMUTEXMEMBER_HXX_ diff --git a/desktop/source/app/sofficemain.cxx b/desktop/source/app/sofficemain.cxx new file mode 100644 index 000000000000..fc06850f237a --- /dev/null +++ b/desktop/source/app/sofficemain.cxx @@ -0,0 +1,52 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include "app.hxx" + +#include <rtl/logfile.hxx> +#include <tools/extendapplicationenvironment.hxx> + +BOOL SVMain(); + +// -=-= main() -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +extern "C" int soffice_main() +{ + tools::extendApplicationEnvironment(); + + RTL_LOGFILE_PRODUCT_TRACE( "PERFORMANCE - enter Main()" ); + + desktop::Desktop aDesktop; + // This string is used during initialization of the Gtk+ VCL module + aDesktop.SetAppName( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("soffice")) ); + SVMain(); + + return 0; +} diff --git a/desktop/source/app/sofficemain.h b/desktop/source/app/sofficemain.h new file mode 100644 index 000000000000..97775acd7016 --- /dev/null +++ b/desktop/source/app/sofficemain.h @@ -0,0 +1,43 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_DESKTOP_SOURCE_APP_SOFFICEMAIN_H +#define INCLUDED_DESKTOP_SOURCE_APP_SOFFICEMAIN_H + +#include "sal/config.h" + +#if defined __cplusplus +extern "C" { +#endif + +int soffice_main(void); + +#if defined __cplusplus +} +#endif + +#endif diff --git a/desktop/source/app/userinstall.cxx b/desktop/source/app/userinstall.cxx new file mode 100644 index 000000000000..546a6f0ad13c --- /dev/null +++ b/desktop/source/app/userinstall.cxx @@ -0,0 +1,301 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + + +#include "userinstall.hxx" +#include "langselect.hxx" + +#include <stdio.h> +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/file.hxx> +#include <osl/mutex.hxx> +#include <osl/process.h> +#include <osl/diagnose.h> +#include <vos/security.hxx> +#include <vos/ref.hxx> +#include <vos/process.hxx> + +#ifndef _TOOLS_RESMGR_HXX_ +#include <tools/resmgr.hxx> +#endif +#include <unotools/bootstrap.hxx> +#include <svl/languageoptions.hxx> +#ifndef _SVTOOLS_SYSLOCALEOPTIONSOPTIONS_HXX +#include <unotools/syslocaleoptions.hxx> +#endif +#include <comphelper/processfactory.hxx> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <i18npool/mslangid.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/util/XChangesBatch.hpp> +#include <com/sun/star/beans/XHierarchicalPropertySet.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XLocalizable.hpp> +#include <com/sun/star/lang/Locale.hpp> + +#include "app.hxx" + +using namespace rtl; +using namespace osl; +using namespace utl; +using namespace com::sun::star::container; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::util; + + +namespace desktop { + + static UserInstall::UserInstallError create_user_install(OUString&); + + static bool is_user_install() + { + try + { + OUString sConfigSrvc( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.ConfigurationProvider" ) ); + OUString sAccessSrvc( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.ConfigurationAccess" ) ); + + // get configuration provider + Reference< XMultiServiceFactory > theMSF + = comphelper::getProcessServiceFactory(); + Reference< XMultiServiceFactory > theConfigProvider + = Reference< XMultiServiceFactory >( + theMSF->createInstance(sConfigSrvc), UNO_QUERY_THROW); + + // localize the provider to user selection +// Reference< XLocalizable > localizable(theConfigProvider, UNO_QUERY_THROW); +// LanguageType aUserLanguageType = LanguageSelection::getLanguageType(); +// Locale aLocale( MsLangId::convertLanguageToIsoString(aUserLanguageType)); +// localizable->setLocale(aLocale); + + Reference< XLocalizable > localizable(theConfigProvider, UNO_QUERY_THROW); + OUString aUserLanguage = LanguageSelection::getLanguageString(); + Locale aLocale = LanguageSelection::IsoStringToLocale(aUserLanguage); + localizable->setLocale(aLocale); + + Sequence< Any > theArgs(1); + NamedValue v; + v.Name = OUString::createFromAscii("NodePath"); + v.Value = makeAny(OUString::createFromAscii("org.openoffice.Setup")); + theArgs[0] <<= v; + Reference< XHierarchicalNameAccess> hnacc( + theConfigProvider->createInstanceWithArguments( + sAccessSrvc, theArgs), UNO_QUERY_THROW); + + try + { + sal_Bool bValue = sal_False; + hnacc->getByHierarchicalName( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "Office/ooSetupInstCompleted" ) ) ) >>= bValue; + + return bValue ? true : false; + } + catch ( NoSuchElementException const & ) + { + // just return false in this case. + } + } + catch (Exception const & e) + { + OString msg(OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US)); + OSL_ENSURE(sal_False, msg.getStr()); + } + + return false; + } + + UserInstall::UserInstallError UserInstall::finalize() + { + OUString aUserInstallPath; + utl::Bootstrap::PathStatus aLocateResult = + utl::Bootstrap::locateUserInstallation(aUserInstallPath); + + switch (aLocateResult) { + + case utl::Bootstrap::DATA_INVALID: + case utl::Bootstrap::DATA_MISSING: + case utl::Bootstrap::DATA_UNKNOWN: + // cannot find a valid path or path is missing + return E_Unknown; + + case utl::Bootstrap::PATH_EXISTS: + { + // path exists, check if an installation lives there + if ( is_user_install() ) + { + return E_None; + } + // Note: fall-thru intended. + } + case utl::Bootstrap::PATH_VALID: + // found a path but need to create user install + return create_user_install(aUserInstallPath); + default: + return E_Unknown; + } + } + + static osl::FileBase::RC copy_recursive( const rtl::OUString& srcUnqPath, const rtl::OUString& dstUnqPath) + { + + FileBase::RC err; + DirectoryItem aDirItem; + DirectoryItem::get(srcUnqPath, aDirItem); + FileStatus aFileStatus(FileStatusMask_All); + aDirItem.getFileStatus(aFileStatus); + + if( aFileStatus.getFileType() == FileStatus::Directory) + { + // create directory if not already there + err = Directory::create( dstUnqPath ); + if (err == osl::FileBase::E_EXIST) + err = osl::FileBase::E_None; + + FileBase::RC next = err; + if (err == osl::FileBase::E_None) + { + // iterate through directory contents + Directory aDir( srcUnqPath ); + aDir.open(); + while (err == osl::FileBase::E_None && + (next = aDir.getNextItem( aDirItem )) == osl::FileBase::E_None) + { + aDirItem.getFileStatus(aFileStatus); + // generate new src/dst pair and make recursive call + rtl::OUString newSrcUnqPath = aFileStatus.getFileURL(); + rtl::OUString newDstUnqPath = dstUnqPath; + rtl::OUString itemname = aFileStatus.getFileName(); + // append trailing '/' if needed + if (newDstUnqPath.lastIndexOf(sal_Unicode('/')) != newDstUnqPath.getLength()-1) + newDstUnqPath += rtl::OUString::createFromAscii("/"); + newDstUnqPath += itemname; + // recursion + err = copy_recursive(newSrcUnqPath, newDstUnqPath); + } + aDir.close(); + + if ( err != osl::FileBase::E_None ) + return err; + if( next != FileBase::E_NOENT ) + err = FileBase::E_INVAL; + } + } + else + { + // copy single file - foldback + err = File::copy( srcUnqPath,dstUnqPath ); + } + return err; + } + + static const char *pszSrcList[] = { + "/presets", + NULL + }; + static const char *pszDstList[] = { + "/user", + NULL + }; + + + static UserInstall::UserInstallError create_user_install(OUString& aUserPath) + { + OUString aBasePath; + if (utl::Bootstrap::locateBaseInstallation(aBasePath) != utl::Bootstrap::PATH_EXISTS) + return UserInstall::E_InvalidBaseinstall; + + // create the user directory + FileBase::RC rc = Directory::createPath(aUserPath); + if ((rc != FileBase::E_None) && (rc != FileBase::E_EXIST)) return UserInstall::E_Creation; + + // copy data from shared data directory of base installation + for (sal_Int32 i=0; pszSrcList[i]!=NULL && pszDstList[i]!=NULL; i++) + { + rc = copy_recursive( + aBasePath + OUString::createFromAscii(pszSrcList[i]), + aUserPath + OUString::createFromAscii(pszDstList[i])); + if ((rc != FileBase::E_None) && (rc != FileBase::E_EXIST)) + { + if ( rc == FileBase::E_NOSPC ) + return UserInstall::E_NoDiskSpace; + else if ( rc == FileBase::E_ACCES ) + return UserInstall::E_NoWriteAccess; + else + return UserInstall::E_Creation; + } + } + try + { + OUString sConfigSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider"); + OUString sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess"); + + // get configuration provider + Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory(); + Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >( + theMSF->createInstance(sConfigSrvc), UNO_QUERY_THROW); + Sequence< Any > theArgs(1); + NamedValue v(OUString::createFromAscii("NodePath"), makeAny(OUString::createFromAscii("org.openoffice.Setup"))); + //v.Name = OUString::createFromAscii("NodePath"); + //v.Value = makeAny(OUString::createFromAscii("org.openoffice.Setup")); + theArgs[0] <<= v; + Reference< XHierarchicalPropertySet> hpset( + theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs), UNO_QUERY_THROW); + hpset->setHierarchicalPropertyValue(OUString::createFromAscii("Office/ooSetupInstCompleted"), makeAny(sal_True)); + Reference< XChangesBatch >(hpset, UNO_QUERY_THROW)->commitChanges(); + } + catch ( PropertyVetoException& ) + { + // we are not allowed to change this + } + catch (Exception& e) + { + OString aMsg("create_user_install(): "); + aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US); + OSL_ENSURE(sal_False, aMsg.getStr()); + return UserInstall::E_Creation; + } + + return UserInstall::E_None; + + } +} + + diff --git a/desktop/source/app/userinstall.hxx b/desktop/source/app/userinstall.hxx new file mode 100644 index 000000000000..8d6a51cd66be --- /dev/null +++ b/desktop/source/app/userinstall.hxx @@ -0,0 +1,52 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#include <sal/types.h> +#include <rtl/ustring.hxx> + +namespace desktop +{ + +class UserInstall +{ +public: + enum UserInstallError { + E_None, // no error + E_Creation, // error while creating user install + E_InvalidBaseinstall, // corrupt base installation + E_SetupFailed, // external setup did not run correctly + E_Configuration, // error while accessing configuration + E_License, // License not accepted + E_NoDiskSpace, // not enough disk space + E_NoWriteAccess, // no write access + E_Unknown // unknown error + }; + + static UserInstallError finalize(); +}; +} diff --git a/desktop/source/app/version.map b/desktop/source/app/version.map new file mode 100644 index 000000000000..0ffffcd58635 --- /dev/null +++ b/desktop/source/app/version.map @@ -0,0 +1,34 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +UDK_3_0_0 { + global: + soffice_main; + + local: + *; +}; |