diff options
Diffstat (limited to 'desktop')
693 files changed, 77990 insertions, 0 deletions
diff --git a/desktop/inc/app.hxx b/desktop/inc/app.hxx new file mode 100644 index 000000000000..977080c73ab9 --- /dev/null +++ b/desktop/inc/app.hxx @@ -0,0 +1,219 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_APP_HXX_ +#define _DESKTOP_APP_HXX_ + +// stl includes first +#include <map> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <vcl/svapp.hxx> +#include <vcl/timer.hxx> +#include <tools/resmgr.hxx> +#include <unotools/bootstrap.hxx> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/task/XStatusIndicator.hpp> +#include <com/sun/star/uno/Reference.h> +#include <osl/mutex.hxx> + +using namespace com::sun::star::task; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; + +#define DESKTOP_SAVETASKS_MOD 0x1 +#define DESKTOP_SAVETASKS_UNMOD 0x2 +#define DESKTOP_SAVETASKS_ALL 0x3 + +namespace desktop +{ + +/*-------------------------------------------------------------------- + Description: Application-class + --------------------------------------------------------------------*/ +class CommandLineArgs; +class Lockfile; +class AcceptorMap : public std::map< rtl::OUString, Reference<XInitialization> > {}; +struct ConvertData; +class Desktop : public Application +{ + friend class UserInstall; + + public: + enum BootstrapError + { + BE_OK, + BE_UNO_SERVICEMANAGER, + BE_UNO_SERVICE_CONFIG_MISSING, + BE_PATHINFO_MISSING, + BE_USERINSTALL_FAILED, + BE_LANGUAGE_MISSING, + BE_USERINSTALL_NOTENOUGHDISKSPACE, + BE_USERINSTALL_NOWRITEACCESS, + BE_OFFICECONFIG_BROKEN + }; + enum BootstrapStatus + { + BS_OK, + BS_TERMINATE + }; + + Desktop(); + ~Desktop(); + virtual void Main( ); + virtual void Init(); + virtual void InitFinished(); + virtual void DeInit(); + virtual BOOL QueryExit(); + virtual USHORT Exception(USHORT nError); + virtual void SystemSettingsChanging( AllSettings& rSettings, Window* pFrame ); + virtual void AppEvent( const ApplicationEvent& rAppEvent ); + + DECL_LINK( OpenClients_Impl, void* ); + + static void OpenClients(); + static void OpenDefault(); + + DECL_LINK( EnableAcceptors_Impl, void*); + + static void HandleAppEvent( const ApplicationEvent& rAppEvent ); + static ResMgr* GetDesktopResManager(); + static CommandLineArgs* GetCommandLineArgs(); + + void HandleBootstrapErrors( BootstrapError ); + void SetBootstrapError( BootstrapError nError ) + { + if ( m_aBootstrapError == BE_OK ) + m_aBootstrapError = nError; + } + BootstrapError GetBootstrapError() const + { + return m_aBootstrapError; + } + + void SetBootstrapStatus( BootstrapStatus nStatus ) + { + m_aBootstrapStatus = nStatus; + } + BootstrapStatus GetBootstrapStatus() const + { + return m_aBootstrapStatus; + } + + static sal_Bool CheckOEM(); + static sal_Bool isCrashReporterEnabled(); + + // first-start (ever) & license relate methods + static rtl::OUString GetLicensePath(); + static sal_Bool LicenseNeedsAcceptance(); + static sal_Bool IsFirstStartWizardNeeded(); + static sal_Bool CheckExtensionDependencies(); + + static void DoRestartActionsIfNecessary( sal_Bool bQuickStart ); + static void SetRestartState(); + + void SynchronizeExtensionRepositories(); + void SetSplashScreenText( const ::rtl::OUString& rText ); + void SetSplashScreenProgress( sal_Int32 ); + + private: + // Bootstrap methods + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > CreateApplicationServiceManager(); + + 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(); + + sal_Bool InitializeInstallation( const rtl::OUString& rAppFilename ); + sal_Bool InitializeConfiguration(); + void FlushConfiguration(); + static sal_Bool shouldLaunchQuickstart(); + sal_Bool InitializeQuickstartMode( com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& rSMgr ); + + void HandleBootstrapPathErrors( ::utl::Bootstrap::Status, const ::rtl::OUString& aMsg ); + void StartSetup( const ::rtl::OUString& aParameters ); + + // Get a resource message string securely e.g. if resource cannot be retrieved return aFaultBackMsg + ::rtl::OUString GetMsgString( USHORT nId, const ::rtl::OUString& aFaultBackMsg ); + + // Create a error message depending on bootstrap failure code and an optional file url + ::rtl::OUString CreateErrorMsgString( utl::Bootstrap::FailureCode nFailureCode, + const ::rtl::OUString& aFileURL ); + + static void PreloadModuleData( CommandLineArgs* ); + static void PreloadConfigurationData(); + + Reference<XStatusIndicator> m_rSplashScreen; + void OpenSplashScreen(); + void CloseSplashScreen(); + + void EnableOleAutomation(); + DECL_LINK( ImplInitFilterHdl, ConvertData* ); + DECL_LINK( AsyncInitFirstRun, void* ); + /** checks if the office is run the first time + <p>If so, <method>DoFirstRunInitializations</method> is called (asynchronously and delayed) and the + respective flag in the configuration is reset.</p> + */ + void CheckFirstRun( ); + + /// does initializations which are necessary for the first run of the office + void DoFirstRunInitializations(); + + static sal_Bool SaveTasks(); + static sal_Bool _bTasksSaved; + + static void retrieveCrashReporterState(); + static sal_Bool isUIOnSessionShutdownAllowed(); + + // on-demand acceptors + static void createAcceptor(const rtl::OUString& aDescription); + static void enableAcceptors(); + static void destroyAcceptor(const rtl::OUString& aDescription); + + sal_Bool m_bMinimized; + sal_Bool m_bInvisible; + bool m_bServicesRegistered; + USHORT m_nAppEvents; + BootstrapError m_aBootstrapError; + BootstrapStatus m_aBootstrapStatus; + + Lockfile *m_pLockfile; + Timer m_firstRunTimer; + + static ResMgr* pResMgr; + static sal_Bool bSuppressOpenDefault; +}; + +} + +#endif // _DESKTOP_APP_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/inc/deployment.hrc b/desktop/inc/deployment.hrc new file mode 100644 index 000000000000..92c5742fcdca --- /dev/null +++ b/desktop/inc/deployment.hrc @@ -0,0 +1,87 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DEPLOYMENT_HRC +#define INCLUDED_DEPLOYMENT_HRC + +#define MASKCOLOR MaskColor = \ + Color { Red = 0xFFFF ; Green = 0x0000 ; Blue = 0xFFFF ; }; + +#define RID_DEPLOYMENT_START 2000 + +#define RID_DEPLOYMENT_GUI_START RID_DEPLOYMENT_START +#define RID_DEPLOYMENT_MISC_START (RID_DEPLOYMENT_START+500) +#define RID_DEPLOYMENT_MANAGER_START (RID_DEPLOYMENT_START+1000) +#define RID_DEPLOYMENT_REGISTRY_START (RID_DEPLOYMENT_START+1500) + +#define RID_DEPLOYMENT_BUNDLE_START (RID_DEPLOYMENT_START+2000) +#define RID_IMG_DEF_PACKAGE_BUNDLE RID_DEPLOYMENT_BUNDLE_START +#define RID_IMG_DEF_PACKAGE_BUNDLE_HC (RID_DEPLOYMENT_BUNDLE_START+1) + +#define RID_DEPLOYMENT_SCRIPT_START (RID_DEPLOYMENT_START+2500) +#define RID_IMG_SCRIPTLIB RID_DEPLOYMENT_SCRIPT_START +#define RID_IMG_SCRIPTLIB_HC (RID_DEPLOYMENT_SCRIPT_START+1) +#define RID_IMG_DIALOGLIB (RID_DEPLOYMENT_SCRIPT_START+2) +#define RID_IMG_DIALOGLIB_HC (RID_DEPLOYMENT_SCRIPT_START+3) + +#define RID_DEPLOYMENT_CONF_START (RID_DEPLOYMENT_START+3000) +#define RID_IMG_CONF_XML RID_DEPLOYMENT_CONF_START +#define RID_IMG_CONF_XML_HC (RID_DEPLOYMENT_CONF_START+1) + +#define RID_DEPLOYMENT_COMPONENT_START (RID_DEPLOYMENT_START+3500) +#define RID_IMG_COMPONENT RID_DEPLOYMENT_COMPONENT_START +#define RID_IMG_COMPONENT_HC (RID_DEPLOYMENT_COMPONENT_START+1) +#define RID_IMG_JAVA_COMPONENT (RID_DEPLOYMENT_COMPONENT_START+2) +#define RID_IMG_JAVA_COMPONENT_HC (RID_DEPLOYMENT_COMPONENT_START+3) +#define RID_IMG_TYPELIB (RID_DEPLOYMENT_COMPONENT_START+4) +#define RID_IMG_TYPELIB_HC (RID_DEPLOYMENT_COMPONENT_START+5) +#define RID_IMG_JAVA_TYPELIB (RID_DEPLOYMENT_COMPONENT_START+6) +#define RID_IMG_JAVA_TYPELIB_HC (RID_DEPLOYMENT_COMPONENT_START+7) + +#define RID_DEPLOYMENT_UNOPKG_START (RID_DEPLOYMENT_START+4000) +#define RID_STR_UNOPKG_ACCEPT_LIC_1 (RID_DEPLOYMENT_UNOPKG_START+1) +#define RID_STR_UNOPKG_ACCEPT_LIC_2 (RID_DEPLOYMENT_UNOPKG_START+2) +#define RID_STR_UNOPKG_ACCEPT_LIC_3 (RID_DEPLOYMENT_UNOPKG_START+3) +#define RID_STR_UNOPKG_ACCEPT_LIC_4 (RID_DEPLOYMENT_UNOPKG_START+4) +#define RID_STR_UNOPKG_ACCEPT_LIC_YES (RID_DEPLOYMENT_UNOPKG_START+5) +#define RID_STR_UNOPKG_ACCEPT_LIC_Y (RID_DEPLOYMENT_UNOPKG_START+6) +#define RID_STR_UNOPKG_ACCEPT_LIC_NO (RID_DEPLOYMENT_UNOPKG_START+7) +#define RID_STR_UNOPKG_ACCEPT_LIC_N (RID_DEPLOYMENT_UNOPKG_START+8) +#define RID_STR_UNOPKG_ERROR (RID_DEPLOYMENT_UNOPKG_START+9) +#define RID_STR_CONCURRENTINSTANCE (RID_DEPLOYMENT_UNOPKG_START+10) + +#define RID_DEPLOYMENT_DEPENDENCIES_START (RID_DEPLOYMENT_START + 4400) +#define RID_DEPLYOMENT_DEPENDENCIES_UNKNOWN RID_DEPLOYMENT_DEPENDENCIES_START +#define RID_DEPLYOMENT_DEPENDENCIES_MIN (RID_DEPLOYMENT_DEPENDENCIES_START+1) +#define RID_DEPLYOMENT_DEPENDENCIES_MAX (RID_DEPLOYMENT_DEPENDENCIES_START+2) + +#define RID_DEPLOYMENT_LICENSE_START (RID_DEPLOYMENT_START+4500) + +#define RID_DEPLOYMENT_HELP_START (RID_DEPLOYMENT_START+5000) +#define RID_IMG_HELP RID_DEPLOYMENT_HELP_START +#define RID_IMG_HELP_HC (RID_DEPLOYMENT_HELP_START+1) +#endif diff --git a/desktop/inc/makefile.mk b/desktop/inc/makefile.mk new file mode 100644 index 000000000000..8715d814274f --- /dev/null +++ b/desktop/inc/makefile.mk @@ -0,0 +1,47 @@ +#************************************************************************* +# +# 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=inc + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk + +.IF "$(ENABLE_PCH)"!="" +ALLTAR : \ + $(SLO)$/precompiled.pch \ + $(SLO)$/precompiled_ex.pch + +.ENDIF # "$(ENABLE_PCH)"!="" + diff --git a/desktop/inc/migration.hxx b/desktop/inc/migration.hxx new file mode 100644 index 000000000000..3319d8d7716f --- /dev/null +++ b/desktop/inc/migration.hxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_MIGRATION_HXX_ +#define _DESKTOP_MIGRATION_HXX_ + +#include <sal/types.h> +#include <rtl/ustring.hxx> + +namespace desktop { + +class Migration +{ +public: + static void migrateSettingsIfNecessary(); +}; +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/inc/pch/precompiled_desktop.cxx b/desktop/inc/pch/precompiled_desktop.cxx new file mode 100644 index 000000000000..c75a09a3177e --- /dev/null +++ b/desktop/inc/pch/precompiled_desktop.cxx @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "precompiled_desktop.hxx" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/inc/pch/precompiled_desktop.hxx b/desktop/inc/pch/precompiled_desktop.hxx new file mode 100644 index 000000000000..023fa4937929 --- /dev/null +++ b/desktop/inc/pch/precompiled_desktop.hxx @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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): Generated on 2006-09-01 17:49:39.170923 + +#ifdef PRECOMPILED_HEADERS +#include "com/sun/star/beans/XPropertySet.hpp" +#include "com/sun/star/beans/NamedValue.hpp" +#include "comphelper/processfactory.hxx" +#include "osl/file.hxx" +#include "rtl/bootstrap.hxx" +#include "rtl/ustring.hxx" +#include "tools/datetime.hxx" +#include "tools/debug.hxx" +#include "unotools/configmgr.hxx" +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/os2/source/applauncher/launcher.cxx b/desktop/os2/source/applauncher/launcher.cxx new file mode 100644 index 000000000000..33bd34a6d059 --- /dev/null +++ b/desktop/os2/source/applauncher/launcher.cxx @@ -0,0 +1,121 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "launcher.hxx" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <malloc.h> +#include <process.h> + +int main( int argc, char* argv[]) +{ + PPIB pib; + APIRET rc; + RESULTCODES result = {0}; + char szFail[ _MAX_PATH]; + + HAB hab = WinInitialize( 0); + HMQ hmq = WinCreateMsgQueue( hab, 0); + ERRORID erridErrorCode = 0; + erridErrorCode = WinGetLastError(hab); + + // Calculate application name + CHAR szLibpath[_MAX_PATH*2]; + CHAR szApplicationName[_MAX_PATH]; + CHAR szDrive[_MAX_PATH]; + CHAR szDir[_MAX_PATH]; + CHAR szFileName[_MAX_PATH]; + CHAR szExt[_MAX_PATH]; + + // get executable fullpath + DosGetInfoBlocks(NULL, &pib); + DosQueryModuleName(pib->pib_hmte, sizeof(szApplicationName), szApplicationName); + + // adjust libpath + _splitpath( szApplicationName, szDrive, szDir, szFileName, szExt ); + char* basedir = strstr( szDir, "\\PROGRAM\\"); + if (basedir) *basedir = 0; + sprintf( szLibpath, "\"%s%s\\URE\\BIN\";\"%s%s\\BASIS\\PROGRAM\";%BeginLIBPATH%", + szDrive, szDir, szDrive, szDir); + DosSetExtLIBPATH( (PCSZ)szLibpath, BEGIN_LIBPATH); + // make sure we load DLL from our path only, so multiple instances/versions + // can be loaded. + + + // adjust exe name + _splitpath( szApplicationName, szDrive, szDir, szFileName, szExt ); + _makepath( szApplicationName, szDrive, szDir, OFFICE_IMAGE_NAME, (".bin") ); + + // copy command line parameters + int i, len; + len = strlen(szApplicationName) + 1 + strlen( APPLICATION_SWITCH) + 1 + 1; + for( i=1; i<argc; i++) + len += strlen( argv[i]) + 1; + + char* pszCommandLine, *pszArgs; + pszCommandLine = (char*) calloc( 1, len); + strcpy( pszCommandLine, szApplicationName); + pszArgs = pszCommandLine + strlen(szApplicationName) + 1; + strcat( pszArgs, APPLICATION_SWITCH); + strcat( pszArgs, " "); + for( i=1; i<argc; i++) { + // add quotes if argument has spaces! + if (strchr( argv[i], ' ')) + strcat( pszArgs, "\""); + strcat( pszArgs, argv[i]); + if (strchr( argv[i], ' ')) + strcat( pszArgs, "\""); + strcat( pszArgs, " "); + } + pszArgs[ strlen( pszArgs) + 0] = 0; + + // execute + rc = DosExecPgm(szFail, sizeof(szFail), + EXEC_SYNC, (PCSZ)pszCommandLine, (PCSZ)NULL, &result, + (PCSZ)szApplicationName); + if (rc) { + char szMessage[ _MAX_PATH*2]; + sprintf( szMessage, "Execution failed! Contact technical support.\n\nReturn code: %d\nFailing module:%s\n", rc, szFail); + rc = WinMessageBox( HWND_DESKTOP, HWND_DESKTOP, + (PSZ)szMessage, + (PSZ)"Unable to start OpenOffice.org!", + 0, MB_ERROR | MB_OK); + WinDestroyMsgQueue( hmq); + WinTerminate( hab); + exit(1); + } + + WinDestroyMsgQueue( hmq); + WinTerminate( hab); + + exit( result.codeResult); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/os2/source/applauncher/launcher.hxx b/desktop/os2/source/applauncher/launcher.hxx new file mode 100644 index 000000000000..1f1c1be96843 --- /dev/null +++ b/desktop/os2/source/applauncher/launcher.hxx @@ -0,0 +1,11 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +#define INCL_DOS +#define INCL_PM +#include <os2.h> + +#define OFFICE_IMAGE_NAME ("soffice") + +extern CHAR APPLICATION_SWITCH[]; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/os2/source/applauncher/makefile.mk b/desktop/os2/source/applauncher/makefile.mk new file mode 100644 index 000000000000..bf71b57c2fdf --- /dev/null +++ b/desktop/os2/source/applauncher/makefile.mk @@ -0,0 +1,121 @@ +#************************************************************************* +# +# 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=applauncher +LIBTARGET=NO +TARGETTYPE=GUI + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +OBJFILES= \ + $(OBJ)$/launcher.obj \ + $(OBJ)$/swriter.obj \ + $(OBJ)$/scalc.obj \ + $(OBJ)$/sdraw.obj \ + $(OBJ)$/simpress.obj \ + $(OBJ)$/sbase.obj \ + $(OBJ)$/smath.obj \ + $(OBJ)$/officeloader.obj \ + $(OBJ)$/quickstart.obj + +APP1TARGET=swriter +APP1NOSAL=TRUE +APP1LINKRES=$(MISC)$/$(TARGET)1.res +APP1ICON=$(SOLARRESDIR)$/icons$/ooo-writer-app.ico +APP1OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/swriter.obj + + +APP2TARGET=scalc +APP2NOSAL=TRUE +APP2LINKRES=$(MISC)$/$(TARGET)2.res +APP2ICON=$(SOLARRESDIR)$/icons$/ooo-calc-app.ico +APP2OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/scalc.obj + +APP3TARGET=sdraw +APP3NOSAL=TRUE +APP3LINKRES=$(MISC)$/$(TARGET)3.res +APP3ICON=$(SOLARRESDIR)$/icons$/ooo-draw-app.ico +APP3OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/sdraw.obj + +APP4TARGET=simpress +APP4NOSAL=TRUE +APP4LINKRES=$(MISC)$/$(TARGET)4.res +APP4ICON=$(SOLARRESDIR)$/icons$/ooo-impress-app.ico +APP4OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/simpress.obj + +APP5TARGET=sbase +APP5NOSAL=TRUE +APP5LINKRES=$(MISC)$/$(TARGET)5.res +APP5ICON=$(SOLARRESDIR)$/icons$/ooo-base-app.ico +APP5OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/sbase.obj + +APP6TARGET=smath +APP6NOSAL=TRUE +APP6LINKRES=$(MISC)$/$(TARGET)6.res +APP6ICON=$(SOLARRESDIR)$/icons$/ooo-math-app.ico +APP6OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/smath.obj + +APP7TARGET=officeloader +APP7NOSAL=TRUE +APP7LINKRES=$(MISC)$/$(TARGET)7.res +APP7ICON=$(SOLARRESDIR)$/icons$/ooo-main-app.ico +APP7OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/officeloader.obj + +APP8TARGET=quickstart +APP8NOSAL=TRUE +APP8LINKRES=$(MISC)$/$(TARGET)8.res +APP8ICON=$(SOLARRESDIR)$/icons$/ooo-main-app.ico +APP8OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/quickstart.obj + +# --- Targets ------------------------------------------------------ + + +.INCLUDE : target.mk + diff --git a/desktop/os2/source/applauncher/officeloader.cxx b/desktop/os2/source/applauncher/officeloader.cxx new file mode 100644 index 000000000000..f3124acdcfeb --- /dev/null +++ b/desktop/os2/source/applauncher/officeloader.cxx @@ -0,0 +1,6 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#include "launcher.hxx" + +CHAR APPLICATION_SWITCH[] = ( "" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/os2/source/applauncher/quickstart.cxx b/desktop/os2/source/applauncher/quickstart.cxx new file mode 100644 index 000000000000..b67389272f77 --- /dev/null +++ b/desktop/os2/source/applauncher/quickstart.cxx @@ -0,0 +1,6 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#include "launcher.hxx" + +CHAR APPLICATION_SWITCH[] = ( "-quickstart" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/os2/source/applauncher/sbase.cxx b/desktop/os2/source/applauncher/sbase.cxx new file mode 100644 index 000000000000..ed3e7cceb378 --- /dev/null +++ b/desktop/os2/source/applauncher/sbase.cxx @@ -0,0 +1,6 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#include "launcher.hxx" + +CHAR APPLICATION_SWITCH[] = ( "-base" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/os2/source/applauncher/scalc.cxx b/desktop/os2/source/applauncher/scalc.cxx new file mode 100644 index 000000000000..854f34e7f6c1 --- /dev/null +++ b/desktop/os2/source/applauncher/scalc.cxx @@ -0,0 +1,6 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#include "launcher.hxx" + +CHAR APPLICATION_SWITCH[] = ( "-calc" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/os2/source/applauncher/sdraw.cxx b/desktop/os2/source/applauncher/sdraw.cxx new file mode 100644 index 000000000000..b3f4bcff301a --- /dev/null +++ b/desktop/os2/source/applauncher/sdraw.cxx @@ -0,0 +1,6 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#include "launcher.hxx" + +CHAR APPLICATION_SWITCH[] = ( "-draw" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/os2/source/applauncher/simpress.cxx b/desktop/os2/source/applauncher/simpress.cxx new file mode 100644 index 000000000000..f4cf9575eb7b --- /dev/null +++ b/desktop/os2/source/applauncher/simpress.cxx @@ -0,0 +1,6 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#include "launcher.hxx" + +CHAR APPLICATION_SWITCH[] = ( "-impress" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/os2/source/applauncher/smath.cxx b/desktop/os2/source/applauncher/smath.cxx new file mode 100644 index 000000000000..d93b15d34519 --- /dev/null +++ b/desktop/os2/source/applauncher/smath.cxx @@ -0,0 +1,6 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#include "launcher.hxx" + +CHAR APPLICATION_SWITCH[] = ( "-math" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/os2/source/applauncher/swriter.cxx b/desktop/os2/source/applauncher/swriter.cxx new file mode 100644 index 000000000000..4fc857cf2e53 --- /dev/null +++ b/desktop/os2/source/applauncher/swriter.cxx @@ -0,0 +1,6 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#include "launcher.hxx" + +CHAR APPLICATION_SWITCH[] = ( "-writer" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/prj/build.lst b/desktop/prj/build.lst new file mode 100644 index 000000000000..162c43b38f15 --- /dev/null +++ b/desktop/prj/build.lst @@ -0,0 +1,45 @@ +dt desktop : l10n sfx2 stoc BERKELEYDB:berkeleydb sysui SO:sysui_so BOOST:boost svx xmlhelp sal unoil officecfg offuh NULL +dt desktop usr1 - all dt_mkout NULL +dt desktop\inc nmake - all dt_inc NULL +dt desktop\prj get - all dt_prj NULL +dt desktop\res get - all dt_res NULL +dt desktop\source\app nmake - all dt_app dt_migr dt_inc dt_dp_misc NULL +dt desktop\source\migration nmake - all dt_migr dt_inc NULL +dt desktop\source\migration\services nmake - all dt_services dt_inc dt_dp_misc NULL +dt desktop\source\so_comp nmake - all dt_so_comp dt_inc NULL +dt desktop\source\offacc nmake - all dt_offac dt_inc NULL +dt desktop\source\splash nmake - all dt_spl dt_migr dt_inc NULL +dt desktop\win32\source nmake - w dt_wrapper dt_inc NULL +dt desktop\win32\source\setup nmake - w dt_setup dt_inc NULL +dt desktop\win32\source\officeloader nmake - w dt_officeloader dt_inc NULL +dt desktop\win32\source\guiloader nmake - w dt_guiloader dt_wrapper.w dt_inc NULL +dt desktop\win32\source\guistdio nmake - w dt_guistdio dt_inc NULL +dt desktop\win32\source\applauncher nmake - w dt_applauncher dt_inc NULL +dt desktop\win32\source\applauncher\ooo nmake - w dt_applauncher_ooo dt_applauncher.w dt_inc NULL +dt desktop\win32\source\rebase nmake - w dt_rebase dt_inc NULL +dt desktop\os2\source\applauncher nmake - p dt_applauncher dt_inc NULL +dt desktop\unx\source\officeloader nmake - u dt_officeloader_unx dt_inc NULL +dt desktop\unx\source nmake - u dt_uwrapper dt_inc NULL +dt desktop\unx\splash nmake - u dt_usplash dt_inc NULL +dt desktop\source\pagein nmake - u dt_pagein dt_inc NULL +dt desktop\source\pkgchk\unopkg nmake - all dt_unopkg dt_dp_misc dt_app dt_inc dt_guiloader.w NULL +dt desktop\source\deployment nmake - all dt_deployment dt_dp_manager dt_dp_registry dt_dp_registry_package dt_dp_registry_executable dt_dp_registry_help dt_dp_registry_script dt_dp_registry_sfwk dt_dp_registry_component dt_dp_registry_configuration dt_dp_unopkg dt_inc dt_dp_misc NULL +dt desktop\source\deployment\misc nmake - all dt_dp_misc dt_inc NULL +dt desktop\source\deployment\unopkg nmake - all dt_dp_unopkg dt_inc NULL +dt desktop\source\deployment\gui nmake - all dt_dp_gui dt_dp_misc dt_inc NULL +dt desktop\source\deployment\manager nmake - all dt_dp_manager dt_inc NULL +dt desktop\source\deployment\registry nmake - all dt_dp_registry dt_inc NULL +dt desktop\source\deployment\registry\package nmake - all dt_dp_registry_package dt_inc NULL +dt desktop\source\deployment\registry\script nmake - all dt_dp_registry_script dt_inc NULL +dt desktop\source\deployment\registry\sfwk nmake - all dt_dp_registry_sfwk dt_inc NULL +dt desktop\source\deployment\registry\component nmake - all dt_dp_registry_component dt_inc NULL +dt desktop\source\deployment\registry\configuration nmake - all dt_dp_registry_configuration dt_inc NULL +dt desktop\source\deployment\registry\help nmake - all dt_dp_registry_help dt_inc NULL +dt desktop\source\deployment\registry\executable nmake - all dt_dp_registry_executable dt_inc NULL +dt desktop\scripts nmake - u dt_scripts dt_inc NULL +dt desktop\util nmake - all dt_util dt_app dt_pagein.u dt_so_comp dt_spl dt_uwrapper.u dt_usplash.u dt_wrapper.w dt_officeloader.w dt_officeloader_unx.u dt_migr dt_rebase.w NULL +dt desktop\zipintro nmake - all dt_zipintro NULL +dt desktop\registry\data\org\openoffice\Office nmake - all sn_regconfig NULL +dt desktop\source\registration\com\sun\star\servicetag\resources get - all sn_svctagres NULL +dt desktop\source\registration\com\sun\star\servicetag nmake - all sn_svctag NULL +dt desktop\source\registration\com\sun\star\registration nmake - all sn_regjob sn_svctag NULL diff --git a/desktop/prj/d.lst b/desktop/prj/d.lst new file mode 100644 index 000000000000..6251de274a69 --- /dev/null +++ b/desktop/prj/d.lst @@ -0,0 +1,137 @@ +mkdir: %COMMON_DEST%\bin%_EXT%\hid +mkdir: %_DEST%\bin%_EXT%\so +mkdir: %_DEST%\bin%_EXT%\c01 +mkdir: %_DEST%\bin%_EXT%\c05 +mkdir: %_DEST%\bin%_EXT%\c08 +mkdir: %_DEST%\bin%_EXT%\odf4ms + +..\%COMMON_OUTDIR%\misc\*.hid %COMMON_DEST%\bin%_EXT%\hid\*.hid +..\%__SRC%\bin\soffice.bin %_DEST%\bin%_EXT%\soffice.bin +..\%__SRC%\bin\officeloader.exe %_DEST%\bin%_EXT%\soffice.exe +..\%__SRC%\bin\soffice %_DEST%\bin%_EXT%\soffice.bin +..\%__SRC%\bin\soffice_mac %_DEST%\bin%_EXT%\soffice +..\%__SRC%\bin\oosplash %_DEST%\bin%_EXT%\oosplash.bin +..\%__SRC%\bin\so\soffice.bin %_DEST%\bin%_EXT%\so\soffice.bin +..\%__SRC%\bin\so\officeloader.exe %_DEST%\bin%_EXT%\so\soffice.exe +..\%__SRC%\bin\so\soffice %_DEST%\bin%_EXT%\so\soffice.bin +..\%__SRC%\bin\so\soffice_mac %_DEST%\bin%_EXT%\so\soffice +..\%__SRC%\bin\sofficea*.dll %_DEST%\bin%_EXT%\sofficea*.dll +..\%__SRC%\lib\isofficeapp.lib %_DEST%\lib%_EXT%\isofficeapp.lib +..\%__SRC%\lib\libsofficeapp.dylib %_DEST%\lib%_EXT%\libsofficeapp.dylib +..\%__SRC%\lib\libsofficeapp.so %_DEST%\lib%_EXT%\libsofficeapp.so + +..\%__SRC%\bin\soffice_oo.exe %_DEST%\bin%_EXT%\soffice_oo.exe +..\%__SRC%\bin\soffice_oo %_DEST%\bin%_EXT%\soffice_oo.bin +..\%__SRC%\bin\so\soffice_so.exe %_DEST%\bin%_EXT%\so\soffice_so.exe +..\%__SRC%\bin\so\soffice_so %_DEST%\bin%_EXT%\so\soffice_so.bin + +..\%__SRC%\bin\scalc.exe %_DEST%\bin%_EXT%\scalc.exe +..\%__SRC%\bin\sdraw.exe %_DEST%\bin%_EXT%\sdraw.exe +..\%__SRC%\bin\simpress.exe %_DEST%\bin%_EXT%\simpress.exe +..\%__SRC%\bin\smath.exe %_DEST%\bin%_EXT%\smath.exe +..\%__SRC%\bin\swriter.exe %_DEST%\bin%_EXT%\swriter.exe +..\%__SRC%\bin\sbase.exe %_DEST%\bin%_EXT%\sbase.exe +..\%__SRC%\bin\sweb.exe %_DEST%\bin%_EXT%\sweb.exe +..\%__SRC%\bin\quickstart.exe %_DEST%\bin%_EXT%\quickstart.exe +..\%__SRC%\bin\so\scalc.exe %_DEST%\bin%_EXT%\so\scalc.exe +..\%__SRC%\bin\so\sdraw.exe %_DEST%\bin%_EXT%\so\sdraw.exe +..\%__SRC%\bin\so\simpress.exe %_DEST%\bin%_EXT%\so\simpress.exe +..\%__SRC%\bin\so\smath.exe %_DEST%\bin%_EXT%\so\smath.exe +..\%__SRC%\bin\so\swriter.exe %_DEST%\bin%_EXT%\so\swriter.exe +..\%__SRC%\bin\so\sbase.exe %_DEST%\bin%_EXT%\so\sbase.exe +..\%__SRC%\bin\so\sweb.exe %_DEST%\bin%_EXT%\so\sweb.exe + +..\%__SRC%\misc\soffice.exe.manifest %_DEST%\bin%_EXT%\soffice.exe.manifest +..\%__SRC%\misc\soffice.bin.manifest %_DEST%\bin%_EXT%\soffice.bin.manifest +..\%__SRC%\bin\wrp*.dll %_DEST%\bin%_EXT%\wrp*.dll +..\%__SRC%\bin\spl*.dll %_DEST%\bin%_EXT%\spl*.dll +..\%__SRC%\bin\socomp.dll %_DEST%\bin%_EXT%\socomp.dll +..\%__SRC%\obj\officeloader.obj %_DEST%\lib%_EXT%\officeloader.obj +..\%__SRC%\obj\extendloaderenvironment.obj %_DEST%\lib%_EXT%\extendloaderenvironment.obj +..\%__SRC%\obj\copyright_ascii_sun.obj %_DEST%\lib%_EXT%\copyright_ascii_sun.obj +..\%__SRC%\obj\main.obj %_DEST%\lib%_EXT%\main.obj +..\%__SRC%\lib\libwrp*.so %_DEST%\lib%_EXT%\libwrp*.so +..\%__SRC%\lib\libwrp*.dylib %_DEST%\lib%_EXT%\libwrp*.dylib +..\%__SRC%\lib\libspl*.so %_DEST%\lib%_EXT%\libspl*.so +..\%__SRC%\lib\libspl*.dylib %_DEST%\lib%_EXT%\libspl*.dylib +..\%__SRC%\lib\libsocomp.so %_DEST%\lib%_EXT%\libsocomp.so +..\%__SRC%\lib\libsocomp.dylib %_DEST%\lib%_EXT%\libsocomp.dylib +..\%__SRC%\bin\offacc*.dll %_DEST%\bin%_EXT%\offacc*.dll +..\%__SRC%\lib\liboffacc*.so %_DEST%\lib%_EXT%\liboffacc*.so +..\%__SRC%\lib\liboffacc*.dylib %_DEST%\lib%_EXT%\liboffacc*.dylib +..\%__SRC%\bin\migratio*.dll %_DEST%\bin%_EXT%\migratio*.dll +..\%__SRC%\lib\migratio*.uno.so %_DEST%\lib%_EXT%\migratio*.uno.so +..\%__SRC%\lib\migratio*.uno.dylib %_DEST%\lib%_EXT%\migratio*.uno.dylib + +..\%__SRC%\bin\sweb %_DEST%\bin%_EXT%\sweb.bin + +..\%__SRC%\bin\loader2.ex? %_DEST%\bin%_EXT%\loader2.ex? + +..\%__SRC%\bin\depl*.dll %_DEST%\bin%_EXT%\depl*.dll +..\%__SRC%\lib\deployment*.uno.so %_DEST%\lib%_EXT%\deployment*.uno.so +..\%__SRC%\lib\deployment*.uno.dylib %_DEST%\lib%_EXT%\deployment*.uno.dylib +..\%__SRC%\bin\deploymentmisc*.dll %_DEST%\bin%_EXT%\deploymentmisc*.dll +..\%__SRC%\lib\libdeploymentmisc*.so %_DEST%\lib%_EXT%\libdeploymentmisc*.so +..\%__SRC%\lib\libdeploymentmisc*.dylib %_DEST%\lib%_EXT%\libdeploymentmisc*.dylib +..\%__SRC%\bin\guiloader.exe %_DEST%\bin%_EXT%\unopkg.exe +..\%__SRC%\bin\so\guiloader.exe %_DEST%\bin%_EXT%\so\unopkg.exe +..\%__SRC%\bin\unopkg %_DEST%\bin%_EXT%\unopkg.bin +..\%__SRC%\bin\so\unopkg %_DEST%\bin%_EXT%\so\unopkg.bin +..\%__SRC%\bin\unopkg.exe %_DEST%\bin%_EXT%\unopkg.bin +..\%__SRC%\bin\so\unopkg.exe %_DEST%\bin%_EXT%\so\unopkg.bin +..\%__SRC%\misc\unopkg.sh %_DEST%\bin%_EXT%\unopkg +..\%__SRC%\bin\unopkga*.dll %_DEST%\bin%_EXT%\unopkga*.dll +..\%__SRC%\lib\libunopkgapp.dylib %_DEST%\lib%_EXT%\libunopkgapp.dylib +..\%__SRC%\lib\libunopkgapp.so %_DEST%\lib%_EXT%\libunopkgapp.so +..\%__SRC%\bin\rebasegui.exe %_DEST%\bin%_EXT%\rebasegui.exe +..\%__SRC%\bin\rebaseoo.exe %_DEST%\bin%_EXT%\rebaseoo.exe + +..\%__SRC%\bin\pagein %_DEST%\bin%_EXT%\pagein +..\%__SRC%\misc\pagein-* %_DEST%\bin%_EXT%\pagein-* + +..\%__SRC%\bin\unoinfo.exe %_DEST%\bin%_EXT%\unoinfo.exe +..\%__SRC%\misc\unoinfo.sh %_DEST%\bin%_EXT%\unoinfo + +..\%__SRC%\bin\*.res %_DEST%\bin%_EXT%\*.res + +..\%__SRC%\misc\soffice.sh-expanded %_DEST%\bin%_EXT%\soffice +..\%__SRC%\misc\sbase.sh %_DEST%\bin%_EXT%\sbase +..\%__SRC%\misc\scalc.sh %_DEST%\bin%_EXT%\scalc +..\%__SRC%\misc\sdraw.sh %_DEST%\bin%_EXT%\sdraw +..\%__SRC%\misc\simpress.sh %_DEST%\bin%_EXT%\simpress +..\%__SRC%\misc\smaster.sh %_DEST%\bin%_EXT%\smaster +..\%__SRC%\misc\smath.sh %_DEST%\bin%_EXT%\smath +..\%__SRC%\misc\sweb.sh %_DEST%\bin%_EXT%\sweb +..\%__SRC%\misc\swriter.sh %_DEST%\bin%_EXT%\swriter +..\%__SRC%\misc\nswrapper.sh %_DEST%\bin%_EXT%\nswrapper +..\%__SRC%\misc\mozwrapper.sh %_DEST%\bin%_EXT%\mozwrapper + +mkdir: %COMMON_DEST%\pck%_EXT%\brand +mkdir: %COMMON_DEST%\pck%_EXT%\brand_dev + +..\%__SRC%\bin\brand\intro.zip %COMMON_DEST%\pck%_EXT%\brand\intro.zip +..\%__SRC%\bin\brand_dev\intro.zip %COMMON_DEST%\pck%_EXT%\brand_dev\intro.zip +..\%__SRC%\bin\shell\shell.zip %COMMON_DEST%\pck%_EXT%\shell.zip + +..\%__SRC%\bin\guiloader.exe %_DEST%\bin%_EXT%\testtool.exe + +..\%__SRC%\bin\guistdio.exe %_DEST%\bin%_EXT%\guistdio.com +..\%__SRC%\bin\guistdio.exe %_DEST%\bin%_EXT%\crashrep.com +..\%__SRC%\bin\unopkgio.exe %_DEST%\bin%_EXT%\unopkg.com + +..\scripts\ure-link %_DEST%\bin%_EXT%\ure-link +..\scripts\basis-link %_DEST%\bin%_EXT%\basis-link +..\scripts\basis-link %_DEST%\bin%_EXT%\c01\basis-link +..\scripts\basis-link %_DEST%\bin%_EXT%\c05\basis-link +..\scripts\basis-link %_DEST%\bin%_EXT%\c08\basis-link +..\scripts\so-basis-link %_DEST%\bin%_EXT%\so\basis-link +..\scripts\odf-basis-link %_DEST%\bin%_EXT%\odf4ms\basis-link + +mkdir: %_DEST%\xml%_EXT%\registry\spool +mkdir: %_DEST%\xml%_EXT%\registry\spool\org +mkdir: %_DEST%\xml%_EXT%\registry\spool\org\openoffice +mkdir: %_DEST%\xml%_EXT%\registry\spool\org\openoffice\Office +mkdir: %_DEST%\xml%_EXT%\registry\spool\org\openoffice\Office\Jobs + +..\%__SRC%\class\*.jar %_DEST%\bin%_EXT%\*.jar +..\%__SRC%\misc\registry\spool\org\openoffice\Office\Jobs\*.xcu %_DEST%\xml%_EXT%\registry\spool\org\openoffice\Office\Jobs diff --git a/desktop/qa/deployment_misc/makefile.mk b/desktop/qa/deployment_misc/makefile.mk new file mode 100644 index 000000000000..15faef0dc46e --- /dev/null +++ b/desktop/qa/deployment_misc/makefile.mk @@ -0,0 +1,54 @@ +#************************************************************************* +# +# 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 := qa_deployment_misc + +ENABLE_EXCEPTIONS := TRUE + +.INCLUDE: settings.mk +.INCLUDE: $(PRJ)$/source$/deployment$/inc$/dp_misc.mk + +CFLAGSCXX += $(CPPUNIT_CFLAGS) +DLLPRE = # no leading "lib" on .so files + +SHL1TARGET = $(TARGET) +SHL1OBJS = $(SLO)$/test_dp_version.obj +SHL1STDLIBS = $(CPPUNITLIB) $(DEPLOYMENTMISCLIB) $(SALLIB) $(TESTSHL2LIB) +SHL1VERSIONMAP = version.map +SHL1IMPLIB = i$(SHL1TARGET) +DEF1NAME = $(SHL1TARGET) + +SLOFILES = $(SHL1OBJS) + +.INCLUDE: target.mk + +ALLTAR: test + +test .PHONY: $(SHL1TARGETN) + $(TESTSHL2) $(SHL1TARGETN) diff --git a/desktop/qa/deployment_misc/test_dp_version.cxx b/desktop/qa/deployment_misc/test_dp_version.cxx new file mode 100644 index 000000000000..d5f2d5b41372 --- /dev/null +++ b/desktop/qa/deployment_misc/test_dp_version.cxx @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "sal/config.h" + +#include <cstddef> + +#include "testshl/simpleheader.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" + +#include "../../source/deployment/inc/dp_version.hxx" + +namespace { + +class Test: public ::CppUnit::TestFixture { +public: + void test(); + + CPPUNIT_TEST_SUITE(Test); + CPPUNIT_TEST(test); + CPPUNIT_TEST_SUITE_END(); +}; + +void Test::test() { + struct Data { + rtl::OUString version1; + rtl::OUString version2; + ::dp_misc::Order order; + }; + static Data const data[] = { + { rtl::OUString(), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0.0000.00.0")), + ::dp_misc::EQUAL }, + { rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".01")), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0.1")), + ::dp_misc::EQUAL }, + { rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("10")), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("2")), + ::dp_misc::GREATER }, + { rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("9223372036854775808")), + // 2^63 + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("9223372036854775807")), + ::dp_misc::GREATER } + }; + for (::std::size_t i = 0; i < sizeof data / sizeof (Data); ++i) { + CPPUNIT_ASSERT_EQUAL( + data[i].order, + ::dp_misc::compareVersions(data[i].version1, data[i].version2)); + static ::dp_misc::Order const reverse[3] = { + ::dp_misc::GREATER, ::dp_misc::EQUAL, ::dp_misc::LESS + }; + CPPUNIT_ASSERT_EQUAL( + reverse[data[i].order], + ::dp_misc::compareVersions(data[i].version2, data[i].version1)); + } +} + +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(Test, "alltests"); + +} + +NOADDITIONAL; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/qa/deployment_misc/version.map b/desktop/qa/deployment_misc/version.map new file mode 100644 index 000000000000..f313c44bd7ad --- /dev/null +++ b/desktop/qa/deployment_misc/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: + registerAllTestFunction; + + local: + *; +}; diff --git a/desktop/registry/data/org/openoffice/Office/Jobs.xcu b/desktop/registry/data/org/openoffice/Office/Jobs.xcu new file mode 100644 index 000000000000..f0d2783833a7 --- /dev/null +++ b/desktop/registry/data/org/openoffice/Office/Jobs.xcu @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--*********************************************************************** + * + * 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. + * + ************************************************************************ --> +<oor:component-data oor:name="Jobs" oor:package="org.openoffice.Office" xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <node oor:name="Jobs"> + <node oor:name="ProductRegistration" oor:op="replace"> + <prop oor:name="Service"> + <value>com.sun.star.comp.framework.DoRegistrationJob</value> + </prop> + <node oor:name="Arguments"> + <prop oor:name="ProductName" oor:op="replace" oor:type="xs:string"> + <value>${SERVICETAG_PRODUCTNAME}</value> + </prop> + <prop oor:name="ProductVersion" oor:op="replace" oor:type="xs:string"> + <value>${SERVICETAG_PRODUCTVERSION}</value> + </prop> + <prop oor:name="ProductURN" oor:op="replace" oor:type="xs:string"> + <value>${SERVICETAG_URN}</value> + </prop> + <prop oor:name="ProductSource" oor:op="replace" oor:type="xs:string"> + <value>${SERVICETAG_SOURCE}</value> + </prop> + <prop oor:name="ProductParent" oor:op="replace" oor:type="xs:string"> + <value>${SERVICETAG_PARENTNAME}</value> + </prop> + <prop oor:name="Vendor" oor:op="replace" oor:type="xs:string"> + <value>Sun Microsystems, Inc.</value> + </prop> + <prop oor:name="RegistrationData" oor:op="replace" oor:type="xs:string"> + <value>$(user)/registration.xml</value> + </prop> + <prop oor:name="RegistrationURL" oor:op="replace" oor:type="xs:string"> + <value>${REGISTRATION_HOST}/register/${registry_urn}?product=${REGISTRATION_PRODUCT}&locale=${locale}&cid=${REGISTRATION_CID}</value> + </prop> + </node> + </node> + </node> + <node oor:name="Events"> + <node oor:name="onRegisterNow" oor:op="fuse"> + <node oor:name="JobList"> + <node oor:name="ProductRegistration" oor:op="replace"/> + </node> + </node> + <node oor:name="onRegisterLater" oor:op="fuse"> + <node oor:name="JobList"> + <node oor:name="ProductRegistration" oor:op="replace"/> + </node> + </node> + </node> +</oor:component-data> diff --git a/desktop/registry/data/org/openoffice/Office/makefile.mk b/desktop/registry/data/org/openoffice/Office/makefile.mk new file mode 100644 index 000000000000..2ad8441ea3d3 --- /dev/null +++ b/desktop/registry/data/org/openoffice/Office/makefile.mk @@ -0,0 +1,77 @@ +#************************************************************************* +# +# 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=setup_native +TARGET=data_registration +PACKAGE=org.openoffice.Office + +ABSXCSROOT=$(SOLARXMLDIR) +XCSROOT=.. +DTDDIR=$(ABSXCSROOT) +XSLDIR=$(ABSXCSROOT)$/processing +PROCESSOUT=$(MISC)$/$(TARGET) +PROCESSORDIR=$(SOLARBINDIR) + +.INCLUDE : settings.mk +.IF "$(L10N_framework)"=="" + +# --- Files ------------------------------------------------------- + +.IF "$(BUILD_SPECIAL)"!="" + +XCUFILES= \ + Jobs.xcu + +MODULEFILES= + +LOCALIZEDFILES= + +PACKAGEDIR=$(subst,.,$/ $(PACKAGE)) +SPOOLDIR=$(MISC)$/registry$/spool + +MYXCUFILES= \ + $(SPOOLDIR)$/$(PACKAGEDIR)$/Jobs$/Jobs-registration.xcu + +.ELSE # "$(BUILD_SPECIAL)"!="" + +dummy: + @echo "Nothing to build" + +.ENDIF # "$(BUILD_SPECIAL)"!="" + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +.ENDIF # L10N_framework +ALLTAR : $(MYXCUFILES) + +$(SPOOLDIR)$/$(PACKAGEDIR)$/Jobs$/Jobs-registration.xcu : $(PROCESSOUT)$/registry$/data$/$/$(PACKAGEDIR)$/Jobs.xcu + @-$(MKDIRHIER) $(@:d) + @$(COPY) $< $@ + diff --git a/desktop/scripts/basis-link b/desktop/scripts/basis-link new file mode 100644 index 000000000000..3af84201e04f --- /dev/null +++ b/desktop/scripts/basis-link @@ -0,0 +1 @@ +Basis
\ No newline at end of file diff --git a/desktop/scripts/makefile.mk b/desktop/scripts/makefile.mk new file mode 100644 index 000000000000..5c412f818702 --- /dev/null +++ b/desktop/scripts/makefile.mk @@ -0,0 +1,67 @@ +#************************************************************************* +# +# 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=scripts + +# --- Settings ----------------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Targets ------------------------------------------------------------- + +UNIXTEXT= \ + $(MISC)$/sbase.sh \ + $(MISC)$/scalc.sh \ + $(MISC)$/sdraw.sh \ + $(MISC)$/simpress.sh \ + $(MISC)$/smaster.sh \ + $(MISC)$/smath.sh \ + $(MISC)$/sweb.sh \ + $(MISC)$/swriter.sh \ + $(MISC)$/mozwrapper.sh \ + $(MISC)$/unoinfo.sh \ + $(MISC)$/unopkg.sh + +.IF "$(OS)" != "MACOSX" + +ALLTAR: $(MISC)$/soffice.sh-expanded + +$(MISC)/soffice.sh-expanded: $(MISC)/soffice.sh +.IF "$(OS)" == "LINUX" && "$(CPUNAME)" == "POWERPC" + $(SED) 's/^#@# //' $< > $@ +.ELSE + $(COPY) $< $@ +.ENDIF + +UNIXTEXT+= $(MISC)$/soffice.sh + +.ENDIF + +.INCLUDE : target.mk diff --git a/desktop/scripts/mozwrapper.sh b/desktop/scripts/mozwrapper.sh new file mode 100644 index 000000000000..89b6415358be --- /dev/null +++ b/desktop/scripts/mozwrapper.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +# if mozilla is not found, specify full path here +MOZILLA=mozilla + +if ${MOZILLA} -remote "openURL($1,new-window)" 2>&1 | egrep -si "not running on display"; then + ${MOZILLA} $1 +fi diff --git a/desktop/scripts/odf-basis-link b/desktop/scripts/odf-basis-link new file mode 100644 index 000000000000..3af84201e04f --- /dev/null +++ b/desktop/scripts/odf-basis-link @@ -0,0 +1 @@ +Basis
\ No newline at end of file diff --git a/desktop/scripts/sbase.sh b/desktop/scripts/sbase.sh new file mode 100644 index 000000000000..932a535e53bd --- /dev/null +++ b/desktop/scripts/sbase.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cmd=`dirname "$0"`/soffice +exec "$cmd" -base "$@" diff --git a/desktop/scripts/scalc.sh b/desktop/scripts/scalc.sh new file mode 100644 index 000000000000..b1c3eebaff1f --- /dev/null +++ b/desktop/scripts/scalc.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cmd=`dirname "$0"`/soffice +exec "$cmd" -calc "$@" diff --git a/desktop/scripts/sdraw.sh b/desktop/scripts/sdraw.sh new file mode 100644 index 000000000000..fe0338a89394 --- /dev/null +++ b/desktop/scripts/sdraw.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cmd=`dirname "$0"`/soffice +exec "$cmd" -draw "$@" diff --git a/desktop/scripts/simpress.sh b/desktop/scripts/simpress.sh new file mode 100644 index 000000000000..20cae509b10a --- /dev/null +++ b/desktop/scripts/simpress.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cmd=`dirname "$0"`/soffice +exec "$cmd" -impress "$@" diff --git a/desktop/scripts/smaster.sh b/desktop/scripts/smaster.sh new file mode 100644 index 000000000000..affd55b265b0 --- /dev/null +++ b/desktop/scripts/smaster.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cmd=`dirname "$0"`/soffice +exec "$cmd" -global "$@" diff --git a/desktop/scripts/smath.sh b/desktop/scripts/smath.sh new file mode 100644 index 000000000000..ae4e3670a8d5 --- /dev/null +++ b/desktop/scripts/smath.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cmd=`dirname "$0"`/soffice +exec "$cmd" -math "$@" diff --git a/desktop/scripts/so-basis-link b/desktop/scripts/so-basis-link new file mode 100644 index 000000000000..3af84201e04f --- /dev/null +++ b/desktop/scripts/so-basis-link @@ -0,0 +1 @@ +Basis
\ No newline at end of file diff --git a/desktop/scripts/soffice.sh b/desktop/scripts/soffice.sh new file mode 100644 index 000000000000..71a5f1895875 --- /dev/null +++ b/desktop/scripts/soffice.sh @@ -0,0 +1,182 @@ +#!/bin/sh +#************************************************************************* +# +# 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. +# +#************************************************************************* + +# +# STAR_PROFILE_LOCKING_DISABLED=1 +# export STAR_PROFILE_LOCKING_DISABLED +# + +# file locking now enabled by default +SAL_ENABLE_FILE_LOCKING=1 +export SAL_ENABLE_FILE_LOCKING + +# Uncomment the line below if you suspect that OpenGL is not +# working on your system. +# SAL_NOOPENGL=true; export SAL_NOOPENGL + +# The following is needed on Linux PPC with IBM j2sdk142: +#@# export JITC_PROCESSOR_TYPE=6 + +# resolve installation directory +sd_cwd="`pwd`" +if [ -h "$0" ] ; then + sd_basename=`basename "$0"` + sd_script=`ls -l "$0" | sed "s/.*${sd_basename} -> //g"` + cd "`dirname "$0"`" + cd "`dirname "$sd_script"`" +else + cd "`dirname "$0"`" +fi +sd_prog=`pwd` +cd "$sd_cwd" + +# linked build needs additional settings +if [ -e ooenv ] ; then + . ./ooenv +fi + +sd_binary=`basename "$0"`.bin + +# this is a temporary hack until we can live with the default search paths +case "`uname -s`" in +OpenBSD) + sd_prog1="$sd_prog/../basis-link/program" + sd_prog2="$sd_prog/../basis-link/ure-link/lib" + LD_LIBRARY_PATH=$sd_prog1:$sd_prog2${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} + JAVA_HOME=$(javaPathHelper -h libreoffice-java 2> /dev/null) + export LD_LIBRARY_PATH + if [ -n "${JAVA_HOME}" ]; then + export JAVA_HOME + fi + ;; +esac + +#collect all bootstrap variables specified on the command line +#so that they can be passed as arguments to javaldx later on +for arg in $@ +do + case "$arg" in + -env:*) BOOTSTRAPVARS=$BOOTSTRAPVARS" ""$arg";; + esac +done + +# test for availability of the fast external splash +for arg in $@; do + if [ "$arg" = "-nologo" -o "$arg" = "-no-oosplash" ]; then + no_oosplash=y + fi +done + +# Setup our app as oosplash, but try to avoid executing pagein, +# and other expensive environment setup pieces wherever possible +# for a second started office +if [ "$sd_binary" = "soffice.bin" -a -x "$sd_prog/oosplash.bin" ] && [ "$no_oosplash" != "y" ] ; then + sd_binary="oosplash.bin" + + # try to connect to a running instance early + if "$sd_prog/$sd_binary" -qsend-and-report "$@" ; then + exit 0 + fi +fi + +# pagein +sd_pagein_args=@pagein-common +for sd_arg in "$@"; do + case ${sd_arg} in + -calc) + sd_pagein_args="${sd_pagein_args} @pagein-calc" + break; + ;; + -draw) + sd_pagein_args="${sd_pagein_args} @pagein-draw" + break; + ;; + -impress) + sd_pagein_args="${sd_pagein_args} @pagein-impress" + break; + ;; + -writer) + sd_pagein_args="${sd_pagein_args} @pagein-writer" + break; + ;; + esac +done +"$sd_prog/../basis-link/program/pagein" -L"$sd_prog/../basis-link/program" \ + ${sd_pagein_args} + +# extend the ld_library_path for java: javaldx checks the sofficerc for us +if [ -x "$sd_prog/../basis-link/ure-link/bin/javaldx" ] ; then + my_path=`"$sd_prog/../basis-link/ure-link/bin/javaldx" $BOOTSTRAPVARS \ + "-env:INIFILENAME=vnd.sun.star.pathname:$sd_prog/redirectrc"` + if [ -n "$my_path" ] ; then + sd_platform=`uname -s` + case $sd_platform in + AIX) + LIBPATH=$my_path${LIBPATH:+:$LIBPATH} + export LIBPATH + ;; + *) + LD_LIBRARY_PATH=$my_path${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} + export LD_LIBRARY_PATH + ;; + esac + fi +fi + +unset XENVIRONMENT + +# uncomment line below to disable anti aliasing of fonts +# SAL_ANTIALIAS_DISABLE=true; export SAL_ANTIALIAS_DISABLE + +# uncomment line below if you encounter problems starting soffice on your system +# SAL_NO_XINITTHREADS=true; export SAL_NO_XINITTHREADS + +# read database entries for Adabas D +if [ -f /etc/adabasrc ]; then + . /etc/adabasrc +fi + +# execute soffice binary +"$sd_prog/$sd_binary" "$@" & +trap 'kill -9 $!' TERM +wait $! +sd_ret=$? + +while [ $sd_ret -eq 79 -o $sd_ret -eq 81 ] +do + if [ $sd_ret -eq 79 ]; then + "$sd_prog/$sd_binary" ""$BOOTSTRAPVARS"" & + elif [ $sd_ret -eq 81 ]; then + "$sd_prog/$sd_binary" "$@" & + fi + + wait $! + sd_ret=$? +done + +exit $sd_ret diff --git a/desktop/scripts/sweb.sh b/desktop/scripts/sweb.sh new file mode 100644 index 000000000000..6d814e26e8aa --- /dev/null +++ b/desktop/scripts/sweb.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cmd=`dirname "$0"`/soffice +exec "$cmd" -web "$@" diff --git a/desktop/scripts/swriter.sh b/desktop/scripts/swriter.sh new file mode 100644 index 000000000000..34ca9fee30c7 --- /dev/null +++ b/desktop/scripts/swriter.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cmd=`dirname "$0"`/soffice +exec "$cmd" -writer "$@" diff --git a/desktop/scripts/unoinfo.sh b/desktop/scripts/unoinfo.sh new file mode 100644 index 000000000000..3af17625a6be --- /dev/null +++ b/desktop/scripts/unoinfo.sh @@ -0,0 +1,56 @@ +#!/bin/sh +#************************************************************************* +# +# 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. +# +#************************************************************************* + +set -e + +# resolve installation directory +if [ -h "$0" ] ; then + sd_basename=`basename "$0"` + sd_script=`ls -l "$0" | sed "s/.*${sd_basename} -> //g"` + cd "`dirname "$0"`" + cd "`dirname "$sd_script"`" +else + cd "`dirname "$0"`" +fi +sd_prog=`pwd` + +case $1 in +c++) + printf '%s' "$sd_prog/../basis-link/ure-link/lib" + ;; +java) + printf '0%s\0%s\0%s\0%s\0%s' \ + "$sd_prog/../basis-link/ure-link/share/java/ridl.jar" \ + "$sd_prog/../basis-link/ure-link/share/java/jurt.jar" \ + "$sd_prog/../basis-link/ure-link/share/java/juh.jar" \ + "$sd_prog/../basis-link/program/classes/unoil.jar" "$sd_prog" + ;; +*) + exit 1 + ;; +esac diff --git a/desktop/scripts/unopkg.sh b/desktop/scripts/unopkg.sh new file mode 100644 index 000000000000..2be74935ef3f --- /dev/null +++ b/desktop/scripts/unopkg.sh @@ -0,0 +1,99 @@ +#!/bin/sh +#************************************************************************* +# +# 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. +# +#************************************************************************* + +# enable file locking +SAL_ENABLE_FILE_LOCKING=1 +export SAL_ENABLE_FILE_LOCKING + +# resolve installation directory +sd_cwd="`pwd`" +if [ -h "$0" ] ; then + sd_basename=`basename "$0"` + sd_script=`ls -l "$0" | sed "s/.*${sd_basename} -> //g"` + cd "`dirname "$0"`" + cd "`dirname "$sd_script"`" +else + cd "`dirname "$0"`" +fi +sd_prog=`pwd` +cd "$sd_cwd" + +# this is a temporary hack until we can live with the default search paths +case "`uname -s`" in +OpenBSD) + sd_prog1="$sd_prog/../basis-link/program" + sd_prog2="$sd_prog/../basis-link/ure-link/lib" + LD_LIBRARY_PATH=$sd_prog1:$sd_prog2${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} + JAVA_HOME=$(javaPathHelper -h libreoffice-java 2> /dev/null) + export LD_LIBRARY_PATH + if [ -n "${JAVA_HOME}" ]; then + export JAVA_HOME + fi + ;; +esac + +#collect all bootstrap variables specified on the command line +#so that they can be passed as arguments to javaldx later on +for arg in $@ +do + case "$arg" in + -env:*) BOOTSTRAPVARS=$BOOTSTRAPVARS" ""$arg";; + esac +done + +# extend the ld_library_path for java: javaldx checks the sofficerc for us +if [ -x "$sd_prog/../basis-link/ure-link/bin/javaldx" ] ; then + my_path=`"$sd_prog/../basis-link/ure-link/bin/javaldx" $BOOTSTRAPVARS \ + "-env:INIFILENAME=vnd.sun.star.pathname:$sd_prog/redirectrc"` + if [ -n "$my_path" ] ; then + sd_platform=`uname -s` + case $sd_platform in + AIX) + LIBPATH=$my_path${LIBPATH:+:$LIBPATH} + export LIBPATH + ;; + *) + LD_LIBRARY_PATH=$my_path${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} + export LD_LIBRARY_PATH + ;; + esac + fi +fi + +unset XENVIRONMENT + +# uncomment line below to disable anti aliasing of fonts +# SAL_ANTIALIAS_DISABLE=true; export SAL_ANTIALIAS_DISABLE + +# uncomment line below if you encounter problems starting soffice on your system +# SAL_NO_XINITTHREADS=true; export SAL_NO_XINITTHREADS + +# execute binary +exec "$sd_prog/unopkg.bin" "$@" \ + "-env:INIFILENAME=vnd.sun.star.pathname:$sd_prog/redirectrc" + diff --git a/desktop/scripts/ure-link b/desktop/scripts/ure-link new file mode 100644 index 000000000000..dd0ecb6115e8 --- /dev/null +++ b/desktop/scripts/ure-link @@ -0,0 +1 @@ +..\URE
\ No newline at end of file diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx new file mode 100644 index 000000000000..05858e19cdc0 --- /dev/null +++ b/desktop/source/app/app.cxx @@ -0,0 +1,3343 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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.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> +#include <com/sun/star/task/XJob.hpp> +#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> +#include <toolkit/unohlp.hxx> +#include <osl/security.hxx> +#include <rtl/ref.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/componentcontext.hxx> +#include <comphelper/configurationhelper.hxx> +#include <unotools/configmgr.hxx> +#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/process.h> +#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 <sfx2/app.hxx> +#include <svl/itemset.hxx> +#include <svl/eitem.hxx> +#include <ucbhelper/contentbroker.hxx> +#include <unotools/bootstrap.hxx> +#include <cppuhelper/bootstrap.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 rtl::OUString; +using rtl::OUStringBuffer; + +//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 oslSignalHandler 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()) + { + osl_getExecutableFile( &sProductKey.pData ); + + ::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(RTL_CONSTASCII_USTRINGPARAM("/")); + + 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 = osl_addSignalHandler(SalMainPipeExchangeSignal_impl, NULL); + } +} + +void Desktop::InitFinished() +{ + RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::InitFinished" ); + + CloseSplashScreen(); +} + +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 ) + osl_removeSignalHandler( 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; + + osl_getExecutableFile( &aProductKey.pData ); + 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_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Recovery/")); + static const ::rtl::OUString CFG_PATH_CRASHREPORTER(RTL_CONSTASCII_USTRINGPARAM("CrashReporter")); + static const ::rtl::OUString CFG_ENTRY_ENABLED(RTL_CONSTASCII_USTRINGPARAM("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_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Recovery/")); + static const ::rtl::OUString CFG_PATH_SESSION(RTL_CONSTASCII_USTRINGPARAM("SessionShutdown")); + static const ::rtl::OUString CFG_ENTRY_UIENABLED(RTL_CONSTASCII_USTRINGPARAM("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_CONSTASCII_USTRINGPARAM("com.sun.star.frame.AutoRecovery")); + static const ::rtl::OUString PROP_CRASHED(RTL_CONSTASCII_USTRINGPARAM("Crashed")); + static const ::rtl::OUString PROP_EXISTSRECOVERY(RTL_CONSTASCII_USTRINGPARAM("ExistsRecoveryData")); + static const ::rtl::OUString PROP_EXISTSSESSION(RTL_CONSTASCII_USTRINGPARAM("ExistsSessionData")); + static const ::rtl::OUString CFG_PACKAGE_RECOVERY(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Recovery/")); + static const ::rtl::OUString CFG_PATH_RECOVERYINFO(RTL_CONSTASCII_USTRINGPARAM("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_CONSTASCII_USTRINGPARAM("com.sun.star.comp.svx.RecoveryUI")); + static ::rtl::OUString SERVICENAME_URLPARSER(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer")); + static ::rtl::OUString COMMAND_EMERGENCYSAVE(RTL_CONSTASCII_USTRINGPARAM("vnd.sun.star.autorecovery:/doEmergencySave")); + static ::rtl::OUString COMMAND_RECOVERY(RTL_CONSTASCII_USTRINGPARAM("vnd.sun.star.autorecovery:/doAutoRecovery")); + static ::rtl::OUString COMMAND_CRASHREPORT(RTL_CONSTASCII_USTRINGPARAM("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 ) + osl_removeSignalHandler( pSignalHandler ); + + restartOnMac(false); + if ( m_rSplashScreen.is() ) + m_rSplashScreen->reset(); + + _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 ); +} + +namespace { + void SetDocumentExtendedStyle( const Reference< ::com::sun::star::awt::XWindow > &xContainerWindow ) + { + // 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!" ); + if (!pContainerWindow) { + fprintf (stderr, "Error: It very much looks as if you have used 'linkoo' (or bin/ooinstall -l)\n" + "but have then forgotten to source 'ooenv' into your shell before running !\n" + "to save a crash, we will exit now with an error - please '. ./ooenv' first.\n"); + exit (1); + } + pContainerWindow->SetExtendedStyle( pContainerWindow->GetExtendedStyle() | WB_EXT_DOCUMENT ); + } +} + +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" ); + + SetSplashScreenProgress(10); + { + 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(20); + } + + 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(25); + +#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(30); + + // 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(35); + 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; + + Migration::migrateSettingsIfNecessary(); + + // keep a language options instance... + pLanguageOptions.reset( new SvtLanguageOptions(sal_True)); + + if (xGlobalBroadcaster.is()) + { + css::document::EventObject aEvent; + aEvent.EventName = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("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()) + { + SetDocumentExtendedStyle(xContainerWindow); + 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(RTL_CONSTASCII_USTRINGPARAM("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); + if ( m_rSplashScreen.is() ) + m_rSplashScreen->reset(); + + // 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::shouldLaunchQuickstart() +{ + sal_Bool bQuickstart = GetCommandLineArgs()->IsQuickstart(); + if (!bQuickstart) + { + const SfxPoolItem* pItem=0; + SfxItemSet aQLSet(SFX_APP()->GetPool(), SID_ATTR_QUICKLAUNCHER, SID_ATTR_QUICKLAUNCHER); + SFX_APP()->GetOptions(aQLSet); + SfxItemState eState = aQLSet.GetItemState(SID_ATTR_QUICKLAUNCHER, FALSE, &pItem); + if (SFX_ITEM_SET == eState) + bQuickstart = ((SfxBoolItem*)pItem)->GetValue(); + } + return bQuickstart; +} + + +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 = shouldLaunchQuickstart(); + + // 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 + { + Sequence< Any > aSeq( 1 ); + aSeq[0] <<= bQuickstart; + 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); + + SvtMenuOptions aMenuOpt; + hStyleSettings.SetUseImagesInMenus(aMenuOpt.GetMenuIconsState()); + + 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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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; + + osl_getExecutableFile( &aIniName.pData ); + 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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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 ); + pArgs->GetConversionList( aRequest.aConversionList ); + pArgs->GetConversionParams( aRequest.aConversionParams ); + pArgs->GetConversionOut( aRequest.aConversionOut ); + pArgs->GetInFilter( aRequest.aInFilter ); + + 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 ) || + aRequest.aConversionList.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 ) && + !pCmdLine->GetConversionList( 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" )); + + // Which splash to use + OUString aSplashService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.office.SplashScreen" )); + if ( pCmdLine->GetStringParam( CommandLineArgs::CMD_STRINGPARAM_SPLASHPIPE ).getLength() ) + aSplashService = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.office.PipeSplashScreen")); + + bVisible = sal_True; + Sequence< Any > aSeq( 2 ); + aSeq[0] <<= bVisible; + aSeq[1] <<= aAppName; + m_rSplashScreen = Reference<XStatusIndicator>( + comphelper::getProcessServiceFactory()->createInstanceWithArguments( + aSplashService, aSeq), UNO_QUERY); + + if(m_rSplashScreen.is()) + m_rSplashScreen->start(OUString(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.task.JobExecutor")) ), UNO_QUERY ); + if( xExecutor.is() ) + xExecutor->trigger( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("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_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.Common/Misc")); + const ::rtl::OUString sFirstRunNodeName(RTL_CONSTASCII_USTRINGPARAM("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(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/appfirststart.cxx b/desktop/source/app/appfirststart.cxx new file mode 100644 index 000000000000..6e6b4c32c7d8 --- /dev/null +++ b/desktop/source/app/appfirststart.cxx @@ -0,0 +1,320 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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; + rtl::OString aMgrName = rtl::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( 1 ); + sal_Bool bQuickstart = shouldLaunchQuickstart(); + aSeq[0] <<= bQuickstart; + + 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 + } + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/appinit.cxx b/desktop/source/app/appinit.cxx new file mode 100644 index 000000000000..c33e7c0077ce --- /dev/null +++ b/desktop/source/app/appinit.cxx @@ -0,0 +1,464 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 <osl/security.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 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; + osl::Security().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(); + + + // 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 (...) + { + } + } + } + } 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 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/appinit.hxx b/desktop/source/app/appinit.hxx new file mode 100644 index 000000000000..01aa78857b2a --- /dev/null +++ b/desktop/source/app/appinit.hxx @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/appsys.cxx b/desktop/source/app/appsys.cxx new file mode 100644 index 000000000000..61948550ca78 --- /dev/null +++ b/desktop/source/app/appsys.cxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/appsys.hxx b/desktop/source/app/appsys.hxx new file mode 100644 index 000000000000..2dad7b5d7103 --- /dev/null +++ b/desktop/source/app/appsys.hxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/check_ext_deps.cxx b/desktop/source/app/check_ext_deps.cxx new file mode 100644 index 000000000000..bfc0197b3a7e --- /dev/null +++ b/desktop/source/app/check_ext_deps.cxx @@ -0,0 +1,434 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 ) ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/checkinstall.cxx b/desktop/source/app/checkinstall.cxx new file mode 100644 index 000000000000..ee5c96b8c7b6 --- /dev/null +++ b/desktop/source/app/checkinstall.cxx @@ -0,0 +1,121 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/checkinstall.hxx b/desktop/source/app/checkinstall.hxx new file mode 100644 index 000000000000..f37d5ee7eac4 --- /dev/null +++ b/desktop/source/app/checkinstall.hxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/cmdlineargs.cxx b/desktop/source/app/cmdlineargs.cxx new file mode 100644 index 000000000000..841f55ce5e1b --- /dev/null +++ b/desktop/source/app/cmdlineargs.cxx @@ -0,0 +1,1005 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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; + sal_Bool bConversionEvent= sal_False; + sal_Bool bConversionParamsEvent= sal_False; + sal_Bool bBatchPrintEvent= sal_False; + sal_Bool bBatchPrinterNameEvent= sal_False; + sal_Bool bConversionOutEvent = 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 ( aArgStr.EqualsIgnoreCaseAscii( "-convert-to" ) ) + { + bOpenEvent = sal_False; + bConversionEvent = sal_True; + bConversionParamsEvent = sal_True; + } + else if ( aArgStr.EqualsIgnoreCaseAscii( "-print-to-file" ) ) + { + bOpenEvent = sal_False; + bBatchPrintEvent = sal_True; + } + else if ( aArgStr.EqualsIgnoreCaseAscii( "-printer-name" ) && + bBatchPrintEvent ) + { + bBatchPrinterNameEvent = sal_True; + } + else if ( aArgStr.EqualsIgnoreCaseAscii( "-outdir" ) && + (bConversionEvent || bBatchPrintEvent) ) + { + bConversionOutEvent = sal_True; + } + } + else + { + if ( bPrinterName && bPrintToEvent ) + { + // first argument after "-pt" this must be the printer name + AddStringListParam_Impl( CMD_STRINGPARAM_PRINTERNAME, aArgStr ); + bPrinterName = sal_False; + } + else if ( bConversionParamsEvent && bConversionEvent ) + { + // first argument must be the the params + AddStringListParam_Impl( CMD_STRINGPARAM_CONVERSIONPARAMS, aArgStr ); + bConversionParamsEvent = sal_False; + } + else if ( bBatchPrinterNameEvent && bBatchPrintEvent ) + { + // first argument is the printer name + AddStringListParam_Impl( CMD_STRINGPARAM_PRINTERNAME, aArgStr ); + bBatchPrinterNameEvent = sal_False; + } + else if ( (bConversionEvent || bBatchPrintEvent) && bConversionOutEvent ) + { + AddStringListParam_Impl( CMD_STRINGPARAM_CONVERSIONOUT, aArgStr ); + bConversionOutEvent = sal_False; + } + else + { + if( bOpenEvent || bViewEvent || bForceNewEvent || bForceOpenEvent ) + { + if( ::rtl::OUString(aArgStr).matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("::ODMA")) ) + { + ::rtl::OUString sArg = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("vnd.sun.star.odma:/")); + sArg += aArgStr; + aArgStr = sArg; + } + } + // 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 + } + else if ( bConversionEvent || bBatchPrintEvent ) + AddStringListParam_Impl( CMD_STRINGPARAM_CONVERSIONLIST, aArgStr ); + } + } + } + } + } +} + +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(ENABLE_QUICKSTART_APPLET) + 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; + } + else if ( aArgStr.Copy(0, 13).EqualsIgnoreCaseAscii( "-splash-pipe=" )) + { + AddStringListParam_Impl( CMD_STRINGPARAM_SPLASHPIPE, aArgStr.Copy( 13 ) ); + 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, 10).EqualsIgnoreCaseAscii( "-infilter=" )) + { + AddStringListParam_Impl( CMD_STRINGPARAM_INFILTER, aArgStr.Copy( 10 ) ); + return sal_True; + } + 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; +} + +const rtl::OUString& CommandLineArgs::GetStringParam( StringParam eParam ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + + OSL_ASSERT( ( eParam >= 0 && eParam < CMD_STRINGPARAM_COUNT ) ); + return m_aStrParams[eParam]; +} + +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::GetInFilter( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_INFILTER ]; + return m_aStrSetParams[ CMD_STRINGPARAM_INFILTER ]; +} + +sal_Bool CommandLineArgs::GetConversionList( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_CONVERSIONLIST ]; + return m_aStrSetParams[ CMD_STRINGPARAM_CONVERSIONLIST ]; +} + +sal_Bool CommandLineArgs::GetConversionParams( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_CONVERSIONPARAMS ]; + return m_aStrSetParams[ CMD_STRINGPARAM_CONVERSIONPARAMS ]; +} +sal_Bool CommandLineArgs::GetConversionOut( ::rtl::OUString& rPara ) const +{ + osl::MutexGuard aMutexGuard( m_aMutex ); + rPara = m_aStrParams[ CMD_STRINGPARAM_CONVERSIONOUT ]; + return m_aStrSetParams[ CMD_STRINGPARAM_CONVERSIONOUT ]; +} + + + +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_SPLASHPIPE ].getLength() )) || + ( ( m_eArgumentCount == ONE ) && ( m_aStrParams[ CMD_STRINGPARAM_ACCEPT ].getLength() )) || + ( ( m_eArgumentCount == ONE ) && m_aBoolParams[ CMD_BOOLPARAM_PSN ] ); +} + +} // namespace desktop + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/cmdlineargs.hxx b/desktop/source/app/cmdlineargs.hxx new file mode 100644 index 000000000000..05b31f40ec03 --- /dev/null +++ b/desktop/source/app/cmdlineargs.hxx @@ -0,0 +1,226 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_SPLASHPIPE, + 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_CONVERSIONLIST, + CMD_STRINGPARAM_CONVERSIONPARAMS, + CMD_STRINGPARAM_CONVERSIONOUT, + CMD_STRINGPARAM_INFILTER, + 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 ); + + const rtl::OUString& GetStringParam( StringParam eParam ) const; + + // 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; + sal_Bool GetInFilter( ::rtl::OUString& rPara ) const; + sal_Bool GetConversionList( ::rtl::OUString& rPara ) const; + sal_Bool GetConversionParams( ::rtl::OUString& rPara ) const; + sal_Bool GetConversionOut( ::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 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/cmdlinehelp.cxx b/desktop/source/app/cmdlinehelp.cxx new file mode 100644 index 000000000000..110aa3e73124 --- /dev/null +++ b/desktop/source/app/cmdlinehelp.cxx @@ -0,0 +1,189 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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\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"\ + "-infilter=<filter>\n"\ + " Force an input filter type if possible\n"\ + " Eg. -infilter=\"Calc Office Open XML\"\n"\ + "-convert-to output_file_extension[:output_filter_name] [-outdir ouput_dir] files\n"\ + " Batch convert files.\n"\ + " If -outdir is not specified then current working dir is used as output_dir.\n"\ + " Eg. -convert-to pdf *.doc\n"\ + " -convert-to pdf:writer_pdf_Export -outdir /home/user *.doc\n"\ + "-print-to-file [-printer-name printer_name] [-outdir ouput_dir] files\n"\ + " Batch print files to file.\n"\ + " If -outdir is not specified then current working dir is used as output_dir.\n"\ + " Eg. -print-to-file *.doc\n"\ + " -print-to-file -printer-name nasty_lowres_printer -outdir /home/user *.doc\n"\ + "\nRemaining 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 +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/cmdlinehelp.hxx b/desktop/source/app/cmdlinehelp.hxx new file mode 100644 index 000000000000..823e7b4d9f77 --- /dev/null +++ b/desktop/source/app/cmdlinehelp.hxx @@ -0,0 +1,24 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#include <vcl/dialog.hxx> +#include <vcl/fixed.hxx> +#include <vcl/button.hxx> + +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 +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/configinit.cxx b/desktop/source/app/configinit.cxx new file mode 100644 index 000000000000..3704d842c39d --- /dev/null +++ b/desktop/source/app/configinit.cxx @@ -0,0 +1,305 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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; +} +//------------------------------------------------------------------------------ + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/configinit.hxx b/desktop/source/app/configinit.hxx new file mode 100644 index 000000000000..8254f4111827 --- /dev/null +++ b/desktop/source/app/configinit.hxx @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#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 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/copyright_ascii_ooo.c b/desktop/source/app/copyright_ascii_ooo.c new file mode 100644 index 000000000000..b35aa2cee929 --- /dev/null +++ b/desktop/source/app/copyright_ascii_ooo.c @@ -0,0 +1,12 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + + /* + * 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."; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/copyright_ascii_sun.c b/desktop/source/app/copyright_ascii_sun.c new file mode 100644 index 000000000000..a94966855e1e --- /dev/null +++ b/desktop/source/app/copyright_ascii_sun.c @@ -0,0 +1,10 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + + /* + * 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."; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/desktop.hrc b/desktop/source/app/desktop.hrc new file mode 100644 index 000000000000..035318b4d7d5 --- /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..e333c441817b --- /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..73038d30f7c8 --- /dev/null +++ b/desktop/source/app/desktopcontext.cxx @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/desktopcontext.hxx b/desktop/source/app/desktopcontext.hxx new file mode 100644 index 000000000000..f0ac41c87ac4 --- /dev/null +++ b/desktop/source/app/desktopcontext.hxx @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/desktopresid.cxx b/desktop/source/app/desktopresid.cxx new file mode 100644 index 000000000000..347ee542a306 --- /dev/null +++ b/desktop/source/app/desktopresid.cxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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() ) +{ +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/desktopresid.hxx b/desktop/source/app/desktopresid.hxx new file mode 100644 index 000000000000..689a0f11da1c --- /dev/null +++ b/desktop/source/app/desktopresid.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/dispatchwatcher.cxx b/desktop/source/app/dispatchwatcher.cxx new file mode 100644 index 000000000000..7701bbae4827 --- /dev/null +++ b/desktop/source/app/dispatchwatcher.cxx @@ -0,0 +1,681 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 <sfx2/docfile.hxx> +#include <sfx2/docfilt.hxx> +#include <sfx2/fcontnr.hxx> +#include "osl/file.hxx" +#include <svl/fstathelper.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 <com/sun/star/frame/XStorable.hpp> + +#include <tools/urlobj.hxx> +#include <comphelper/mediadescriptor.hxx> + +#include <vector> +#include <osl/thread.hxx> + +using ::rtl::OUString; +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; +}; + +static String impl_GetFilterFromExt( OUString aUrl, SfxFilterFlags nFlags, + String aAppl ) +{ + String aFilter; + SfxMedium* pMedium = new SfxMedium( aUrl, + STREAM_STD_READ, FALSE ); + const SfxFilter *pSfxFilter = NULL; + SfxFilterMatcher aMatcher; + if( nFlags == SFX_FILTER_EXPORT ) + aMatcher = SfxFilterMatcher( aAppl ); + aMatcher.GuessFilterIgnoringContent( *pMedium, &pSfxFilter, nFlags, 0 ); + if( pSfxFilter ) + aFilter = ( nFlags == SFX_FILTER_EXPORT ) ? pSfxFilter->GetFilterName() : + pSfxFilter->GetServiceName(); + + delete pMedium; + return aFilter; +} +static OUString impl_GuessFilter( OUString aUrlIn, OUString aUrlOut ) +{ + /* aAppl can also be set to Factory like scalc, swriter... */ + String aAppl; + aAppl = impl_GetFilterFromExt( aUrlIn, SFX_FILTER_IMPORT, aAppl ); + return impl_GetFilterFromExt( aUrlOut, SFX_FILTER_EXPORT, aAppl ); +} + +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")); + sal_Bool bSetInputFilter = sal_False; + ::rtl::OUString aForcedInputFilter; + + for ( p = aDispatchRequestsList.begin(); p != aDispatchRequestsList.end(); p++ ) + { + const DispatchRequest& aDispatchRequest = *p; + + // create parameter array + sal_Int32 nCount = 4; + if ( aDispatchRequest.aPreselectedFactory.getLength() ) + nCount++; + + // Set Input Filter + if ( aDispatchRequest.aRequestType == REQUEST_INFILTER ) + { + bSetInputFilter = sal_True; + aForcedInputFilter = aDispatchRequest.aURL; + OfficeIPCThread::RequestsCompleted( 1 ); + continue; + } + + // we need more properties for a print/print to request + if ( aDispatchRequest.aRequestType == REQUEST_PRINT || + aDispatchRequest.aRequestType == REQUEST_PRINTTO || + aDispatchRequest.aRequestType == REQUEST_BATCHPRINT || + aDispatchRequest.aRequestType == REQUEST_CONVERSION) + nCount++; + + Sequence < PropertyValue > aArgs( nCount ); + + // mark request as user interaction from outside + aArgs[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Referer")); + aArgs[0].Value <<= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:OpenEvent")); + + if ( aDispatchRequest.aRequestType == REQUEST_PRINT || + aDispatchRequest.aRequestType == REQUEST_PRINTTO || + aDispatchRequest.aRequestType == REQUEST_BATCHPRINT || + aDispatchRequest.aRequestType == REQUEST_CONVERSION) + { + aArgs[1].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ReadOnly")); + aArgs[2].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OpenNewView")); + aArgs[3].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Hidden")); + aArgs[4].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Silent")); + } + else + { + Reference < com::sun::star::task::XInteractionHandler > xInteraction( + ::comphelper::getProcessServiceFactory()->createInstance( OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.task.InteractionHandler")) ), + com::sun::star::uno::UNO_QUERY ); + + aArgs[1].Name = OUString(RTL_CONSTASCII_USTRINGPARAM( "InteractionHandler" )); + aArgs[1].Value <<= xInteraction; + + sal_Int16 nMacroExecMode = ::com::sun::star::document::MacroExecMode::USE_CONFIG; + aArgs[2].Name = OUString(RTL_CONSTASCII_USTRINGPARAM( "MacroExecutionMode" )); + aArgs[2].Value <<= nMacroExecMode; + + sal_Int16 nUpdateDoc = ::com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG; + aArgs[3].Name = OUString(RTL_CONSTASCII_USTRINGPARAM( "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 || + aDispatchRequest.aRequestType == REQUEST_BATCHPRINT || + aDispatchRequest.aRequestType == REQUEST_CONVERSION) + { + // 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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM( + "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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("StartPresentation")); + aArgs[nIndex].Value <<= sal_True; + } + + // Force input filter, if possible + if( bSetInputFilter ) + { + sal_Int32 nIndex = aArgs.getLength(); + aArgs.realloc(nIndex+1); + aArgs[nIndex].Name = OUString(RTL_CONSTASCII_USTRINGPARAM("FilterName")); + aArgs[nIndex].Value <<= aForcedInputFilter; + } + + // 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(RTL_CONSTASCII_USTRINGPARAM( + "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(RTL_CONSTASCII_USTRINGPARAM( + "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 || + aDispatchRequest.aRequestType == REQUEST_BATCHPRINT || + aDispatchRequest.aRequestType == REQUEST_CONVERSION ) + { + if ( xDoc.is() ) + { + if ( aDispatchRequest.aRequestType == REQUEST_CONVERSION ) { + Reference< XStorable > xStorable( xDoc, UNO_QUERY ); + if ( xStorable.is() ) { + rtl::OUString aParam = aDispatchRequest.aPrinterName; + sal_Int32 nPathIndex = aParam.lastIndexOfAsciiL( ";", 1 ); + sal_Int32 nFilterIndex = aParam.indexOfAsciiL( ":", 1 ); + if( nPathIndex < nFilterIndex ) + nFilterIndex = -1; + rtl::OUString aFilterOut=aParam.copy( nPathIndex+1 ); + rtl::OUString aFilter; + rtl::OUString aFilterExt; + sal_Bool bGuess = sal_False; + + if( nFilterIndex >= 0 ) + { + aFilter = aParam.copy( nFilterIndex+1, nPathIndex-nFilterIndex-1 ); + aFilterExt = aParam.copy( 0, nFilterIndex ); + } + else + { + // Guess + bGuess = sal_True; + aFilterExt = aParam.copy( 0, nPathIndex ); + } + INetURLObject aOutFilename( aObj ); + aOutFilename.SetExtension( aFilterExt ); + FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut ); + rtl::OUString aOutFile = aFilterOut+ + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "/" ))+ + aOutFilename.getName(); + //FileBase::getFileURLFromSystemPath( aOutFile, aOutFile ); + + if ( bGuess ) + { + aFilter = impl_GuessFilter( aName, aOutFile ); + } + + Sequence<PropertyValue> conversionProperties( 2 ); + conversionProperties[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Overwrite" )); + conversionProperties[0].Value <<= sal_True; + + conversionProperties[1].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "FilterName" )); + conversionProperties[1].Value <<= aFilter; + + rtl::OUString aTempName; + FileBase::getSystemPathFromFileURL( aName, aTempName ); + rtl::OString aSource8 = ::rtl::OUStringToOString ( aTempName, RTL_TEXTENCODING_UTF8 ); + FileBase::getSystemPathFromFileURL( aOutFile, aTempName ); + rtl::OString aTargetURL8 = ::rtl::OUStringToOString(aTempName, RTL_TEXTENCODING_UTF8 ); + printf("convert %s -> %s using %s\n", aSource8.getStr(), aTargetURL8.getStr(), + ::rtl::OUStringToOString( aFilter, RTL_TEXTENCODING_UTF8 ).getStr()); + if( FStatHelper::IsDocument(aOutFile) ) + printf("Overwriting: %s\n",::rtl::OUStringToOString( aTempName, RTL_TEXTENCODING_UTF8 ).getStr() ); + try + { + xStorable->storeToURL( aOutFile, conversionProperties ); + } + catch ( Exception& ) + { + fprintf( stderr, "Error: Please reverify input parameters...\n" ); + } + } + } else if ( aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ) { + rtl::OUString aParam = aDispatchRequest.aPrinterName; + sal_Int32 nPathIndex = aParam.lastIndexOfAsciiL( ";", 1 ); + + rtl::OUString aFilterOut; + rtl::OUString aPrinterName; + if( nPathIndex != -1 ) + aFilterOut=aParam.copy( nPathIndex+1 ); + if( nPathIndex != 0 ) + aPrinterName=aParam.copy( 0, nPathIndex ); + + INetURLObject aOutFilename( aObj ); + aOutFilename.SetExtension( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ps")) ); + FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut ); + rtl::OUString aOutFile = aFilterOut+ + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "/" ))+ + aOutFilename.getName(); + + rtl::OUString aTempName; + FileBase::getSystemPathFromFileURL( aName, aTempName ); + rtl::OString aSource8 = ::rtl::OUStringToOString ( aTempName, RTL_TEXTENCODING_UTF8 ); + FileBase::getSystemPathFromFileURL( aOutFile, aTempName ); + rtl::OString aTargetURL8 = ::rtl::OUStringToOString(aTempName, RTL_TEXTENCODING_UTF8 ); + printf("print %s -> %s using %s\n", aSource8.getStr(), aTargetURL8.getStr(), + aPrinterName.getLength() ? + ::rtl::OUStringToOString( aPrinterName, RTL_TEXTENCODING_UTF8 ).getStr() : "<default_printer>"); + + // create the custom printer, if given + Sequence < PropertyValue > aPrinterArgs( 1 ); + if( aPrinterName.getLength() ) + { + aPrinterArgs[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Name")); + aPrinterArgs[0].Value <<= aPrinterName; + xDoc->setPrinter( aPrinterArgs ); + } + + // print ( also without user interaction ) + aPrinterArgs.realloc(2); + aPrinterArgs[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FileName")); + aPrinterArgs[0].Value <<= aOutFile; + aPrinterArgs[1].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Wait")); + aPrinterArgs[1].Value <<= ( sal_Bool ) sal_True; + xDoc->print( aPrinterArgs ); + } else { + if ( aDispatchRequest.aRequestType == REQUEST_PRINTTO ) + { + // create the printer + Sequence < PropertyValue > aPrinterArgs( 1 ); + aPrinterArgs[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("Referer")); + aArgs[0].Value <<= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:OpenEvent")); + aArgs[1].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("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(); + } + } +} + +} + + + + + + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/dispatchwatcher.hxx b/desktop/source/app/dispatchwatcher.hxx new file mode 100644 index 000000000000..6dc2d9362cf1 --- /dev/null +++ b/desktop/source/app/dispatchwatcher.hxx @@ -0,0 +1,130 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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, + REQUEST_CONVERSION, + REQUEST_INFILTER, + REQUEST_BATCHPRINT + }; + + 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; // also conversion params + 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 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 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..e3563606082a --- /dev/null +++ b/desktop/source/app/langselect.cxx @@ -0,0 +1,561 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("UILocale")), makeAny(aLocaleString)); + Reference< XChangesBatch >(xProp2, UNO_QUERY_THROW)->commitChanges(); + } + + MsLangId::setConfiguredSystemUILanguage( MsLangId::convertLocaleToLanguage(loc) ); + + OUString sLocale; + xProp->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationProvider")); + OUString sAccessSrvc; + if (bUpdate) + sAccessSrvc = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationUpdateAccess")); + else + sAccessSrvc = OUString(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("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 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/langselect.hxx b/desktop/source/app/langselect.hxx new file mode 100644 index 000000000000..6db4f5bc24b1 --- /dev/null +++ b/desktop/source/app/langselect.hxx @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/lockfile.cxx b/desktop/source/app/lockfile.cxx new file mode 100644 index 000000000000..db23c7db195a --- /dev/null +++ b/desktop/source/app/lockfile.cxx @@ -0,0 +1,240 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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> +#else +#include <unistd.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; + + +static rtl::OString impl_getHostname() +{ + rtl::OString 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 + /* Don't do dns lookup on Linux either */ + sal_Char pHostName[1024]; + + if ( gethostname( pHostName, sizeof( pHostName ) - 1 ) == 0 ) + { + pHostName[sizeof( pHostName ) - 1] = '\0'; + aHost = OString( pHostName ); + } + else + aHost = OString("UNKNOWN"); +#endif + + return aHost; +} + +namespace desktop { + + 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 + LOCKFILE_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(LOCKFILE_GROUP); + ByteString aIPCserver = aConfig.ReadKey( LOCKFILE_IPCKEY ); + if (! aIPCserver.EqualsIgnoreCaseAscii( "true" )) + return false; + + ByteString aHost = aConfig.ReadKey( LOCKFILE_HOSTKEY ); + ByteString aUser = aConfig.ReadKey( LOCKFILE_USERKEY ); + + // lockfile from same host? + ByteString myHost( impl_getHostname() ); + 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(LOCKFILE_GROUP); + + // get information + ByteString aHost( impl_getHostname() ); + 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( LOCKFILE_USERKEY, aUser ); + aConfig.WriteKey( LOCKFILE_HOSTKEY, aHost ); + aConfig.WriteKey( LOCKFILE_STAMPKEY, aStamp ); + aConfig.WriteKey( LOCKFILE_TIMEKEY, aTime ); + aConfig.WriteKey( + LOCKFILE_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 ); + } +} + + + + + + + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/lockfile.hxx b/desktop/source/app/lockfile.hxx new file mode 100644 index 000000000000..0d286e13cafb --- /dev/null +++ b/desktop/source/app/lockfile.hxx @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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; + +#define LOCKFILE_SUFFIX rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/.lock" ) ) +#define LOCKFILE_GROUP ByteString( "Lockdata" ) +#define LOCKFILE_USERKEY ByteString( "User" ) +#define LOCKFILE_HOSTKEY ByteString( "Host" ) +#define LOCKFILE_STAMPKEY ByteString( "Stamp" ) +#define LOCKFILE_TIMEKEY ByteString( "Time" ) +#define LOCKFILE_IPCKEY ByteString( "IPCServer" ) + +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: + 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 ); + + }; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/lockfile2.cxx b/desktop/source/app/lockfile2.cxx new file mode 100644 index 000000000000..9f61c563fd4b --- /dev/null +++ b/desktop/source/app/lockfile2.cxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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( LOCKFILE_GROUP ); + ByteString aHost = aConfig.ReadKey( LOCKFILE_HOSTKEY ); + ByteString aUser = aConfig.ReadKey( LOCKFILE_USERKEY ); + ByteString aStamp = aConfig.ReadKey( LOCKFILE_STAMPKEY ); + ByteString aTime = aConfig.ReadKey( LOCKFILE_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; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/main.c b/desktop/source/app/main.c new file mode 100644 index 000000000000..198e42a0caf1 --- /dev/null +++ b/desktop/source/app/main.c @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/makefile.mk b/desktop/source/app/makefile.mk new file mode 100644 index 000000000000..e7c30a2ca70f --- /dev/null +++ b/desktop/source/app/makefile.mk @@ -0,0 +1,119 @@ +#************************************************************************* +# +# 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 + +.IF "$(GUI)"=="WNT" || "$(GUI)"=="OS2" || "$(GUIBASE)"=="aqua" || "$(ENABLE_SYSTRAY_GTK)"=="TRUE" +CFLAGS+=-DENABLE_QUICKSTART_APPLET +.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) \ + +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..c685596d2626 --- /dev/null +++ b/desktop/source/app/officeipcthread.cxx @@ -0,0 +1,1057 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 <osl/process.h> +#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 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<osl::Security, Security> {}; } +::osl::Mutex* OfficeIPCThread::pOfficeIPCThreadMutex = 0; + +// Turns a string in aMsg such as file://home/foo/.libreoffice/3 +// Into a hex string of well known length ff132a86... +String CreateMD5FromString( const OUString& aMsg ) +{ +#if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL + fprintf (stderr, "create md5 frim '%s'\n", + (const sal_Char *)rtl::OUStringToOString (aMsg, RTL_TEXTENCODING_UTF8)); +#endif + + 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 ); +} + +oslSignalAction SAL_CALL SalMainPipeExchangeSignal_impl(void* /*pData*/, oslSignalInfo* pInfo) +{ + if( pInfo->Signal == osl_Signal_Terminate ) + OfficeIPCThread::DisableOfficeIPCThread(); + return osl_Signal_ActCallNextHdl; +} + +// ---------------------------------------------------------------------------- + +// 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; + + 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; + + osl_getExecutableFile( &aIniName.pData ); + + 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 + { + osl::Security &rSecurity = Security::get(); + // Try to create pipe + if ( pThread->maPipe.create( pThread->maPipeIdent.getStr(), osl_Pipe_CREATE, rSecurity )) + { + // Pipe created + nPipeMode = PIPEMODE_CREATED; + } + else if( pThread->maPipe.create( pThread->maPipeIdent.getStr(), osl_Pipe_OPEN, rSecurity )) // Creation not successfull, now we try to connect + { + // Pipe connected to first office + nPipeMode = PIPEMODE_CONNECTED; + } + else + { + oslPipeError eReason = pThread->maPipe.getError(); + if ((eReason == osl_Pipe_E_ConnectionRefused) || (eReason == osl_Pipe_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 + osl::StreamPipe aStreamPipe(pThread->maPipe.getHandle()); + + 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 + aStreamPipe.write( aArguments.GetBuffer(), aArguments.Len() ); + aStreamPipe.write( "\0", 1 ); + + // wait for confirmation #95361# #95425# + ByteString aToken(sc_aConfirmationSequence); + char *aReceiveBuffer = new char[aToken.Len()+1]; + int n = aStreamPipe.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 + osl::StreamPipe aPipe ( pOfficeIPCThread->maPipeIdent, osl_Pipe_OPEN, Security::get() ); + //Pipe.send( TERMINATION_SEQUENCE, TERMINATION_LENGTH ); + if (aPipe.is()) + { + aPipe.send( sc_aTerminationSequence, sc_nTSeqLength+1 ); // also send 0-byte + + // close the pipe so that the streampipe on the other + // side produces EOF + aPipe.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 + { + oslPipeError nError = maPipe.accept( maStreamPipe ); + + + if( nError == osl_Pipe_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; + wait( 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 ); + } +} + +static void AddConversionsToDispatchList( + DispatchWatcher::DispatchList& rDispatchList, + boost::optional< rtl::OUString > const & cwdUrl, + const OUString& rRequestList, + const OUString& rParam, + const OUString& rPrinterName, + const OUString& rFactory, + const OUString& rParamOut ) +{ + DispatchWatcher::RequestType nType; + OUString aParam( rParam ); + + if( rParam.getLength() ) + { + nType = DispatchWatcher::REQUEST_CONVERSION; + aParam = rParam; + } + else + { + nType = DispatchWatcher::REQUEST_BATCHPRINT; + aParam = rPrinterName; + } + + OUString aOutDir( rParamOut.trim() ); + ::rtl::OUString aPWD; + ::tools::getProcessWorkingDir( &aPWD ); + + if( !::osl::FileBase::getAbsoluteFileURL( aPWD, rParamOut, aOutDir ) ) + ::osl::FileBase::getSystemPathFromFileURL( aOutDir, aOutDir ); + + if( rParamOut.trim().getLength() ) + { + aParam += ::rtl::OUString::createFromAscii(";"); + aParam += aOutDir; + } + else + { + ::osl::FileBase::getSystemPathFromFileURL( aPWD, aPWD ); + aParam += ::rtl::OUString::createFromAscii( ";" ) + aPWD; + } + + if ( rRequestList.getLength() > 0 ) + { + sal_Int32 nIndex = 0; + do + { + OUString aToken = rRequestList.getToken( 0, APPEVENT_PARAM_DELIMITER, nIndex ); + if ( aToken.getLength() > 0 ) + rDispatchList.push_back( + DispatchWatcher::DispatchRequest( nType, aToken, cwdUrl, aParam, rFactory )); + } + 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.aInFilter, DispatchWatcher::REQUEST_INFILTER, aEmpty, aRequest.aModule ); + 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 ); + AddConversionsToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aConversionList, aRequest.aConversionParams, aRequest.aPrinterName, aRequest.aModule, aRequest.aConversionOut ); + 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; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/officeipcthread.hxx b/desktop/source/app/officeipcthread.hxx new file mode 100644 index 000000000000..f075aec313f2 --- /dev/null +++ b/desktop/source/app/officeipcthread.hxx @@ -0,0 +1,167 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 <osl/pipe.hxx> +#include <osl/security.hxx> +#include <osl/signal.h> +#include <rtl/ustring.hxx> +#include <cppuhelper/implbase2.hxx> +#include <osl/conditn.hxx> +#include <osl/thread.hxx> +#include "boost/optional.hpp" + +namespace desktop +{ + +oslSignalAction SAL_CALL SalMainPipeExchangeSignal_impl(void* /*pData*/, oslSignalInfo* 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 + ::rtl::OUString aConversionList; + ::rtl::OUString aConversionParams; + ::rtl::OUString aConversionOut; + ::rtl::OUString aInFilter; + ::osl::Condition *pcProcessed; // pointer condition to be set when the request has been processed +}; + +class DispatchWatcher; +class OfficeIPCThread : public osl::Thread +{ + private: + static OfficeIPCThread* pGlobalOfficeIPCThread; + static ::osl::Mutex* pOfficeIPCThreadMutex; + + osl::Pipe maPipe; + osl::StreamPipe 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_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/omutexmember.hxx b/desktop/source/app/omutexmember.hxx new file mode 100644 index 000000000000..4e33e1313da9 --- /dev/null +++ b/desktop/source/app/omutexmember.hxx @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/sofficemain.cxx b/desktop/source/app/sofficemain.cxx new file mode 100644 index 000000000000..b7d190c845e1 --- /dev/null +++ b/desktop/source/app/sofficemain.cxx @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/sofficemain.h b/desktop/source/app/sofficemain.h new file mode 100644 index 000000000000..5b07bb4684ed --- /dev/null +++ b/desktop/source/app/sofficemain.h @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/userinstall.cxx b/desktop/source/app/userinstall.cxx new file mode 100644 index 000000000000..ca68ab00ad9d --- /dev/null +++ b/desktop/source/app/userinstall.cxx @@ -0,0 +1,299 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 <osl/security.hxx> +#include <rtl/ref.hxx> + +#include <tools/resmgr.hxx> +#include <unotools/bootstrap.hxx> +#include <svl/languageoptions.hxx> +#include <unotools/syslocaleoptions.hxx> +#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 rtl::OString; +using rtl::OUString; +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; + + } +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/userinstall.hxx b/desktop/source/app/userinstall.hxx new file mode 100644 index 000000000000..67b4f0081a87 --- /dev/null +++ b/desktop/source/app/userinstall.hxx @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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(); +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/app/version.map b/desktop/source/app/version.map new file mode 100644 index 000000000000..ad52c57cc1cb --- /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: + *; +}; diff --git a/desktop/source/deployment/dp_log.cxx b/desktop/source/deployment/dp_log.cxx new file mode 100644 index 000000000000..bb58770c4cdb --- /dev/null +++ b/desktop/source/deployment/dp_log.cxx @@ -0,0 +1,213 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_misc.h" +#include "rtl/strbuf.hxx" +#include "osl/time.h" +#include "osl/thread.h" +#include "cppuhelper/compbase1.hxx" +#include "comphelper/anytostring.hxx" +#include "comphelper/servicedecl.hxx" +#include "comphelper/unwrapargs.hxx" +#include "com/sun/star/deployment/DeploymentException.hpp" +#include "com/sun/star/ucb/XProgressHandler.hpp" +#include "com/sun/star/ucb/XSimpleFileAccess.hpp" +#include "com/sun/star/io/XSeekable.hpp" +#include <stdio.h> + + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace dp_log { + +typedef ::cppu::WeakComponentImplHelper1<ucb::XProgressHandler> t_log_helper; + +//============================================================================== +class ProgressLogImpl : public ::dp_misc::MutexHolder, public t_log_helper +{ + Reference<io::XOutputStream> m_xLogFile; + sal_Int32 m_log_level; + void log_write( OString const & text ); + +protected: + virtual void SAL_CALL disposing(); + virtual ~ProgressLogImpl(); + +public: + ProgressLogImpl( Sequence<Any> const & args, + Reference<XComponentContext> const & xContext ); + + // XProgressHandler + virtual void SAL_CALL push( Any const & Status ) throw (RuntimeException); + virtual void SAL_CALL update( Any const & Status ) throw (RuntimeException); + virtual void SAL_CALL pop() throw (RuntimeException); +}; + +//______________________________________________________________________________ +ProgressLogImpl::~ProgressLogImpl() +{ +} + +//______________________________________________________________________________ +void ProgressLogImpl::disposing() +{ + try { + if (m_xLogFile.is()) { + m_xLogFile->closeOutput(); + m_xLogFile.clear(); + } + } + catch (Exception & exc) { + (void) exc; + OSL_ENSURE( 0, OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + } +} + +//______________________________________________________________________________ +ProgressLogImpl::ProgressLogImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xContext ) + : t_log_helper( getMutex() ), + m_log_level( 0 ) +{ + OUString log_file; + boost::optional< Reference<task::XInteractionHandler> > interactionHandler; + comphelper::unwrapArgs( args, log_file, interactionHandler ); + + Reference<ucb::XSimpleFileAccess> xSimpleFileAccess( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.ucb.SimpleFileAccess"), + xContext ), UNO_QUERY_THROW ); + // optional ia handler: + if (interactionHandler) + xSimpleFileAccess->setInteractionHandler( *interactionHandler ); + + m_xLogFile.set( + xSimpleFileAccess->openFileWrite( log_file ), UNO_QUERY_THROW ); + Reference<io::XSeekable> xSeekable( m_xLogFile, UNO_QUERY_THROW ); + xSeekable->seek( xSeekable->getLength() ); + + // write log stamp + OStringBuffer buf; + buf.append( + RTL_CONSTASCII_STRINGPARAM("###### Progress log entry ") ); + TimeValue m_start_time, tLocal; + oslDateTime date_time; + if (osl_getSystemTime( &m_start_time ) && + osl_getLocalTimeFromSystemTime( &m_start_time, &tLocal ) && + osl_getDateTimeFromTimeValue( &tLocal, &date_time )) + { + char ar[ 128 ]; + snprintf( + ar, sizeof (ar), + "%04d-%02d-%02d %02d:%02d:%02d ", + date_time.Year, date_time.Month, date_time.Day, + date_time.Hours, date_time.Minutes, date_time.Seconds ); + buf.append( ar ); + } + buf.append( RTL_CONSTASCII_STRINGPARAM("######\n") ); + log_write( buf.makeStringAndClear() ); +} + +//______________________________________________________________________________ +void ProgressLogImpl::log_write( OString const & text ) +{ + try { + if (m_xLogFile.is()) { + m_xLogFile->writeBytes( + Sequence< sal_Int8 >( + reinterpret_cast< sal_Int8 const * >(text.getStr()), + text.getLength() ) ); + } + } + catch (io::IOException & exc) { + (void) exc; + OSL_ENSURE( 0, OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + } +} + +// XProgressHandler +//______________________________________________________________________________ +void ProgressLogImpl::push( Any const & Status ) + throw (RuntimeException) +{ + update( Status ); + OSL_ASSERT( m_log_level >= 0 ); + ++m_log_level; +} + +//______________________________________________________________________________ +void ProgressLogImpl::update( Any const & Status ) + throw (RuntimeException) +{ + if (! Status.hasValue()) + return; + + OUStringBuffer buf; + OSL_ASSERT( m_log_level >= 0 ); + for ( sal_Int32 n = 0; n < m_log_level; ++n ) + buf.append( static_cast<sal_Unicode>(' ') ); + + OUString msg; + if (Status >>= msg) { + buf.append( msg ); + } + else { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("ERROR: ") ); + buf.append( ::comphelper::anyToString(Status) ); + } + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\n") ); + log_write( OUStringToOString( + buf.makeStringAndClear(), osl_getThreadTextEncoding() ) ); +} + +//______________________________________________________________________________ +void ProgressLogImpl::pop() throw (RuntimeException) +{ + OSL_ASSERT( m_log_level > 0 ); + --m_log_level; +} + +namespace sdecl = comphelper::service_decl; +sdecl::class_<ProgressLogImpl, sdecl::with_args<true> > servicePLI; +extern sdecl::ServiceDecl const serviceDecl( + servicePLI, + // a private one: + "com.sun.star.comp.deployment.ProgressLog", + "com.sun.star.comp.deployment.ProgressLog" ); + +} // namespace dp_log + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/dp_persmap.cxx b/desktop/source/deployment/dp_persmap.cxx new file mode 100644 index 000000000000..410bb01c1afb --- /dev/null +++ b/desktop/source/deployment/dp_persmap.cxx @@ -0,0 +1,255 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_misc.h" +#include "dp_ucb.h" +#include "dp_persmap.h" +#include "rtl/strbuf.hxx" +#include "rtl/ustrbuf.hxx" +#include "osl/file.hxx" +#include "osl/thread.h" + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::rtl; +using ::osl::File; + +namespace dp_misc +{ + +//______________________________________________________________________________ +void PersistentMap::throw_rtexc( int err, char const * pmsg ) const +{ + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[") ); + buf.append( m_sysPath ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] Berkeley Db error (") ); + buf.append( static_cast<sal_Int32>(err) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("): ") ); + if (pmsg == 0) + pmsg = DbEnv::strerror(err); + const OString msg(pmsg); + buf.append( OUString( msg.getStr(), msg.getLength(), + osl_getThreadTextEncoding() ) ); + const OUString msg_(buf.makeStringAndClear()); + OSL_ENSURE( 0, rtl::OUStringToOString( + msg_, RTL_TEXTENCODING_UTF8 ).getStr() ); + throw RuntimeException( msg_, Reference<XInterface>() ); +} + +//______________________________________________________________________________ +PersistentMap::~PersistentMap() +{ + try { + m_db.close(0); + } + catch (DbException & exc) { + (void) exc; // avoid warnings + OSL_ENSURE( 0, DbEnv::strerror( exc.get_errno() ) ); + } +} + +//______________________________________________________________________________ +PersistentMap::PersistentMap( OUString const & url_, bool readOnly ) + : m_db( 0, 0 ) +{ + try { + OUString url( expandUnoRcUrl(url_) ); + if ( File::getSystemPathFromFileURL( url, m_sysPath ) != File::E_None ) + { + OSL_ASSERT( false ); + } + OString cstr_sysPath( + OUStringToOString( m_sysPath, RTL_TEXTENCODING_UTF8 ) ); + char const * pcstr_sysPath = cstr_sysPath.getStr(); + + u_int32_t flags = DB_CREATE; + if (readOnly) { + flags = DB_RDONLY; + if (! create_ucb_content( + 0, url, + Reference<com::sun::star::ucb::XCommandEnvironment>(), + false /* no throw */ )) { + // ignore non-existent file in read-only mode: simulate empty db + pcstr_sysPath = 0; + flags = DB_CREATE; + } + } + + int err = m_db.open( + // xxx todo: DB_THREAD, DB_DBT_MALLOC currently not used + 0, pcstr_sysPath, 0, DB_HASH, flags/* | DB_THREAD*/, 0664 /* fs mode */ ); + if (err != 0) + throw_rtexc(err); + } + catch (DbException & exc) { + throw_rtexc( exc.get_errno(), exc.what() ); + } +} + +//______________________________________________________________________________ +PersistentMap::PersistentMap() + : m_db( 0, 0 ) +{ + try { + // xxx todo: DB_THREAD, DB_DBT_MALLOC currently not used + int err = m_db.open( 0, 0, 0, DB_HASH, DB_CREATE/* | DB_THREAD*/, 0 ); + if (err != 0) + throw_rtexc(err); + } + catch (DbException & exc) { + throw_rtexc( exc.get_errno(), exc.what() ); + } +} + +//______________________________________________________________________________ +bool PersistentMap::has( OString const & key ) const +{ + return get( 0, key ); +} + +//______________________________________________________________________________ +bool PersistentMap::get( OString * value, OString const & key ) const +{ + try { + Dbt dbKey( const_cast< sal_Char * >(key.getStr()), key.getLength() ); + Dbt dbData; + int err = m_db.get( 0, &dbKey, &dbData, 0 ); + if (err == DB_NOTFOUND) + return false; + if (err == 0) { + if (value != 0) { + *value = OString( + static_cast< sal_Char const * >(dbData.get_data()), + dbData.get_size() ); + } + return true; + } + throw_rtexc(err); + } + catch (DbException & exc) { + throw_rtexc( exc.get_errno(), exc.what() ); + } + return false; // avoiding warning +} + +//______________________________________________________________________________ +void PersistentMap::put( OString const & key, OString const & value ) +{ + try { + Dbt dbKey( const_cast< sal_Char * >(key.getStr()), key.getLength() ); + Dbt dbData( const_cast< sal_Char * >( + value.getStr()), value.getLength() ); + int err = m_db.put( 0, &dbKey, &dbData, 0 ); + if (err == 0) { +#if OSL_DEBUG_LEVEL > 0 + OString v; + OSL_ASSERT( get( &v, key ) ); + OSL_ASSERT( v.equals( value ) ); +#endif + err = m_db.sync(0); + } + if (err != 0) + throw_rtexc(err); + } + catch (DbException & exc) { + throw_rtexc( exc.get_errno(), exc.what() ); + } +} + +//______________________________________________________________________________ +bool PersistentMap::erase( OString const & key, bool flush_immediately ) +{ + try { + Dbt dbKey( const_cast< sal_Char * >(key.getStr()), key.getLength() ); + int err = m_db.del( &dbKey, 0 ); + if (err == 0) { + if (flush_immediately) { + err = m_db.sync(0); + if (err != 0) + throw_rtexc(err); + } + return true; + } + if (err == DB_NOTFOUND) + return false; + throw_rtexc(err); + } + catch (DbException & exc) { + throw_rtexc( exc.get_errno(), exc.what() ); + } + return false; // avoiding warning +} + +//______________________________________________________________________________ +t_string2string_map PersistentMap::getEntries() const +{ + try { + Dbc * pcurs = 0; + int err = m_db.cursor( 0, &pcurs, 0 ); + if (err != 0) + throw_rtexc(err); + + t_string2string_map ret; + for (;;) { + Dbt dbKey, dbData; + err = pcurs->get( &dbKey, &dbData, DB_NEXT ); + if (err == DB_NOTFOUND) + break; + if (err != 0) + throw_rtexc(err); + + ::std::pair<t_string2string_map::iterator, bool > insertion( + ret.insert( t_string2string_map::value_type( + t_string2string_map::value_type( + OString( static_cast< sal_Char const * >( + dbKey.get_data()), + dbKey.get_size() ), + OString( static_cast< sal_Char const * >( + dbData.get_data()), + dbData.get_size() ) ) ) ) ); + OSL_ASSERT( insertion.second ); + } + err = pcurs->close(); + if (err != 0) + throw_rtexc(err); + return ret; + } + catch (DbException & exc) { + throw_rtexc( exc.get_errno(), exc.what() ); + } + return t_string2string_map(); // avoiding warning +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/dp_services.cxx b/desktop/source/deployment/dp_services.cxx new file mode 100644 index 000000000000..36e7163f283c --- /dev/null +++ b/desktop/source/deployment/dp_services.cxx @@ -0,0 +1,138 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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" + +#define COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS 12 +#include "comphelper/servicedecl.hxx" + +using namespace com::sun::star; +namespace sdecl = comphelper::service_decl; + +namespace dp_registry { +namespace backend { + +namespace configuration { +extern sdecl::ServiceDecl const serviceDecl; +} + +namespace component { +extern sdecl::ServiceDecl const serviceDecl; +} + +namespace script { +extern sdecl::ServiceDecl const serviceDecl; +} + +namespace sfwk { +extern sdecl::ServiceDecl const serviceDecl; +} + +namespace help { +extern sdecl::ServiceDecl const serviceDecl; +} + +namespace executable { +extern sdecl::ServiceDecl const serviceDecl; +} + +} // namespace backend +} // namespace dp_registry + +namespace dp_manager { +namespace factory { +extern sdecl::ServiceDecl const serviceDecl; +bool singleton_entries( uno::Reference<registry::XRegistryKey> const& ); +} +extern sdecl::ServiceDecl const serviceDecl; +bool singleton_entries( uno::Reference<registry::XRegistryKey> const& ); +} + +namespace dp_log { +extern sdecl::ServiceDecl const serviceDecl; +} + +namespace dp_info { +extern sdecl::ServiceDecl const serviceDecl; +bool singleton_entries( uno::Reference<registry::XRegistryKey> const& ); +} + +extern "C" { + +struct uno_Environment; + +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +sal_Bool SAL_CALL component_writeInfo( + lang::XMultiServiceFactory * pServiceManager, + registry::XRegistryKey * pRegistryKey ) +{ + return component_writeInfoHelper( + pServiceManager, pRegistryKey, + dp_registry::backend::configuration::serviceDecl, + dp_registry::backend::component::serviceDecl, + dp_registry::backend::help::serviceDecl, + dp_registry::backend::script::serviceDecl, + dp_registry::backend::sfwk::serviceDecl, + dp_registry::backend::executable::serviceDecl, + dp_manager::factory::serviceDecl, + dp_log::serviceDecl, + dp_info::serviceDecl, + dp_manager::serviceDecl) && + dp_manager::factory::singleton_entries( pRegistryKey ) && + dp_info::singleton_entries( pRegistryKey ) && + dp_manager::singleton_entries( pRegistryKey); +} + +void * SAL_CALL component_getFactory( + sal_Char const * pImplName, + lang::XMultiServiceFactory * pServiceManager, + registry::XRegistryKey * pRegistryKey ) +{ + return component_getFactoryHelper( + pImplName, pServiceManager, pRegistryKey, + dp_registry::backend::configuration::serviceDecl, + dp_registry::backend::component::serviceDecl, + dp_registry::backend::help::serviceDecl, + dp_registry::backend::script::serviceDecl, + dp_registry::backend::sfwk::serviceDecl, + dp_registry::backend::executable::serviceDecl, + dp_manager::factory::serviceDecl, + dp_log::serviceDecl, + dp_info::serviceDecl, + dp_manager::serviceDecl); +} + +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/dp_xml.cxx b/desktop/source/deployment/dp_xml.cxx new file mode 100644 index 000000000000..db787eb57808 --- /dev/null +++ b/desktop/source/deployment/dp_xml.cxx @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_misc.h" +#include "dp_xml.h" +#include "rtl/ustrbuf.hxx" +#include "ucbhelper/content.hxx" +#include "com/sun/star/xml/sax/XParser.hpp" + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +namespace dp_misc +{ + +//============================================================================== +void xml_parse( + Reference<xml::input::XRoot> const & xRoot, + ::ucbhelper::Content & ucb_content, + Reference<XComponentContext> const & xContext ) +{ + const Any arg(xRoot); + const Reference<xml::sax::XDocumentHandler> xDocHandler( + xContext->getServiceManager()->createInstanceWithArgumentsAndContext( + OUSTR("com.sun.star.xml.input.SaxDocumentHandler"), + Sequence<Any>( &arg, 1 ), xContext ), UNO_QUERY_THROW ); + xml_parse( xDocHandler, ucb_content, xContext ); + } + +//============================================================================== +void xml_parse( + Reference<xml::sax::XDocumentHandler> const & xDocHandler, + ::ucbhelper::Content & ucb_content, + Reference<XComponentContext> const & xContext ) +{ + // raise sax parser: + Reference<xml::sax::XParser> xParser( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.xml.sax.Parser"), xContext ), UNO_QUERY_THROW ); + + // error handler, entity resolver omitted + xParser->setDocumentHandler( xDocHandler ); + xml::sax::InputSource source; + source.aInputStream = ucb_content.openStream(); + source.sSystemId = ucb_content.getURL(); + xParser->parseStream( source ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/descedit.cxx b/desktop/source/deployment/gui/descedit.cxx new file mode 100644 index 000000000000..0291ce5802f1 --- /dev/null +++ b/desktop/source/deployment/gui/descedit.cxx @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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/scrbar.hxx> +#include <svtools/txtattr.hxx> +#include <svtools/xtextedt.hxx> + +#include "descedit.hxx" + +#include "dp_gui.hrc" + +using dp_gui::DescriptionEdit; + +// DescriptionEdit ------------------------------------------------------- + +DescriptionEdit::DescriptionEdit( Window* pParent, const ResId& rResId ) : + + ExtMultiLineEdit( pParent, rResId ), + + m_bIsVerticalScrollBarHidden( true ) + +{ + Init(); +} + +// ----------------------------------------------------------------------- + +void DescriptionEdit::Init() +{ + Clear(); + // no tabstop + SetStyle( ( GetStyle() & ~WB_TABSTOP ) | WB_NOTABSTOP ); + // read-only + SetReadOnly(); + // no cursor + EnableCursor( FALSE ); +} + +// ----------------------------------------------------------------------- + +void DescriptionEdit::UpdateScrollBar() +{ + if ( m_bIsVerticalScrollBarHidden ) + { + ScrollBar* pVScrBar = GetVScrollBar(); + if ( pVScrBar && pVScrBar->GetVisibleSize() < pVScrBar->GetRangeMax() ) + { + pVScrBar->Show(); + m_bIsVerticalScrollBarHidden = false; + } + } +} + +// ----------------------------------------------------------------------- + +void DescriptionEdit::Clear() +{ + SetText( String() ); + + m_bIsVerticalScrollBarHidden = true; + ScrollBar* pVScrBar = GetVScrollBar(); + if ( pVScrBar ) + pVScrBar->Hide(); +} + +// ----------------------------------------------------------------------- + +void DescriptionEdit::SetDescription( const String& rDescription ) +{ + SetText( rDescription ); + UpdateScrollBar(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/descedit.hxx b/desktop/source/deployment/gui/descedit.hxx new file mode 100644 index 000000000000..27e36e14a0c8 --- /dev/null +++ b/desktop/source/deployment/gui/descedit.hxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_DEPLOYMENT_GUI_DP_GUI_DESCEDIT_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_DESCEDIT_HXX + +#include "svtools/svmedit2.hxx" + +/// @HTML + +namespace dp_gui +{ + + class DescriptionEdit : public ExtMultiLineEdit + { + private: + bool m_bIsVerticalScrollBarHidden; + + void Init(); + void UpdateScrollBar(); + + public: + DescriptionEdit( Window* pParent, const ResId& rResId ); + inline ~DescriptionEdit() {} + + void Clear(); + void SetDescription( const String& rDescription ); + }; + +} // namespace dp_gui + +#endif // INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_DESCEDIT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui.h b/desktop/source/deployment/gui/dp_gui.h new file mode 100644 index 000000000000..043a86f1aff8 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui.h @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_GUI_H +#define INCLUDED_DP_GUI_H + +#include "dp_gui_updatedata.hxx" +#include "dp_misc.h" +#include "dp_gui.hrc" +#include "rtl/ref.hxx" +#include "rtl/instance.hxx" +#include "osl/thread.hxx" +#include "cppuhelper/implbase2.hxx" +#include "vcl/svapp.hxx" +#include "vcl/dialog.hxx" +#include "vcl/button.hxx" +#include "vcl/fixed.hxx" +#include "salhelper/simplereferenceobject.hxx" +#include "svtools/svtabbx.hxx" +#include "svtools/headbar.hxx" +#include "com/sun/star/ucb/XContentEventListener.hpp" +#include "osl/mutex.hxx" +#include <list> +#include <memory> +#include <queue> + +namespace com { namespace sun { namespace star { + namespace container { + class XNameAccess; + } + namespace frame { + class XDesktop; + } + namespace awt { + class XWindow; + } + namespace uno { + class XComponentContext; + } + namespace deployment { + class XPackageManagerFactory; + } +} } } + +namespace svt { + class FixedHyperlink; +} + +namespace dp_gui { + +enum PackageState { REGISTERED, NOT_REGISTERED, AMBIGUOUS, NOT_AVAILABLE }; + +//============================================================================== + +class SelectedPackage: public salhelper::SimpleReferenceObject { +public: + SelectedPackage() {} + SelectedPackage( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage> &xPackage) + : m_xPackage( xPackage ) + {} + + virtual ~SelectedPackage(); + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage> getPackage() const { return m_xPackage; } + +private: + SelectedPackage(SelectedPackage &); // not defined + void operator =(SelectedPackage &); // not defined + + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage> m_xPackage; +}; + +} // namespace dp_gui + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui.hrc b/desktop/source/deployment/gui/dp_gui.hrc new file mode 100755 index 000000000000..19b2faf129a0 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui.hrc @@ -0,0 +1,180 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_GUI_HRC +#define INCLUDED_DP_GUI_HRC + +#include "deployment.hrc" +#include "helpid.hrc" + +// Package Manager Dialog: +#define RID_DLG_EXTENSION_MANAGER RID_DEPLOYMENT_GUI_START +#define RID_DLG_UPDATE_REQUIRED (RID_DEPLOYMENT_GUI_START + 11) + +#define RID_EM_BTN_CLOSE 10 +#define RID_EM_BTN_HELP 11 +#define RID_EM_BTN_ADD 12 +#define RID_EM_BTN_CHECK_UPDATES 13 +#define RID_EM_BTN_OPTIONS 14 +#define RID_EM_BTN_CANCEL 15 +#define RID_EM_FT_GET_EXTENSIONS 20 +#define RID_EM_FT_PROGRESS 21 +#define RID_EM_FT_MSG 22 + +// local RIDs: +#define PB_LICENSE_DOWN 50 +#define ML_LICENSE 51 +#define BTN_LICENSE_DECLINE 53 +#define FT_LICENSE_HEADER 54 +#define FT_LICENSE_BODY_1 55 +#define FT_LICENSE_BODY_1_TXT 56 +#define FT_LICENSE_BODY_2 57 +#define FT_LICENSE_BODY_2_TXT 58 +#define FL_LICENSE 69 +#define FI_LICENSE_ARROW1 60 +#define FI_LICENSE_ARROW2 61 +#define IMG_LICENCE_ARROW_HC 62 +#define BTN_LICENSE_ACCEPT 63 + +// local RIDs for "Download and Install" dialog + +#define RID_DLG_UPDATE_INSTALL_ABORT 2 +#define RID_DLG_UPDATE_INSTALL_OK 3 +#define RID_DLG_UPDATE_INSTALL_DOWNLOADING 4 +#define RID_DLG_UPDATE_INSTALL_INSTALLING 5 +#define RID_DLG_UPDATE_INSTALL_FINISHED 6 +#define RID_DLG_UPDATE_INSTALL_LINE 7 +#define RID_DLG_UPDATE_INSTALL_HELP 8 +#define RID_DLG_UPDATE_INSTALL_STATUSBAR 9 +#define RID_DLG_UPDATE_INSTALL_EXTENSION_NAME 10 +#define RID_DLG_UPDATE_INSTALL_RESULTS 11 +#define RID_DLG_UPDATE_INSTALL_INFO 12 +#define RID_DLG_UPDATE_INSTALL_NO_ERRORS 13 +#define RID_DLG_UPDATE_INSTALL_THIS_ERROR_OCCURRED 14 +#define RID_DLG_UPDATE_INSTALL_ERROR_DOWNLOAD 15 +#define RID_DLG_UPDATE_INSTALL_ERROR_INSTALLATION 16 +#define RID_DLG_UPDATE_INSTALL_ERROR_LIC_DECLINED 17 +#define RID_DLG_UPDATE_INSTALL_EXTENSION_NOINSTALL 18 + +#define RID_DLG_DEPENDENCIES (RID_DEPLOYMENT_GUI_START + 1) +#define RID_DLG_DEPENDENCIES_TEXT 1 +#define RID_DLG_DEPENDENCIES_LIST 2 +#define RID_DLG_DEPENDENCIES_OK 3 + +#define RID_QUERYBOX_INSTALL_FOR_ALL (RID_DEPLOYMENT_GUI_START + 2) +#define RID_WARNINGBOX_VERSION_LESS (RID_DEPLOYMENT_GUI_START + 3) +#define RID_STR_WARNINGBOX_VERSION_LESS_DIFFERENT_NAMES (RID_DEPLOYMENT_GUI_START + 4) +#define RID_WARNINGBOX_VERSION_EQUAL (RID_DEPLOYMENT_GUI_START + 5) +#define RID_STR_WARNINGBOX_VERSION_EQUAL_DIFFERENT_NAMES (RID_DEPLOYMENT_GUI_START + 6) +#define RID_WARNINGBOX_VERSION_GREATER (RID_DEPLOYMENT_GUI_START + 7) +#define RID_STR_WARNINGBOX_VERSION_GREATER_DIFFERENT_NAMES (RID_DEPLOYMENT_GUI_START + 8) +#define RID_WARNINGBOX_INSTALL_EXTENSION (RID_DEPLOYMENT_GUI_START + 9) + +#define RID_DLG_UPDATE (RID_DEPLOYMENT_GUI_START + 10) + +#define RID_DLG_UPDATE_CHECKING 1 +#define RID_DLG_UPDATE_THROBBER 2 +#define RID_DLG_UPDATE_UPDATE 3 +#define RID_DLG_UPDATE_UPDATES 4 +#define RID_DLG_UPDATE_ALL 5 +#define RID_DLG_UPDATE_DESCRIPTION 6 +#define RID_DLG_UPDATE_DESCRIPTIONS 7 +#define RID_DLG_UPDATE_LINE 8 +#define RID_DLG_UPDATE_HELP 9 +#define RID_DLG_UPDATE_OK 10 +#define RID_DLG_UPDATE_CANCEL 11 +#define RID_DLG_UPDATE_NORMALALERT 12 +#define RID_DLG_UPDATE_HIGHCONTRASTALERT 13 +#define RID_DLG_UPDATE_ERROR 14 +#define RID_DLG_UPDATE_NONE 15 +#define RID_DLG_UPDATE_NOINSTALLABLE 16 +#define RID_DLG_UPDATE_FAILURE 17 +#define RID_DLG_UPDATE_UNKNOWNERROR 18 +#define RID_DLG_UPDATE_NODESCRIPTION 19 +#define RID_DLG_UPDATE_NOINSTALL 20 +#define RID_DLG_UPDATE_NODEPENDENCY 21 +#define RID_DLG_UPDATE_NODEPENDENCY_CUR_VER 22 +#define RID_DLG_UPDATE_NOPERMISSION 23 +#define RID_DLG_UPDATE_NOPERMISSION_VISTA 24 +#define RID_DLG_UPDATE_BROWSERBASED 25 +#define RID_DLG_UPDATE_PUBLISHER_LABEL 26 +#define RID_DLG_UPDATE_PUBLISHER_LINK 27 +#define RID_DLG_UPDATE_RELEASENOTES_LABEL 28 +#define RID_DLG_UPDATE_RELEASENOTES_LINK 29 +#define RID_DLG_UPDATE_NOUPDATE 30 +#define RID_DLG_UPDATE_VERSION 31 + + +#define RID_DLG_UPDATEINSTALL (RID_DEPLOYMENT_GUI_START + 20) +#define RID_INFOBOX_UPDATE_SHARED_EXTENSION (RID_DEPLOYMENT_GUI_START + 21) + +#define RID_IMG_WARNING (RID_DEPLOYMENT_GUI_START+56) +#define RID_IMG_WARNING_HC (RID_DEPLOYMENT_GUI_START+57) +#define RID_IMG_LOCKED (RID_DEPLOYMENT_GUI_START+58) +#define RID_IMG_LOCKED_HC (RID_DEPLOYMENT_GUI_START+59) +#define RID_IMG_EXTENSION (RID_DEPLOYMENT_GUI_START+60) +#define RID_IMG_EXTENSION_HC (RID_DEPLOYMENT_GUI_START+61) +#define RID_IMG_SHARED (RID_DEPLOYMENT_GUI_START+62) +#define RID_IMG_SHARED_HC (RID_DEPLOYMENT_GUI_START+63) + +#define RID_STR_ADD_PACKAGES (RID_DEPLOYMENT_GUI_START+70) + +#define RID_CTX_ITEM_REMOVE (RID_DEPLOYMENT_GUI_START+80) +#define RID_CTX_ITEM_ENABLE (RID_DEPLOYMENT_GUI_START+81) +#define RID_CTX_ITEM_DISABLE (RID_DEPLOYMENT_GUI_START+82) +#define RID_CTX_ITEM_CHECK_UPDATE (RID_DEPLOYMENT_GUI_START+83) +#define RID_CTX_ITEM_OPTIONS (RID_DEPLOYMENT_GUI_START+84) + +#define RID_STR_ADDING_PACKAGES (RID_DEPLOYMENT_GUI_START+85) +#define RID_STR_REMOVING_PACKAGES (RID_DEPLOYMENT_GUI_START+86) +#define RID_STR_ENABLING_PACKAGES (RID_DEPLOYMENT_GUI_START+87) +#define RID_STR_DISABLING_PACKAGES (RID_DEPLOYMENT_GUI_START+88) +#define RID_STR_ACCEPT_LICENSE (RID_DEPLOYMENT_GUI_START+89) + +#define RID_STR_INSTALL_FOR_ALL (RID_DEPLOYMENT_GUI_START+90) +#define RID_STR_INSTALL_FOR_ME (RID_DEPLOYMENT_GUI_START+91) +#define RID_STR_ERROR_UNKNOWN_STATUS (RID_DEPLOYMENT_GUI_START+92) +#define RID_STR_CLOSE_BTN (RID_DEPLOYMENT_GUI_START+93) +#define RID_STR_EXIT_BTN (RID_DEPLOYMENT_GUI_START+94) +#define RID_STR_NO_ADMIN_PRIVILEGE (RID_DEPLOYMENT_GUI_START+95) +#define RID_STR_ERROR_MISSING_DEPENDENCIES (RID_DEPLOYMENT_GUI_START+96) +#define RID_STR_ERROR_MISSING_LICENSE (RID_DEPLOYMENT_GUI_START+97) + +#define WARNINGBOX_CONCURRENTINSTANCE (RID_DEPLOYMENT_GUI_START+100) + +#define RID_STR_UNSUPPORTED_PLATFORM (RID_DEPLOYMENT_GUI_START+101) +#define RID_WARNINGBOX_UPDATE_SHARED_EXTENSION (RID_DEPLOYMENT_GUI_START+102) +#define RID_WARNINGBOX_REMOVE_EXTENSION (RID_DEPLOYMENT_GUI_START+103) +#define RID_WARNINGBOX_REMOVE_SHARED_EXTENSION (RID_DEPLOYMENT_GUI_START+104) +#define RID_WARNINGBOX_ENABLE_SHARED_EXTENSION (RID_DEPLOYMENT_GUI_START+105) +#define RID_WARNINGBOX_DISABLE_SHARED_EXTENSION (RID_DEPLOYMENT_GUI_START+106) + +#define RID_DLG_LICENSE RID_DEPLOYMENT_LICENSE_START + + + +#endif diff --git a/desktop/source/deployment/gui/dp_gui_autoscrolledit.cxx b/desktop/source/deployment/gui/dp_gui_autoscrolledit.cxx new file mode 100644 index 000000000000..c00123fb912e --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_autoscrolledit.cxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "svtools/svmedit2.hxx" +#include "svl/lstner.hxx" +#include "svtools/xtextedt.hxx" +#include "vcl/scrbar.hxx" + +#include "dp_gui_autoscrolledit.hxx" + + +namespace dp_gui { + + +AutoScrollEdit::AutoScrollEdit( Window* pParent, const ResId& rResId ) + : ExtMultiLineEdit( pParent, rResId ) +{ + ScrollBar* pScroll = GetVScrollBar(); + if (pScroll) + pScroll->Hide(); +// SetLeftMargin( 0 ); + StartListening( *GetTextEngine() ); +} + +AutoScrollEdit::~AutoScrollEdit() +{ + EndListeningAll(); +} + +void AutoScrollEdit::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.IsA( TYPE(TextHint) ) ) + { + ULONG nId = ((const TextHint&)rHint).GetId(); + if ( nId == TEXT_HINT_VIEWSCROLLED ) + { + ScrollBar* pScroll = GetVScrollBar(); + if ( pScroll ) + pScroll->Show(); + } + } +} + + +} // namespace dp_gui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_autoscrolledit.hxx b/desktop/source/deployment/gui/dp_gui_autoscrolledit.hxx new file mode 100644 index 000000000000..ddec1e81ae93 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_autoscrolledit.hxx @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_DEPLOYMENT_GUI_DP_GUI_AUTOSCROLLEDIT_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_AUTOSCROLLEDIT_HXX + +#include "svtools/svmedit2.hxx" +#include "svl/lstner.hxx" + +namespace dp_gui { + +/** This control shows automatically the vertical scroll bar if text is inserted, + that does not fit into the text area. In the resource one uses MultiLineEdit + and needs to set VScroll = TRUE +*/ +class AutoScrollEdit : public ExtMultiLineEdit, public SfxListener +{ +public: + AutoScrollEdit( Window* pParent, const ResId& rResId ); + ~AutoScrollEdit(); + + using ExtMultiLineEdit::Notify; + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); +}; + +} // namespace dp_gui + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_backend.src b/desktop/source/deployment/gui/dp_gui_backend.src new file mode 100644 index 000000000000..343d75df6a5e --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_backend.src @@ -0,0 +1,131 @@ +/************************************************************************* + * + * 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 "dp_gui.hrc" + +// package bundle: +Image RID_IMG_DEF_PACKAGE_BUNDLE +{ + ImageBitmap = Bitmap { File = "sx03256.bmp"; }; + MASKCOLOR +}; +Image RID_IMG_DEF_PACKAGE_BUNDLE_HC +{ + ImageBitmap = Bitmap { File = "sxh03256.bmp"; }; + MASKCOLOR +}; + +// script, dialog: +Image RID_IMG_SCRIPTLIB +{ + ImageBitmap = Bitmap { File = "im30820.bmp"; }; + MASKCOLOR +}; +Image RID_IMG_SCRIPTLIB_HC +{ + ImageBitmap = Bitmap { File = "imh30820.bmp"; }; + MASKCOLOR +}; + +Image RID_IMG_DIALOGLIB +{ + ImageBitmap = Bitmap { File = "dialogfolder_16.bmp"; }; + MASKCOLOR +}; +Image RID_IMG_DIALOGLIB_HC +{ + ImageBitmap = Bitmap { File = "dialogfolder_16_h.bmp"; }; + MASKCOLOR +}; + +// configuration: +Image RID_IMG_CONF_XML +{ + ImageBitmap = Bitmap { File = "xml_16.bmp"; }; + MASKCOLOR +}; +Image RID_IMG_CONF_XML_HC +{ + ImageBitmap = Bitmap { File = "xml_16_h.bmp"; }; + MASKCOLOR +}; + +// component, typelib: +Image RID_IMG_COMPONENT +{ + ImageBitmap = Bitmap { File = "component_16.bmp"; }; + MASKCOLOR +}; +Image RID_IMG_COMPONENT_HC +{ + ImageBitmap = Bitmap { File = "component_16_h.bmp"; }; + MASKCOLOR +}; + +Image RID_IMG_JAVA_COMPONENT +{ + ImageBitmap = Bitmap { File = "javacomponent_16.bmp"; }; + MASKCOLOR +}; +Image RID_IMG_JAVA_COMPONENT_HC +{ + ImageBitmap = Bitmap { File = "javacomponent_16_h.bmp"; }; + MASKCOLOR +}; + +Image RID_IMG_TYPELIB +{ + ImageBitmap = Bitmap { File = "library_16.bmp"; }; + MASKCOLOR +}; +Image RID_IMG_TYPELIB_HC +{ + ImageBitmap = Bitmap { File = "library_16_h.bmp"; }; + MASKCOLOR +}; + +Image RID_IMG_JAVA_TYPELIB +{ + ImageBitmap = Bitmap { File = "javalibrary_16.bmp"; }; + MASKCOLOR +}; +Image RID_IMG_JAVA_TYPELIB_HC +{ + ImageBitmap = Bitmap { File = "javalibrary_16_h.bmp"; }; + MASKCOLOR +}; + +Image RID_IMG_HELP +{ + ImageBitmap = Bitmap { File = "commandimagelist/sc_helperdialog.bmp"; }; + MASKCOLOR +}; +Image RID_IMG_HELP_HC +{ + ImageBitmap = Bitmap { File = "commandimagelist/sch_helperdialog.bmp"; }; + MASKCOLOR +}; diff --git a/desktop/source/deployment/gui/dp_gui_dependencydialog.cxx b/desktop/source/deployment/gui/dp_gui_dependencydialog.cxx new file mode 100644 index 000000000000..694f764d5ed7 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_dependencydialog.cxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "sal/config.h" + +#include <algorithm> +#include <vector> + +#include "rtl/ustring.hxx" +#include "tools/gen.hxx" +#include "tools/resid.hxx" +#include "tools/resmgr.hxx" +#include "tools/solar.h" +#include "tools/string.hxx" +#include "vcl/dialog.hxx" + +#include "dp_gui.hrc" +#include "dp_gui_dependencydialog.hxx" +#include "dp_gui_shared.hxx" + +class Window; + +using dp_gui::DependencyDialog; + +DependencyDialog::DependencyDialog( + Window * parent, std::vector< rtl::OUString > const & dependencies): + ModalDialog(parent, DpGuiResId(RID_DLG_DEPENDENCIES) ), + m_text(this, DpGuiResId(RID_DLG_DEPENDENCIES_TEXT)), + m_list(this, DpGuiResId(RID_DLG_DEPENDENCIES_LIST)), + m_ok(this, DpGuiResId(RID_DLG_DEPENDENCIES_OK)), + m_listDelta( + GetOutputSizePixel().Width() - m_list.GetSizePixel().Width(), + GetOutputSizePixel().Height() - m_list.GetSizePixel().Height()) +{ + FreeResource(); + SetMinOutputSizePixel(GetOutputSizePixel()); + m_list.SetReadOnly(); + for (std::vector< rtl::OUString >::const_iterator i(dependencies.begin()); + i != dependencies.end(); ++i) + { + m_list.InsertEntry(*i); + } +} + +DependencyDialog::~DependencyDialog() {} + +void DependencyDialog::Resize() { + long n = m_ok.GetPosPixel().Y() - + (m_list.GetPosPixel().Y() + m_list.GetSizePixel().Height()); + m_list.SetSizePixel( + Size( + GetOutputSizePixel().Width() - m_listDelta.Width(), + GetOutputSizePixel().Height() - m_listDelta.Height())); + m_ok.SetPosPixel( + Point( + (m_list.GetPosPixel().X() + + (m_list.GetSizePixel().Width() - m_ok.GetSizePixel().Width()) / 2), + m_list.GetPosPixel().Y() + m_list.GetSizePixel().Height() + n)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_dependencydialog.hxx b/desktop/source/deployment/gui/dp_gui_dependencydialog.hxx new file mode 100644 index 000000000000..72f8334d38dc --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_dependencydialog.hxx @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_DEPLOYMENT_GUI_DP_GUI_DEPENDENCYDIALOG_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_DEPENDENCYDIALOG_HXX + +#include "sal/config.h" + +#include <vector> +#include "tools/gen.hxx" +#include "vcl/button.hxx" +#include "vcl/dialog.hxx" +#include "vcl/fixed.hxx" +#include "vcl/lstbox.hxx" + +class Window; +namespace rtl { class OUString; } + +namespace dp_gui { + +class DependencyDialog: public ModalDialog { +public: + DependencyDialog( + Window * parent, std::vector< rtl::OUString > const & dependencies); + + ~DependencyDialog(); + +private: + DependencyDialog(DependencyDialog &); // not defined + void operator =(DependencyDialog &); // not defined + + virtual void Resize(); + + FixedText m_text; + ListBox m_list; + OKButton m_ok; + Size m_listDelta; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_dependencydialog.src b/desktop/source/deployment/gui/dp_gui_dependencydialog.src new file mode 100644 index 000000000000..80b584f89423 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_dependencydialog.src @@ -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. + * + ************************************************************************/ + +#include "svtools/controldims.hrc" + +#include "dp_gui.hrc" + +#define LOCAL_WIDTH (50 * RSC_BS_CHARWIDTH) +#define LOCAL_TEXT_HEIGHT (2 * RSC_CD_FIXEDTEXT_HEIGHT) +#define LOCAL_LIST_HEIGHT (6 * RSC_BS_CHARHEIGHT) + +ModalDialog RID_DLG_DEPENDENCIES { + Size = MAP_APPFONT( + (RSC_SP_DLG_INNERBORDER_LEFT + LOCAL_WIDTH + + RSC_SP_DLG_INNERBORDER_RIGHT), + (RSC_SP_DLG_INNERBORDER_TOP + LOCAL_TEXT_HEIGHT + RSC_SP_CTRL_DESC_Y + + LOCAL_LIST_HEIGHT + RSC_SP_CTRL_Y + RSC_CD_PUSHBUTTON_HEIGHT + + RSC_SP_DLG_INNERBORDER_BOTTOM)); + Text[en-US] = "System dependencies check"; + Sizeable = TRUE; + Moveable = TRUE; + Closeable = TRUE; + FixedText RID_DLG_DEPENDENCIES_TEXT { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, RSC_SP_DLG_INNERBORDER_TOP); + Size = MAP_APPFONT(LOCAL_WIDTH, LOCAL_TEXT_HEIGHT); + Text[en-US] = "The extension cannot be installed as the following\nsystem dependencies are not fulfilled:"; + NoLabel = TRUE; + }; + ListBox RID_DLG_DEPENDENCIES_LIST { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + LOCAL_TEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y)); + Size = MAP_APPFONT(LOCAL_WIDTH, LOCAL_LIST_HEIGHT); + }; + OKButton RID_DLG_DEPENDENCIES_OK { + Pos = MAP_APPFONT( + (RSC_SP_DLG_INNERBORDER_LEFT + + (LOCAL_WIDTH - RSC_CD_PUSHBUTTON_WIDTH) / 2), + (RSC_SP_DLG_INNERBORDER_TOP + LOCAL_TEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT + RSC_SP_CTRL_Y)); + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT); + DefButton = TRUE; + }; +}; diff --git a/desktop/source/deployment/gui/dp_gui_dialog.src b/desktop/source/deployment/gui/dp_gui_dialog.src new file mode 100755 index 000000000000..db2e09769de3 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_dialog.src @@ -0,0 +1,345 @@ +/************************************************************************* + * + * 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 "svtools/controldims.hrc" +#include "dp_gui.hrc" + +String RID_STR_ADD_PACKAGES +{ + Text [ en-US ] = "Add Extension(s)"; +}; +String RID_CTX_ITEM_REMOVE +{ + Text [ en-US ] = "~Remove"; +}; +String RID_CTX_ITEM_ENABLE +{ + Text [ en-US ] = "~Enable"; +}; +String RID_CTX_ITEM_DISABLE +{ + Text [ en-US ] = "~Disable"; +}; +String RID_CTX_ITEM_CHECK_UPDATE +{ + Text [ en-US ] = "~Update..."; +}; +String RID_CTX_ITEM_OPTIONS +{ + Text [ en-US ] = "~Options..."; +}; + +String RID_STR_ADDING_PACKAGES +{ + Text [ en-US ] = "Adding %EXTENSION_NAME"; +}; + +String RID_STR_REMOVING_PACKAGES +{ + Text [ en-US ] = "Removing %EXTENSION_NAME"; +}; + +String RID_STR_ENABLING_PACKAGES +{ + Text [ en-US ] = "Enabling %EXTENSION_NAME"; +}; + +String RID_STR_DISABLING_PACKAGES +{ + Text [ en-US ] = "Disabling %EXTENSION_NAME"; +}; + +String RID_STR_ACCEPT_LICENSE +{ + Text [ en-US ] = "Accept license for %EXTENSION_NAME"; +}; + +String RID_STR_INSTALL_FOR_ALL +{ + Text [ en-US ] = "~For all users"; +}; + +String RID_STR_INSTALL_FOR_ME +{ + Text [ en-US ] = "~Only for me"; +}; + +String RID_STR_ERROR_UNKNOWN_STATUS +{ + Text [ en-US ] = "Error: The status of this extension is unknown"; +}; + +String RID_STR_CLOSE_BTN +{ + Text [ en-US ] = "Close"; +}; + +String RID_STR_EXIT_BTN +{ + Text [ en-US ] = "Quit"; +}; + +String RID_STR_NO_ADMIN_PRIVILEGE +{ + Text [ en-US ] = "%PRODUCTNAME has been updated to a new version. " + "Some shared %PRODUCTNAME extensions are not compatible with this version and need to be updated before %PRODUCTNAME can be started.\n\n" + "Updating of shared extension requires administrator privileges. Contact your system administrator to update the following shared extensions:"; +}; + +String RID_STR_ERROR_MISSING_DEPENDENCIES +{ + Text [ en-US ] = "The extension cannot be enabled as the following system dependencies are not fulfilled:"; +}; + +String RID_STR_ERROR_MISSING_LICENSE +{ + Text [ en-US ] = "This extension is disabled because you haven't accepted the license yet.\n"; +}; + +// Dialog layout +// --------------------------------------------------- +// row 1 | multi line edit +// --------------------------------------------------- +// row 2 | fixed text +// --------------------------------------------------- +// row 3 | img | fixed text | fixed text | button +// ---------------------------------------------------- +// row 4 | img | fixed text | fixed text +// --------------------------------------------------- +// row 5 |fixed line +// --------------------------------------------------- +// row 6 | | |button | button +// --------------------------------------------------- +// | col 1 | col 2 | col3 | col4 | col5 + +//To change the overall size of the multi line edit change +//ROW1_HEIGHT and COL3_WIDTH + +#define ROW1_Y RSC_SP_DLG_INNERBORDER_TOP +#define ROW1_HEIGHT 16*RSC_CD_FIXEDTEXT_HEIGHT +#define ROW2_Y ROW1_Y+ROW1_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW2_HEIGHT 3*RSC_CD_FIXEDTEXT_HEIGHT +#define ROW3_Y ROW2_Y+ROW2_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW3_HEIGHT 3*RSC_CD_FIXEDTEXT_HEIGHT +#define ROW4_Y ROW3_Y+ROW3_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW4_HEIGHT 3*RSC_CD_FIXEDTEXT_HEIGHT +#define ROW5_Y ROW4_Y+ROW4_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW5_HEIGHT RSC_CD_FIXEDTEXT_HEIGHT +#define ROW6_Y ROW5_Y+ROW5_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW6_HEIGHT RSC_CD_PUSHBUTTON_HEIGHT + +#define LIC_DLG_HEIGHT ROW6_Y+ROW6_HEIGHT+RSC_SP_DLG_INNERBORDER_BOTTOM + +#define COL1_X RSC_SP_DLG_INNERBORDER_LEFT +#define IMG_ARROW_WIDTH 16 +#define COL1_WIDTH IMG_ARROW_WIDTH +#define COL2_X COL1_X+COL1_WIDTH +#define COL2_WIDTH 10 +#define COL3_X COL2_X+COL2_WIDTH+RSC_SP_CTRL_GROUP_X +#define COL3_WIDTH 150 +#define COL4_X COL3_X+COL3_WIDTH +#define COL4_WIDTH RSC_CD_PUSHBUTTON_WIDTH+RSC_SP_CTRL_GROUP_X +#define COL5_X COL4_X+COL4_WIDTH + +#define LIC_DLG_WIDTH COL5_X+RSC_CD_PUSHBUTTON_WIDTH+RSC_SP_DLG_INNERBORDER_RIGHT +#define BODYWIDTH LIC_DLG_WIDTH-RSC_SP_DLG_INNERBORDER_LEFT-RSC_SP_DLG_INNERBORDER_RIGHT + +ModalDialog RID_DLG_LICENSE +{ + Text [ en-US ] = "Extension Software License Agreement"; + + Size = MAP_APPFONT(LIC_DLG_WIDTH, LIC_DLG_HEIGHT); + OutputSize = TRUE; + SVLook = TRUE; + Moveable = TRUE; + Closeable = TRUE; + Sizeable = FALSE; +// Hide = TRUE; + + MultiLineEdit ML_LICENSE + { + Pos = MAP_APPFONT(COL1_X, ROW1_Y); + Size = MAP_APPFONT(BODYWIDTH, ROW1_HEIGHT); + Border = TRUE; + VScroll = TRUE; + ReadOnly = TRUE; + }; + + FixedText FT_LICENSE_HEADER + { + Pos = MAP_APPFONT(COL1_X, ROW2_Y); + Size = MAP_APPFONT(COL1_WIDTH+COL2_WIDTH+COL3_WIDTH+COL4_WIDTH, ROW2_HEIGHT); + WordBreak = TRUE; + NoLabel = TRUE; + Text [ en-US ] = "Please follow these steps to proceed with the installation of the extension:"; + }; + FixedText FT_LICENSE_BODY_1 + { + Pos = MAP_APPFONT(COL2_X, ROW3_Y); + Size = MAP_APPFONT( COL2_WIDTH, ROW3_HEIGHT ); + NoLabel = TRUE; + Text [ en-US ] = "1."; + }; + //spans col3 + col4 + FixedText FT_LICENSE_BODY_1_TXT + { + Pos = MAP_APPFONT(COL3_X, ROW3_Y); + Size = MAP_APPFONT(COL3_WIDTH+COL4_WIDTH, ROW3_HEIGHT); + WordBreak = TRUE; + NoLabel = TRUE; + Text [ en-US ] = "Read the complete License Agreement. Use the scroll bar or the \'Scroll Down\' button in this dialog to view the entire license text."; + }; + FixedText FT_LICENSE_BODY_2 + { + Pos = MAP_APPFONT(COL2_X, ROW4_Y); + Size = MAP_APPFONT(COL2_WIDTH, ROW4_HEIGHT); + NoLabel = TRUE; + Text [ en-US ] = "2."; + }; + FixedText FT_LICENSE_BODY_2_TXT + { + Pos = MAP_APPFONT(COL3_X, ROW4_Y); + Size = MAP_APPFONT(COL3_WIDTH+COL4_WIDTH, ROW4_HEIGHT); + WordBreak = TRUE; + NoLabel = TRUE; + Text [ en-US ] = "Accept the License Agreement for the extension by pressing the \'Accept\' button."; + + }; + PushButton PB_LICENSE_DOWN + { + TabStop = TRUE ; + Pos = MAP_APPFONT(COL5_X , ROW3_Y) ; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT) ; + Text [ en-US ] = "~Scroll Down"; + + }; + FixedLine FL_LICENSE + { + Pos = MAP_APPFONT ( 0, ROW5_Y) ; + Size = MAP_APPFONT ( LIC_DLG_WIDTH, ROW5_HEIGHT ) ; + }; + + FixedImage FI_LICENSE_ARROW1 + { + Pos = MAP_APPFONT (COL1_X, ROW3_Y) ; + Size = (16, 16); + Fixed = Image + { + ImageBitmap = Bitmap { File = "sc06300.png"; }; + MASKCOLOR + }; + }; + + FixedImage FI_LICENSE_ARROW2 + { + Pos = MAP_APPFONT (COL1_X, ROW4_Y) ; + Size = (16,16); + Fixed = Image + { + ImageBitmap = Bitmap { File = "sc06300.png"; }; + MASKCOLOR + }; + }; + + Image IMG_LICENCE_ARROW_HC + { + ImageBitmap = Bitmap { File = "sch06300.png"; }; + MASKCOLOR + }; + + OKButton BTN_LICENSE_ACCEPT + { + Pos = MAP_APPFONT(COL4_X, ROW6_Y); + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + + TabStop = TRUE; + DefButton = TRUE; + Text [ en-US ] = "Accept"; + }; + + CancelButton BTN_LICENSE_DECLINE + { + Pos = MAP_APPFONT(COL5_X, ROW6_Y); + Size = MAP_APPFONT( RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + Text [ en-US ] = "Decline" ; + TabStop = TRUE; + }; + +}; + + + +WarningBox RID_WARNINGBOX_INSTALL_EXTENSION { + Buttons = WB_OK_CANCEL; + DefButton = WB_DEF_OK; + Message[en-US] = "You are about to install the extension \'%NAME\'.\n" + "Click \'OK\' to proceed with the installation.\n" + "Click \'Cancel\' to stop the installation."; +}; + +WarningBox RID_WARNINGBOX_REMOVE_EXTENSION { + Buttons = WB_OK_CANCEL; + DefButton = WB_DEF_CANCEL; + Message[en-US] = "You are about to remove the extension \'%NAME\'.\n" + "Click \'OK\' to remove the extension.\n" + "Click \'Cancel\' to stop removing the extension."; +}; + +WARNINGBOX RID_WARNINGBOX_REMOVE_SHARED_EXTENSION +{ + Buttons = WB_OK_CANCEL; + DefButton = WB_DEF_CANCEL; + Message[en-US] = "Make sure that no further users are working with the same " + "%PRODUCTNAME, when changing shared extensions in a multi user environment.\n" + "Click \'OK\' to remove the extension.\n" + "Click \'Cancel\' to stop removing the extension."; +}; + +WARNINGBOX RID_WARNINGBOX_ENABLE_SHARED_EXTENSION +{ + Buttons = WB_OK_CANCEL; + DefButton = WB_DEF_CANCEL; + Message[en-US] = "Make sure that no further users are working with the same " + "%PRODUCTNAME, when changing shared extensions in a multi user environment.\n" + "Click \'OK\' to enable the extension.\n" + "Click \'Cancel\' to stop enabling the extension."; +}; + +WARNINGBOX RID_WARNINGBOX_DISABLE_SHARED_EXTENSION +{ + Buttons = WB_OK_CANCEL; + DefButton = WB_DEF_CANCEL; + Message[en-US] = "Make sure that no further users are working with the same " + "%PRODUCTNAME, when changing shared extensions in a multi user environment.\n" + "Click \'OK\' to disable the extension.\n" + "Click \'Cancel\' to stop disabling the extension."; +}; + + +String RID_STR_UNSUPPORTED_PLATFORM +{ + Text [ en-US ] = "The extension \'%Name\' does not work on this computer."; +}; diff --git a/desktop/source/deployment/gui/dp_gui_dialog2.cxx b/desktop/source/deployment/gui/dp_gui_dialog2.cxx new file mode 100644 index 000000000000..53628fb8546d --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_dialog2.cxx @@ -0,0 +1,1787 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_gui.hrc" +#include "svtools/controldims.hrc" +#include "svtools/svtools.hrc" + +#include "dp_gui.h" +#include "dp_gui_dialog2.hxx" +#include "dp_gui_extlistbox.hxx" +#include "dp_gui_shared.hxx" +#include "dp_gui_theextmgr.hxx" +#include "dp_gui_extensioncmdqueue.hxx" +#include "dp_misc.h" +#include "dp_update.hxx" +#include "dp_identifier.hxx" + +#include "vcl/ctrl.hxx" +#include "vcl/menu.hxx" +#include "vcl/msgbox.hxx" +#include "vcl/scrbar.hxx" +#include "vcl/svapp.hxx" + +#include "osl/mutex.hxx" + +#include "svtools/extensionlistbox.hxx" + +#include "sfx2/sfxdlg.hxx" + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "cppuhelper/bootstrap.hxx" + +#include "comphelper/processfactory.hxx" +#include "ucbhelper/content.hxx" +#include "unotools/collatorwrapper.hxx" + +#include "com/sun/star/beans/StringPair.hpp" + +#include "com/sun/star/i18n/CollatorOptions.hpp" + +#include "com/sun/star/system/SystemShellExecuteFlags.hpp" +#include "com/sun/star/system/XSystemShellExecute.hpp" + +#include "com/sun/star/ui/dialogs/ExecutableDialogResults.hpp" +#include "com/sun/star/ui/dialogs/TemplateDescription.hpp" +#include "com/sun/star/ui/dialogs/XFilePicker.hpp" +#include "com/sun/star/ui/dialogs/XFilterManager.hpp" + +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" + +#include <map> +#include <vector> +#include <boost/shared_ptr.hpp> + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + +using namespace ::com::sun::star; +using namespace ::com::sun::star::system; + +using ::rtl::OUString; + + +namespace dp_gui { + +#define TOP_OFFSET 5 +#define LINE_SIZE 4 +#define PROGRESS_WIDTH 60 +#define PROGRESS_HEIGHT 14 + +//------------------------------------------------------------------------------ +struct StrAllFiles : public rtl::StaticWithInit< const OUString, StrAllFiles > +{ + const OUString operator () () { + const SolarMutexGuard guard; + ::std::auto_ptr< ResMgr > const resmgr( ResMgr::CreateResMgr( "fps_office" ) ); + OSL_ASSERT( resmgr.get() != 0 ); + String ret( ResId( STR_FILTERNAME_ALL, *resmgr.get() ) ); + return ret; + } +}; + +//------------------------------------------------------------------------------ +// ExtBoxWithBtns_Impl +//------------------------------------------------------------------------------ + +enum MENU_COMMAND +{ + CMD_NONE = 0, + CMD_REMOVE = 1, + CMD_ENABLE, + CMD_DISABLE, + CMD_UPDATE +}; + +class ExtBoxWithBtns_Impl : public ExtensionBox_Impl +{ + Size m_aOutputSize; + bool m_bInterfaceLocked; + + PushButton *m_pOptionsBtn; + PushButton *m_pEnableBtn; + PushButton *m_pRemoveBtn; + + ExtMgrDialog *m_pParent; + + void SetButtonPos( const Rectangle& rRect ); + void SetButtonStatus( const TEntry_Impl pEntry ); + bool HandleTabKey( bool bReverse ); + MENU_COMMAND ShowPopupMenu( const Point &rPos, const long nPos ); + + //----------------- + DECL_DLLPRIVATE_LINK( ScrollHdl, ScrollBar * ); + + DECL_DLLPRIVATE_LINK( HandleOptionsBtn, void * ); + DECL_DLLPRIVATE_LINK( HandleEnableBtn, void * ); + DECL_DLLPRIVATE_LINK( HandleRemoveBtn, void * ); + DECL_DLLPRIVATE_LINK( HandleHyperlink, svt::FixedHyperlink * ); + +public: + ExtBoxWithBtns_Impl( ExtMgrDialog* pParent, TheExtensionManager *pManager ); + ~ExtBoxWithBtns_Impl(); + + virtual void MouseButtonDown( const MouseEvent& rMEvt ); + virtual long Notify( NotifyEvent& rNEvt ); + + const Size GetMinOutputSizePixel() const; + + virtual void RecalcAll(); + virtual void selectEntry( const long nPos ); + //----------------- + void enableButtons( bool bEnable ); +}; + +//------------------------------------------------------------------------------ +ExtBoxWithBtns_Impl::ExtBoxWithBtns_Impl( ExtMgrDialog* pParent, TheExtensionManager *pManager ) : + ExtensionBox_Impl( pParent, pManager ), + m_bInterfaceLocked( false ), + m_pOptionsBtn( NULL ), + m_pEnableBtn( NULL ), + m_pRemoveBtn( NULL ), + m_pParent( pParent ) +{ + m_pOptionsBtn = new PushButton( this, WB_TABSTOP ); + m_pEnableBtn = new PushButton( this, WB_TABSTOP ); + m_pRemoveBtn = new PushButton( this, WB_TABSTOP ); + + SetHelpId( HID_EXTENSION_MANAGER_LISTBOX ); + m_pOptionsBtn->SetHelpId( HID_EXTENSION_MANAGER_LISTBOX_OPTIONS ); + m_pEnableBtn->SetHelpId( HID_EXTENSION_MANAGER_LISTBOX_DISABLE ); + m_pRemoveBtn->SetHelpId( HID_EXTENSION_MANAGER_LISTBOX_REMOVE ); + + m_pOptionsBtn->SetClickHdl( LINK( this, ExtBoxWithBtns_Impl, HandleOptionsBtn ) ); + m_pEnableBtn->SetClickHdl( LINK( this, ExtBoxWithBtns_Impl, HandleEnableBtn ) ); + m_pRemoveBtn->SetClickHdl( LINK( this, ExtBoxWithBtns_Impl, HandleRemoveBtn ) ); + + m_pOptionsBtn->SetText( DialogHelper::getResourceString( RID_CTX_ITEM_OPTIONS ) ); + m_pEnableBtn->SetText( DialogHelper::getResourceString( RID_CTX_ITEM_DISABLE ) ); + m_pRemoveBtn->SetText( DialogHelper::getResourceString( RID_CTX_ITEM_REMOVE ) ); + + Size aSize = LogicToPixel( Size( RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ), + MapMode( MAP_APPFONT ) ); + m_pOptionsBtn->SetSizePixel( aSize ); + m_pEnableBtn->SetSizePixel( aSize ); + m_pRemoveBtn->SetSizePixel( aSize ); + + SetExtraSize( aSize.Height() + 2 * TOP_OFFSET ); + + SetScrollHdl( LINK( this, ExtBoxWithBtns_Impl, ScrollHdl ) ); +} + +//------------------------------------------------------------------------------ +ExtBoxWithBtns_Impl::~ExtBoxWithBtns_Impl() +{ + delete m_pOptionsBtn; + delete m_pEnableBtn; + delete m_pRemoveBtn; +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +const Size ExtBoxWithBtns_Impl::GetMinOutputSizePixel() const +{ + Size aMinSize( ExtensionBox_Impl::GetMinOutputSizePixel() ); + long nHeight = aMinSize.Height(); + nHeight += m_pOptionsBtn->GetSizePixel().Height(); + nHeight += 2 * TOP_OFFSET; + long nWidth = m_pOptionsBtn->GetSizePixel().Width(); + nWidth *= 3; + nWidth += 5*TOP_OFFSET + 20; + + return Size( nWidth, nHeight ); +} + +// ----------------------------------------------------------------------- +void ExtBoxWithBtns_Impl::RecalcAll() +{ + ExtensionBox_Impl::RecalcAll(); + + const sal_Int32 nActive = getSelIndex(); + + if ( nActive != EXTENSION_LISTBOX_ENTRY_NOTFOUND ) + { + SetButtonPos( GetEntryRect( nActive ) ); + SetButtonStatus( GetEntryData( nActive) ); + } + else + { + m_pOptionsBtn->Hide(); + m_pEnableBtn->Hide(); + m_pRemoveBtn->Hide(); + } +} + + +//------------------------------------------------------------------------------ +//This function may be called with nPos < 0 +void ExtBoxWithBtns_Impl::selectEntry( const long nPos ) +{ + if ( HasActive() && ( nPos == getSelIndex() ) ) + return; + + ExtensionBox_Impl::selectEntry( nPos ); +} + +// ----------------------------------------------------------------------- +void ExtBoxWithBtns_Impl::SetButtonPos( const Rectangle& rRect ) +{ + Size aBtnSize( m_pOptionsBtn->GetSizePixel() ); + Point aBtnPos( rRect.Left() + ICON_OFFSET, + rRect.Bottom() - TOP_OFFSET - aBtnSize.Height() ); + + m_pOptionsBtn->SetPosPixel( aBtnPos ); + aBtnPos.X() = rRect.Right() - TOP_OFFSET - aBtnSize.Width(); + m_pRemoveBtn->SetPosPixel( aBtnPos ); + aBtnPos.X() -= ( TOP_OFFSET + aBtnSize.Width() ); + m_pEnableBtn->SetPosPixel( aBtnPos ); +} + +// ----------------------------------------------------------------------- +void ExtBoxWithBtns_Impl::SetButtonStatus( const TEntry_Impl pEntry ) +{ + bool bShowOptionBtn = true; + + pEntry->m_bHasButtons = false; + if ( ( pEntry->m_eState == REGISTERED ) || ( pEntry->m_eState == NOT_AVAILABLE ) ) + { + m_pEnableBtn->SetText( DialogHelper::getResourceString( RID_CTX_ITEM_DISABLE ) ); + m_pEnableBtn->SetHelpId( HID_EXTENSION_MANAGER_LISTBOX_DISABLE ); + } + else + { + m_pEnableBtn->SetText( DialogHelper::getResourceString( RID_CTX_ITEM_ENABLE ) ); + m_pEnableBtn->SetHelpId( HID_EXTENSION_MANAGER_LISTBOX_ENABLE ); + bShowOptionBtn = false; + } + + if ( ( !pEntry->m_bUser || ( pEntry->m_eState == NOT_AVAILABLE ) || pEntry->m_bMissingDeps ) + && !pEntry->m_bMissingLic ) + m_pEnableBtn->Hide(); + else + { + m_pEnableBtn->Enable( !pEntry->m_bLocked ); + m_pEnableBtn->Show(); + pEntry->m_bHasButtons = true; + } + + if ( pEntry->m_bHasOptions && bShowOptionBtn ) + { + m_pOptionsBtn->Enable( pEntry->m_bHasOptions ); + m_pOptionsBtn->Show(); + pEntry->m_bHasButtons = true; + } + else + m_pOptionsBtn->Hide(); + + if ( pEntry->m_bUser || pEntry->m_bShared ) + { + m_pRemoveBtn->Enable( !pEntry->m_bLocked ); + m_pRemoveBtn->Show(); + pEntry->m_bHasButtons = true; + } + else + m_pRemoveBtn->Hide(); +} + +// ----------------------------------------------------------------------- +bool ExtBoxWithBtns_Impl::HandleTabKey( bool bReverse ) +{ + sal_Int32 nIndex = getSelIndex(); + + if ( nIndex == EXTENSION_LISTBOX_ENTRY_NOTFOUND ) + return false; + + PushButton *pNext = NULL; + + if ( m_pOptionsBtn->HasFocus() ) { + if ( !bReverse && !GetEntryData( nIndex )->m_bLocked ) + pNext = m_pEnableBtn; + } + else if ( m_pEnableBtn->HasFocus() ) { + if ( !bReverse ) + pNext = m_pRemoveBtn; + else if ( GetEntryData( nIndex )->m_bHasOptions ) + pNext = m_pOptionsBtn; + } + else if ( m_pRemoveBtn->HasFocus() ) { + if ( bReverse ) + pNext = m_pEnableBtn; + } + else { + if ( !bReverse ) { + if ( GetEntryData( nIndex )->m_bHasOptions ) + pNext = m_pOptionsBtn; + else if ( ! GetEntryData( nIndex )->m_bLocked ) + pNext = m_pEnableBtn; + } else { + if ( ! GetEntryData( nIndex )->m_bLocked ) + pNext = m_pRemoveBtn; + else if ( GetEntryData( nIndex )->m_bHasOptions ) + pNext = m_pOptionsBtn; + } + } + + if ( pNext ) + { + pNext->GrabFocus(); + return true; + } + else + return false; +} + +// ----------------------------------------------------------------------- +MENU_COMMAND ExtBoxWithBtns_Impl::ShowPopupMenu( const Point & rPos, const long nPos ) +{ + if ( ( nPos >= 0 ) && ( nPos < (long) getItemCount() ) ) + { + if ( ! GetEntryData( nPos )->m_bLocked ) + { + PopupMenu aPopup; + + aPopup.InsertItem( CMD_UPDATE, DialogHelper::getResourceString( RID_CTX_ITEM_CHECK_UPDATE ) ); + + if ( GetEntryData( nPos )->m_bUser ) + { + if ( GetEntryData( nPos )->m_eState == REGISTERED ) + aPopup.InsertItem( CMD_DISABLE, DialogHelper::getResourceString( RID_CTX_ITEM_DISABLE ) ); + else if ( GetEntryData( nPos )->m_eState != NOT_AVAILABLE ) + aPopup.InsertItem( CMD_ENABLE, DialogHelper::getResourceString( RID_CTX_ITEM_ENABLE ) ); + } + + aPopup.InsertItem( CMD_REMOVE, DialogHelper::getResourceString( RID_CTX_ITEM_REMOVE ) ); + + return (MENU_COMMAND) aPopup.Execute( this, rPos ); + } + } + return CMD_NONE; +} + +//------------------------------------------------------------------------------ +void ExtBoxWithBtns_Impl::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( m_bInterfaceLocked ) + return; + + const Point aMousePos( rMEvt.GetPosPixel() ); + const long nPos = PointToPos( aMousePos ); + + if ( rMEvt.IsRight() ) + { + switch( ShowPopupMenu( aMousePos, nPos ) ) + { + case CMD_NONE: break; + case CMD_ENABLE: m_pParent->enablePackage( GetEntryData( nPos )->m_xPackage, true ); + break; + case CMD_DISABLE: m_pParent->enablePackage( GetEntryData( nPos )->m_xPackage, false ); + break; + case CMD_UPDATE: m_pParent->updatePackage( GetEntryData( nPos )->m_xPackage ); + break; + case CMD_REMOVE: m_pParent->removePackage( GetEntryData( nPos )->m_xPackage ); + break; + } + } + else if ( rMEvt.IsLeft() ) + { + const SolarMutexGuard aGuard; + if ( rMEvt.IsMod1() && HasActive() ) + selectEntry( EXTENSION_LISTBOX_ENTRY_NOTFOUND ); // Selecting an not existing entry will deselect the current one + else + selectEntry( nPos ); + } +} + +//------------------------------------------------------------------------------ +long ExtBoxWithBtns_Impl::Notify( NotifyEvent& rNEvt ) +{ + bool bHandled = false; + + if ( rNEvt.GetType() == EVENT_KEYINPUT ) + { + const KeyEvent* pKEvt = rNEvt.GetKeyEvent(); + KeyCode aKeyCode = pKEvt->GetKeyCode(); + USHORT nKeyCode = aKeyCode.GetCode(); + + if ( nKeyCode == KEY_TAB ) + bHandled = HandleTabKey( aKeyCode.IsShift() ); + } + + if ( !bHandled ) + return ExtensionBox_Impl::Notify( rNEvt ); + else + return true; +} + +//------------------------------------------------------------------------------ +void ExtBoxWithBtns_Impl::enableButtons( bool bEnable ) +{ + m_bInterfaceLocked = ! bEnable; + + if ( bEnable ) + { + sal_Int32 nIndex = getSelIndex(); + if ( nIndex != EXTENSION_LISTBOX_ENTRY_NOTFOUND ) + SetButtonStatus( GetEntryData( nIndex ) ); + } + else + { + m_pOptionsBtn->Enable( false ); + m_pRemoveBtn->Enable( false ); + m_pEnableBtn->Enable( false ); + } +} + +// ----------------------------------------------------------------------- +IMPL_LINK( ExtBoxWithBtns_Impl, ScrollHdl, ScrollBar*, pScrBar ) +{ + long nDelta = pScrBar->GetDelta(); + + Point aNewOptPt( m_pOptionsBtn->GetPosPixel() - Point( 0, nDelta ) ); + Point aNewRemPt( m_pRemoveBtn->GetPosPixel() - Point( 0, nDelta ) ); + Point aNewEnPt( m_pEnableBtn->GetPosPixel() - Point( 0, nDelta ) ); + + DoScroll( nDelta ); + + m_pOptionsBtn->SetPosPixel( aNewOptPt ); + m_pRemoveBtn->SetPosPixel( aNewRemPt ); + m_pEnableBtn->SetPosPixel( aNewEnPt ); + + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( ExtBoxWithBtns_Impl, HandleOptionsBtn, void*, EMPTYARG ) +{ + const sal_Int32 nActive = getSelIndex(); + + if ( nActive != EXTENSION_LISTBOX_ENTRY_NOTFOUND ) + { + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + + if ( pFact ) + { + OUString sExtensionId = GetEntryData( nActive )->m_xPackage->getIdentifier().Value; + VclAbstractDialog* pDlg = pFact->CreateOptionsDialog( this, sExtensionId, rtl::OUString() ); + + pDlg->Execute(); + + delete pDlg; + } + } + + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( ExtBoxWithBtns_Impl, HandleEnableBtn, void*, EMPTYARG ) +{ + const sal_Int32 nActive = getSelIndex(); + + if ( nActive != EXTENSION_LISTBOX_ENTRY_NOTFOUND ) + { + TEntry_Impl pEntry = GetEntryData( nActive ); + + if ( pEntry->m_bMissingLic ) + m_pParent->acceptLicense( pEntry->m_xPackage ); + else + { + const bool bEnable( pEntry->m_eState != REGISTERED ); + m_pParent->enablePackage( pEntry->m_xPackage, bEnable ); + } + } + + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( ExtBoxWithBtns_Impl, HandleRemoveBtn, void*, EMPTYARG ) +{ + const sal_Int32 nActive = getSelIndex(); + + if ( nActive != EXTENSION_LISTBOX_ENTRY_NOTFOUND ) + { + TEntry_Impl pEntry = GetEntryData( nActive ); + m_pParent->removePackage( pEntry->m_xPackage ); + } + + return 1; +} + +//------------------------------------------------------------------------------ +// DialogHelper +//------------------------------------------------------------------------------ +DialogHelper::DialogHelper( const uno::Reference< uno::XComponentContext > &xContext, + Dialog *pWindow ) : + m_pVCLWindow( pWindow ), + m_nEventID( 0 ), + m_bIsBusy( false ) +{ + m_xContext = xContext; +} + +//------------------------------------------------------------------------------ +DialogHelper::~DialogHelper() +{ + if ( m_nEventID ) + Application::RemoveUserEvent( m_nEventID ); +} + +//------------------------------------------------------------------------------ +ResId DialogHelper::getResId( USHORT nId ) +{ + const SolarMutexGuard guard; + return ResId( nId, *DeploymentGuiResMgr::get() ); +} + +//------------------------------------------------------------------------------ +String DialogHelper::getResourceString( USHORT id ) +{ + // init with non-acquired solar mutex: + BrandName::get(); + const SolarMutexGuard guard; + String ret( ResId( id, *DeploymentGuiResMgr::get() ) ); + if (ret.SearchAscii( "%PRODUCTNAME" ) != STRING_NOTFOUND) { + ret.SearchAndReplaceAllAscii( "%PRODUCTNAME", BrandName::get() ); + } + return ret; +} + +//------------------------------------------------------------------------------ +bool DialogHelper::IsSharedPkgMgr( const uno::Reference< deployment::XPackage > &xPackage ) +{ + if ( xPackage->getRepositoryName().equals( OUSTR("shared") ) ) + return true; + else + return false; +} + +//------------------------------------------------------------------------------ +bool DialogHelper::continueOnSharedExtension( const uno::Reference< deployment::XPackage > &xPackage, + Window *pParent, + const USHORT nResID, + bool &bHadWarning ) +{ + if ( !bHadWarning && IsSharedPkgMgr( xPackage ) ) + { + const SolarMutexGuard guard; + WarningBox aInfoBox( pParent, getResId( nResID ) ); + String aMsgText = aInfoBox.GetMessText(); + aMsgText.SearchAndReplaceAllAscii( "%PRODUCTNAME", BrandName::get() ); + aInfoBox.SetMessText( aMsgText ); + + bHadWarning = true; + + if ( RET_OK == aInfoBox.Execute() ) + return true; + else + return false; + } + else + return true; +} + +//------------------------------------------------------------------------------ +void DialogHelper::openWebBrowser( const OUString & sURL, const OUString &sTitle ) const +{ + if ( ! sURL.getLength() ) // Nothing to do, when the URL is empty + return; + + try + { + uno::Reference< XSystemShellExecute > xSystemShellExecute( + m_xContext->getServiceManager()->createInstanceWithContext( OUSTR( "com.sun.star.system.SystemShellExecute" ), m_xContext), uno::UNO_QUERY_THROW); + //throws css::lang::IllegalArgumentException, css::system::SystemShellExecuteException + xSystemShellExecute->execute( sURL, OUString(), SystemShellExecuteFlags::DEFAULTS ); + } + catch ( uno::Exception& ) + { + uno::Any exc( ::cppu::getCaughtException() ); + OUString msg( ::comphelper::anyToString( exc ) ); + const SolarMutexGuard guard; + ErrorBox aErrorBox( NULL, WB_OK, msg ); + aErrorBox.SetText( sTitle ); + aErrorBox.Execute(); + } +} + +//------------------------------------------------------------------------------ +bool DialogHelper::installExtensionWarn( const OUString &rExtensionName ) const +{ + const SolarMutexGuard guard; + WarningBox aInfo( m_pVCLWindow, getResId( RID_WARNINGBOX_INSTALL_EXTENSION ) ); + + String sText( aInfo.GetMessText() ); + sText.SearchAndReplaceAllAscii( "%NAME", rExtensionName ); + aInfo.SetMessText( sText ); + + return ( RET_OK == aInfo.Execute() ); +} + +//------------------------------------------------------------------------------ +bool DialogHelper::installForAllUsers( bool &bInstallForAll ) const +{ + const SolarMutexGuard guard; + QueryBox aQuery( m_pVCLWindow, getResId( RID_QUERYBOX_INSTALL_FOR_ALL ) ); + + String sMsgText = aQuery.GetMessText(); + sMsgText.SearchAndReplaceAllAscii( "%PRODUCTNAME", BrandName::get() ); + aQuery.SetMessText( sMsgText ); + + USHORT nYesBtnID = aQuery.GetButtonId( 0 ); + USHORT nNoBtnID = aQuery.GetButtonId( 1 ); + + if ( nYesBtnID != BUTTONDIALOG_BUTTON_NOTFOUND ) + aQuery.SetButtonText( nYesBtnID, getResourceString( RID_STR_INSTALL_FOR_ME ) ); + if ( nNoBtnID != BUTTONDIALOG_BUTTON_NOTFOUND ) + aQuery.SetButtonText( nNoBtnID, getResourceString( RID_STR_INSTALL_FOR_ALL ) ); + + short nRet = aQuery.Execute(); + + if ( nRet == RET_CANCEL ) + return false; + + bInstallForAll = ( nRet == RET_NO ); + return true; +} + +//------------------------------------------------------------------------------ +void DialogHelper::PostUserEvent( const Link& rLink, void* pCaller ) +{ + if ( m_nEventID ) + Application::RemoveUserEvent( m_nEventID ); + + m_nEventID = Application::PostUserEvent( rLink, pCaller ); +} + +//------------------------------------------------------------------------------ +// ExtMgrDialog +//------------------------------------------------------------------------------ +ExtMgrDialog::ExtMgrDialog( Window *pParent, TheExtensionManager *pManager ) : + ModelessDialog( pParent, getResId( RID_DLG_EXTENSION_MANAGER ) ), + DialogHelper( pManager->getContext(), (Dialog*) this ), + m_aAddBtn( this, getResId( RID_EM_BTN_ADD ) ), + m_aUpdateBtn( this, getResId( RID_EM_BTN_CHECK_UPDATES ) ), + m_aCloseBtn( this, getResId( RID_EM_BTN_CLOSE ) ), + m_aHelpBtn( this, getResId( RID_EM_BTN_HELP ) ), + m_aDivider( this ), + m_aGetExtensions( this, getResId( RID_EM_FT_GET_EXTENSIONS ) ), + m_aProgressText( this, getResId( RID_EM_FT_PROGRESS ) ), + m_aProgressBar( this, WB_BORDER + WB_3DLOOK ), + m_aCancelBtn( this, getResId( RID_EM_BTN_CANCEL ) ), + m_sAddPackages( getResourceString( RID_STR_ADD_PACKAGES ) ), + m_bHasProgress( false ), + m_bProgressChanged( false ), + m_bStartProgress( false ), + m_bStopProgress( false ), + m_bUpdateWarning( false ), + m_bEnableWarning( false ), + m_bDisableWarning( false ), + m_bDeleteWarning( false ), + m_nProgress( 0 ), + m_pManager( pManager ) +{ + // free local resources (RID < 256): + FreeResource(); + + m_pExtensionBox = new ExtBoxWithBtns_Impl( this, pManager ); + m_pExtensionBox->SetHyperlinkHdl( LINK( this, ExtMgrDialog, HandleHyperlink ) ); + + m_aAddBtn.SetClickHdl( LINK( this, ExtMgrDialog, HandleAddBtn ) ); + m_aUpdateBtn.SetClickHdl( LINK( this, ExtMgrDialog, HandleUpdateBtn ) ); + m_aGetExtensions.SetClickHdl( LINK( this, ExtMgrDialog, HandleHyperlink ) ); + m_aCancelBtn.SetClickHdl( LINK( this, ExtMgrDialog, HandleCancelBtn ) ); + + // resize update button + Size aBtnSize = m_aUpdateBtn.GetSizePixel(); + String sTitle = m_aUpdateBtn.GetText(); + long nWidth = m_aUpdateBtn.GetCtrlTextWidth( sTitle ); + nWidth += 2 * m_aUpdateBtn.GetTextHeight(); + if ( nWidth > aBtnSize.Width() ) + m_aUpdateBtn.SetSizePixel( Size( nWidth, aBtnSize.Height() ) ); + + // minimum size: + SetMinOutputSizePixel( + Size( // width: + (3 * m_aHelpBtn.GetSizePixel().Width()) + + m_aUpdateBtn.GetSizePixel().Width() + + (5 * RSC_SP_DLG_INNERBORDER_LEFT ), + // height: + (1 * m_aHelpBtn.GetSizePixel().Height()) + + (1 * m_aGetExtensions.GetSizePixel().Height()) + + (1 * m_pExtensionBox->GetMinOutputSizePixel().Height()) + + (3 * RSC_SP_DLG_INNERBORDER_LEFT) ) ); + + m_aDivider.Show(); + m_aProgressBar.Hide(); + + m_aUpdateBtn.Enable( false ); + + m_aTimeoutTimer.SetTimeout( 500 ); // mSec + m_aTimeoutTimer.SetTimeoutHdl( LINK( this, ExtMgrDialog, TimeOutHdl ) ); +} + +//------------------------------------------------------------------------------ +ExtMgrDialog::~ExtMgrDialog() +{ + m_aTimeoutTimer.Stop(); + delete m_pExtensionBox; +} + +//------------------------------------------------------------------------------ +void ExtMgrDialog::setGetExtensionsURL( const ::rtl::OUString &rURL ) +{ + m_aGetExtensions.SetURL( rURL ); +} + +//------------------------------------------------------------------------------ +long ExtMgrDialog::addPackageToList( const uno::Reference< deployment::XPackage > &xPackage, + bool bLicenseMissing ) +{ + const SolarMutexGuard aGuard; + m_aUpdateBtn.Enable( true ); + return m_pExtensionBox->addEntry( xPackage, bLicenseMissing ); +} + +//------------------------------------------------------------------------------ +void ExtMgrDialog::prepareChecking() +{ + m_pExtensionBox->prepareChecking(); +} + +//------------------------------------------------------------------------------ +void ExtMgrDialog::checkEntries() +{ + const SolarMutexGuard guard; + m_pExtensionBox->checkEntries(); +} + +//------------------------------------------------------------------------------ +bool ExtMgrDialog::removeExtensionWarn( const OUString &rExtensionName ) const +{ + const SolarMutexGuard guard; + WarningBox aInfo( const_cast< ExtMgrDialog* >(this), getResId( RID_WARNINGBOX_REMOVE_EXTENSION ) ); + + String sText( aInfo.GetMessText() ); + sText.SearchAndReplaceAllAscii( "%NAME", rExtensionName ); + aInfo.SetMessText( sText ); + + return ( RET_OK == aInfo.Execute() ); +} + +//------------------------------------------------------------------------------ +bool ExtMgrDialog::enablePackage( const uno::Reference< deployment::XPackage > &xPackage, + bool bEnable ) +{ + if ( !xPackage.is() ) + return false; + + if ( bEnable ) + { + if ( ! continueOnSharedExtension( xPackage, this, RID_WARNINGBOX_ENABLE_SHARED_EXTENSION, m_bEnableWarning ) ) + return false; + } + else + { + if ( ! continueOnSharedExtension( xPackage, this, RID_WARNINGBOX_DISABLE_SHARED_EXTENSION, m_bDisableWarning ) ) + return false; + } + + m_pManager->getCmdQueue()->enableExtension( xPackage, bEnable ); + + return true; +} + +//------------------------------------------------------------------------------ +bool ExtMgrDialog::removePackage( const uno::Reference< deployment::XPackage > &xPackage ) +{ + if ( !xPackage.is() ) + return false; + + if ( !IsSharedPkgMgr( xPackage ) || m_bDeleteWarning ) + { + if ( ! removeExtensionWarn( xPackage->getDisplayName() ) ) + return false; + } + + if ( ! continueOnSharedExtension( xPackage, this, RID_WARNINGBOX_REMOVE_SHARED_EXTENSION, m_bDeleteWarning ) ) + return false; + + m_pManager->getCmdQueue()->removeExtension( xPackage ); + + return true; +} + +//------------------------------------------------------------------------------ +bool ExtMgrDialog::updatePackage( const uno::Reference< deployment::XPackage > &xPackage ) +{ + if ( !xPackage.is() ) + return false; + + // get the extension with highest version + uno::Sequence<uno::Reference<deployment::XPackage> > seqExtensions = + m_pManager->getExtensionManager()->getExtensionsWithSameIdentifier( + dp_misc::getIdentifier(xPackage), xPackage->getName(), uno::Reference<ucb::XCommandEnvironment>()); + uno::Reference<deployment::XPackage> extension = + dp_misc::getExtensionWithHighestVersion(seqExtensions); + OSL_ASSERT(extension.is()); + std::vector< css::uno::Reference< css::deployment::XPackage > > vEntries; + vEntries.push_back(extension); + + m_pManager->getCmdQueue()->checkForUpdates( vEntries ); + + return true; +} + +//------------------------------------------------------------------------------ +bool ExtMgrDialog::acceptLicense( const uno::Reference< deployment::XPackage > &xPackage ) +{ + if ( !xPackage.is() ) + return false; + + m_pManager->getCmdQueue()->acceptLicense( xPackage ); + + return true; +} + +//------------------------------------------------------------------------------ +uno::Sequence< OUString > ExtMgrDialog::raiseAddPicker() +{ + const uno::Any mode( static_cast< sal_Int16 >( ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE ) ); + const uno::Reference< uno::XComponentContext > xContext( m_pManager->getContext() ); + const uno::Reference< ui::dialogs::XFilePicker > xFilePicker( + xContext->getServiceManager()->createInstanceWithArgumentsAndContext( + OUSTR("com.sun.star.ui.dialogs.FilePicker"), + uno::Sequence< uno::Any >( &mode, 1 ), xContext ), uno::UNO_QUERY_THROW ); + xFilePicker->setTitle( m_sAddPackages ); + + if ( m_sLastFolderURL.Len() ) + xFilePicker->setDisplayDirectory( m_sLastFolderURL ); + + // collect and set filter list: + typedef ::std::map< OUString, OUString > t_string2string; + t_string2string title2filter; + OUString sDefaultFilter( StrAllFiles::get() ); + + const uno::Sequence< uno::Reference< deployment::XPackageTypeInfo > > packageTypes( + m_pManager->getExtensionManager()->getSupportedPackageTypes() ); + + for ( sal_Int32 pos = 0; pos < packageTypes.getLength(); ++pos ) + { + uno::Reference< deployment::XPackageTypeInfo > const & xPackageType = packageTypes[ pos ]; + const OUString filter( xPackageType->getFileFilter() ); + if (filter.getLength() > 0) + { + const OUString title( xPackageType->getShortDescription() ); + const ::std::pair< t_string2string::iterator, bool > insertion( + title2filter.insert( t_string2string::value_type( title, filter ) ) ); + if ( ! insertion.second ) + { // already existing, append extensions: + ::rtl::OUStringBuffer buf; + buf.append( insertion.first->second ); + buf.append( static_cast<sal_Unicode>(';') ); + buf.append( filter ); + insertion.first->second = buf.makeStringAndClear(); + } + if ( xPackageType->getMediaType() == OUSTR( "application/vnd.sun.star.package-bundle" ) ) + sDefaultFilter = title; + } + } + + const uno::Reference< ui::dialogs::XFilterManager > xFilterManager( xFilePicker, uno::UNO_QUERY_THROW ); + // All files at top: + xFilterManager->appendFilter( StrAllFiles::get(), OUSTR("*.*") ); + // then supported ones: + t_string2string::const_iterator iPos( title2filter.begin() ); + const t_string2string::const_iterator iEnd( title2filter.end() ); + for ( ; iPos != iEnd; ++iPos ) { + try { + xFilterManager->appendFilter( iPos->first, iPos->second ); + } + catch (lang::IllegalArgumentException & exc) { + OSL_ENSURE( 0, ::rtl::OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + (void) exc; + } + } + xFilterManager->setCurrentFilter( sDefaultFilter ); + + if ( xFilePicker->execute() != ui::dialogs::ExecutableDialogResults::OK ) + return uno::Sequence<OUString>(); // cancelled + + m_sLastFolderURL = xFilePicker->getDisplayDirectory(); + uno::Sequence< OUString > files( xFilePicker->getFiles() ); + OSL_ASSERT( files.getLength() > 0 ); + return files; +} + +//------------------------------------------------------------------------------ +IMPL_LINK( ExtMgrDialog, HandleCancelBtn, void*, EMPTYARG ) +{ + // m_dialog->m_cmdEnv->m_aborted = true; + if ( m_xAbortChannel.is() ) + { + try + { + m_xAbortChannel->sendAbort(); + } + catch ( uno::RuntimeException & ) + { + OSL_ENSURE( 0, "### unexpected RuntimeException!" ); + } + } + return 1; +} + +// ------------------------------------------------------------------------------ +IMPL_LINK( ExtMgrDialog, startProgress, void*, _bLockInterface ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + bool bLockInterface = (bool) _bLockInterface; + + if ( m_bStartProgress && !m_bHasProgress ) + m_aTimeoutTimer.Start(); + + if ( m_bStopProgress ) + { + if ( m_aProgressBar.IsVisible() ) + m_aProgressBar.SetValue( 100 ); + m_xAbortChannel.clear(); + + OSL_TRACE( " startProgress handler: stop\n" ); + } + else + { + OSL_TRACE( " startProgress handler: start\n" ); + } + + m_aCancelBtn.Enable( bLockInterface ); + m_aAddBtn.Enable( !bLockInterface ); + m_aUpdateBtn.Enable( !bLockInterface && m_pExtensionBox->getItemCount() ); + m_pExtensionBox->enableButtons( !bLockInterface ); + + clearEventID(); + + return 0; +} + +// ------------------------------------------------------------------------------ +void ExtMgrDialog::showProgress( bool _bStart ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + bool bStart = _bStart; + + if ( bStart ) + { + m_nProgress = 0; + m_bStartProgress = true; + OSL_TRACE( "showProgress start\n" ); + } + else + { + m_nProgress = 100; + m_bStopProgress = true; + OSL_TRACE( "showProgress stop!\n" ); + } + + DialogHelper::PostUserEvent( LINK( this, ExtMgrDialog, startProgress ), (void*) bStart ); +} + +// ----------------------------------------------------------------------- +void ExtMgrDialog::updateProgress( const long nProgress ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + m_nProgress = nProgress; +} + +// ----------------------------------------------------------------------- +void ExtMgrDialog::updateProgress( const OUString &rText, + const uno::Reference< task::XAbortChannel > &xAbortChannel) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + m_xAbortChannel = xAbortChannel; + m_sProgressText = rText; + m_bProgressChanged = true; +} + +//------------------------------------------------------------------------------ +void ExtMgrDialog::updatePackageInfo( const uno::Reference< deployment::XPackage > &xPackage ) +{ + const SolarMutexGuard aGuard; + m_pExtensionBox->updateEntry( xPackage ); +} + +// ----------------------------------------------------------------------- +IMPL_LINK( ExtMgrDialog, HandleAddBtn, void*, EMPTYARG ) +{ + setBusy( true ); + + uno::Sequence< OUString > aFileList = raiseAddPicker(); + + if ( aFileList.getLength() ) + { + m_pManager->installPackage( aFileList[0] ); + } + + setBusy( false ); + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( ExtMgrDialog, HandleUpdateBtn, void*, EMPTYARG ) +{ + m_pManager->checkUpdates( false, true ); + + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( ExtMgrDialog, HandleHyperlink, svt::FixedHyperlink*, pHyperlink ) +{ + openWebBrowser( pHyperlink->GetURL(), GetText() ); + + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( ExtMgrDialog, TimeOutHdl, Timer*, EMPTYARG ) +{ + if ( m_bStopProgress ) + { + m_bHasProgress = false; + m_bStopProgress = false; + m_aProgressText.Hide(); + m_aProgressBar.Hide(); + m_aCancelBtn.Hide(); + } + else + { + if ( m_bProgressChanged ) + { + m_bProgressChanged = false; + m_aProgressText.SetText( m_sProgressText ); + } + + if ( m_bStartProgress ) + { + m_bStartProgress = false; + m_bHasProgress = true; + m_aProgressBar.Show(); + m_aProgressText.Show(); + m_aCancelBtn.Enable(); + m_aCancelBtn.Show(); + } + + if ( m_aProgressBar.IsVisible() ) + m_aProgressBar.SetValue( (USHORT) m_nProgress ); + + m_aTimeoutTimer.Start(); + } + + return 1; +} + +//------------------------------------------------------------------------------ +// VCL::Window / Dialog +void ExtMgrDialog::Resize() +{ + Size aTotalSize( GetOutputSizePixel() ); + Size aBtnSize( m_aHelpBtn.GetSizePixel() ); + Size aUpdBtnSize( m_aUpdateBtn.GetSizePixel() ); + + Point aPos( RSC_SP_DLG_INNERBORDER_LEFT, + aTotalSize.Height() - RSC_SP_DLG_INNERBORDER_BOTTOM - aBtnSize.Height() ); + + m_aHelpBtn.SetPosPixel( aPos ); + + aPos.X() = aTotalSize.Width() - RSC_SP_DLG_INNERBORDER_RIGHT - aBtnSize.Width(); + m_aCloseBtn.SetPosPixel( aPos ); + + aPos.X() -= ( RSC_SP_CTRL_X + aUpdBtnSize.Width() ); + m_aUpdateBtn.SetPosPixel( aPos ); + + aPos.X() -= ( RSC_SP_CTRL_GROUP_Y + aBtnSize.Width() ); + m_aAddBtn.SetPosPixel( aPos ); + + Size aDivSize( aTotalSize.Width(), LINE_SIZE ); + aPos = Point( 0, aPos.Y() - LINE_SIZE - RSC_SP_DLG_INNERBORDER_BOTTOM ); + m_aDivider.SetPosSizePixel( aPos, aDivSize ); + + Size aFTSize( m_aGetExtensions.CalcMinimumSize() ); + aPos = Point( RSC_SP_DLG_INNERBORDER_LEFT, aPos.Y() - RSC_CD_FIXEDTEXT_HEIGHT - 2*RSC_SP_DLG_INNERBORDER_BOTTOM ); + + m_aGetExtensions.SetPosSizePixel( aPos, aFTSize ); + + aPos.X() = aTotalSize.Width() - RSC_SP_DLG_INNERBORDER_RIGHT - aBtnSize.Width(); + m_aCancelBtn.SetPosPixel( Point( aPos.X(), aPos.Y() - ((aBtnSize.Height()-aFTSize.Height())/2) ) ); + + // Calc progress height + long nProgressHeight = aFTSize.Height(); + + if( IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) ) + { + ImplControlValue aValue; + bool bNativeOK; + Rectangle aControlRegion( Point( 0, 0 ), m_aProgressBar.GetSizePixel() ); + Rectangle aNativeControlRegion, aNativeContentRegion; + if( (bNativeOK = GetNativeControlRegion( CTRL_PROGRESS, PART_ENTIRE_CONTROL, aControlRegion, + CTRL_STATE_ENABLED, aValue, rtl::OUString(), + aNativeControlRegion, aNativeContentRegion ) ) != FALSE ) + { + nProgressHeight = aNativeControlRegion.GetHeight(); + } + } + + if ( nProgressHeight < PROGRESS_HEIGHT ) + nProgressHeight = PROGRESS_HEIGHT; + + aPos.X() -= ( RSC_SP_CTRL_GROUP_Y + PROGRESS_WIDTH ); + m_aProgressBar.SetPosSizePixel( Point( aPos.X(), aPos.Y() - ((nProgressHeight-aFTSize.Height())/2) ), + Size( PROGRESS_WIDTH, nProgressHeight ) ); + + Rectangle aRect1( m_aGetExtensions.GetPosPixel(), m_aGetExtensions.GetSizePixel() ); + Rectangle aRect2( m_aProgressBar.GetPosPixel(), m_aProgressBar.GetSizePixel() ); + + aFTSize.Width() = ( aRect2.Left() - aRect1.Right() ) - 2*RSC_SP_DLG_INNERBORDER_LEFT; + aPos.X() = aRect1.Right() + RSC_SP_DLG_INNERBORDER_LEFT; + m_aProgressText.SetPosSizePixel( aPos, aFTSize ); + + Size aSize( aTotalSize.Width() - RSC_SP_DLG_INNERBORDER_LEFT - RSC_SP_DLG_INNERBORDER_RIGHT, + aTotalSize.Height() - 2*aBtnSize.Height() - LINE_SIZE - + RSC_SP_DLG_INNERBORDER_TOP - 3*RSC_SP_DLG_INNERBORDER_BOTTOM ); + + m_pExtensionBox->SetSizePixel( aSize ); +} +//------------------------------------------------------------------------------ +// VCL::Window / Dialog + +long ExtMgrDialog::Notify( NotifyEvent& rNEvt ) +{ + bool bHandled = false; + + if ( rNEvt.GetType() == EVENT_KEYINPUT ) + { + const KeyEvent* pKEvt = rNEvt.GetKeyEvent(); + KeyCode aKeyCode = pKEvt->GetKeyCode(); + USHORT nKeyCode = aKeyCode.GetCode(); + + if ( nKeyCode == KEY_TAB ) + { + if ( aKeyCode.IsShift() ) { + if ( m_aAddBtn.HasFocus() ) { + m_pExtensionBox->GrabFocus(); + bHandled = true; + } + } else { + if ( m_aGetExtensions.HasFocus() ) { + m_pExtensionBox->GrabFocus(); + bHandled = true; + } + } + } + if ( aKeyCode.GetGroup() == KEYGROUP_CURSOR ) + bHandled = m_pExtensionBox->Notify( rNEvt ); + } +// VCLEVENT_WINDOW_CLOSE + if ( !bHandled ) + return ModelessDialog::Notify( rNEvt ); + else + return true; +} + +//------------------------------------------------------------------------------ +BOOL ExtMgrDialog::Close() +{ + bool bRet = m_pManager->queryTermination(); + if ( bRet ) + { + bRet = ModelessDialog::Close(); + m_pManager->terminateDialog(); + } + return bRet; +} + +//------------------------------------------------------------------------------ +// UpdateRequiredDialog +//------------------------------------------------------------------------------ +UpdateRequiredDialog::UpdateRequiredDialog( Window *pParent, TheExtensionManager *pManager ) : + ModalDialog( pParent, getResId( RID_DLG_UPDATE_REQUIRED ) ), + DialogHelper( pManager->getContext(), (Dialog*) this ), + m_aUpdateNeeded( this, getResId( RID_EM_FT_MSG ) ), + m_aUpdateBtn( this, getResId( RID_EM_BTN_CHECK_UPDATES ) ), + m_aCloseBtn( this, getResId( RID_EM_BTN_CLOSE ) ), + m_aHelpBtn( this, getResId( RID_EM_BTN_HELP ) ), + m_aCancelBtn( this, getResId( RID_EM_BTN_CANCEL ) ), + m_aDivider( this ), + m_aProgressText( this, getResId( RID_EM_FT_PROGRESS ) ), + m_aProgressBar( this, WB_BORDER + WB_3DLOOK ), + m_sAddPackages( getResourceString( RID_STR_ADD_PACKAGES ) ), + m_sCloseText( getResourceString( RID_STR_CLOSE_BTN ) ), + m_bHasProgress( false ), + m_bProgressChanged( false ), + m_bStartProgress( false ), + m_bStopProgress( false ), + m_bUpdateWarning( false ), + m_bDisableWarning( false ), + m_bHasLockedEntries( false ), + m_nProgress( 0 ), + m_pManager( pManager ) +{ + // free local resources (RID < 256): + FreeResource(); + + m_pExtensionBox = new ExtensionBox_Impl( this, pManager ); + m_pExtensionBox->SetHyperlinkHdl( LINK( this, UpdateRequiredDialog, HandleHyperlink ) ); + + m_aUpdateBtn.SetClickHdl( LINK( this, UpdateRequiredDialog, HandleUpdateBtn ) ); + m_aCloseBtn.SetClickHdl( LINK( this, UpdateRequiredDialog, HandleCloseBtn ) ); + m_aCancelBtn.SetClickHdl( LINK( this, UpdateRequiredDialog, HandleCancelBtn ) ); + + String aText = m_aUpdateNeeded.GetText(); + aText.SearchAndReplaceAllAscii( "%PRODUCTNAME", BrandName::get() ); + m_aUpdateNeeded.SetText( aText ); + + // resize update button + Size aBtnSize = m_aUpdateBtn.GetSizePixel(); + String sTitle = m_aUpdateBtn.GetText(); + long nWidth = m_aUpdateBtn.GetCtrlTextWidth( sTitle ); + nWidth += 2 * m_aUpdateBtn.GetTextHeight(); + if ( nWidth > aBtnSize.Width() ) + m_aUpdateBtn.SetSizePixel( Size( nWidth, aBtnSize.Height() ) ); + + // resize update button + aBtnSize = m_aCloseBtn.GetSizePixel(); + sTitle = m_aCloseBtn.GetText(); + nWidth = m_aCloseBtn.GetCtrlTextWidth( sTitle ); + nWidth += 2 * m_aCloseBtn.GetTextHeight(); + if ( nWidth > aBtnSize.Width() ) + m_aCloseBtn.SetSizePixel( Size( nWidth, aBtnSize.Height() ) ); + + // minimum size: + SetMinOutputSizePixel( + Size( // width: + (5 * m_aHelpBtn.GetSizePixel().Width()) + + (5 * RSC_SP_DLG_INNERBORDER_LEFT ), + // height: + (1 * m_aHelpBtn.GetSizePixel().Height()) + + (1 * m_aUpdateNeeded.GetSizePixel().Height()) + + (1 * m_pExtensionBox->GetMinOutputSizePixel().Height()) + + (3 * RSC_SP_DLG_INNERBORDER_LEFT) ) ); + + m_aDivider.Show(); + m_aProgressBar.Hide(); + m_aUpdateBtn.Enable( false ); + m_aCloseBtn.GrabFocus(); + + m_aTimeoutTimer.SetTimeout( 50 ); // mSec + m_aTimeoutTimer.SetTimeoutHdl( LINK( this, UpdateRequiredDialog, TimeOutHdl ) ); +} + +//------------------------------------------------------------------------------ +UpdateRequiredDialog::~UpdateRequiredDialog() +{ + m_aTimeoutTimer.Stop(); + + delete m_pExtensionBox; +} + +//------------------------------------------------------------------------------ +long UpdateRequiredDialog::addPackageToList( const uno::Reference< deployment::XPackage > &xPackage, + bool bLicenseMissing ) +{ + // We will only add entries to the list with unsatisfied dependencies + if ( !bLicenseMissing && !checkDependencies( xPackage ) ) + { + m_bHasLockedEntries |= m_pManager->isReadOnly( xPackage ); + const SolarMutexGuard aGuard; + m_aUpdateBtn.Enable( true ); + return m_pExtensionBox->addEntry( xPackage ); + } + return 0; +} + +//------------------------------------------------------------------------------ +void UpdateRequiredDialog::prepareChecking() +{ + m_pExtensionBox->prepareChecking(); +} + +//------------------------------------------------------------------------------ +void UpdateRequiredDialog::checkEntries() +{ + const SolarMutexGuard guard; + m_pExtensionBox->checkEntries(); + + if ( ! hasActiveEntries() ) + { + m_aCloseBtn.SetText( m_sCloseText ); + m_aCloseBtn.GrabFocus(); + } +} + +//------------------------------------------------------------------------------ +bool UpdateRequiredDialog::enablePackage( const uno::Reference< deployment::XPackage > &xPackage, + bool bEnable ) +{ + m_pManager->getCmdQueue()->enableExtension( xPackage, bEnable ); + + return true; +} + +//------------------------------------------------------------------------------ +IMPL_LINK( UpdateRequiredDialog, HandleCancelBtn, void*, EMPTYARG ) +{ + // m_dialog->m_cmdEnv->m_aborted = true; + if ( m_xAbortChannel.is() ) + { + try + { + m_xAbortChannel->sendAbort(); + } + catch ( uno::RuntimeException & ) + { + OSL_ENSURE( 0, "### unexpected RuntimeException!" ); + } + } + return 1; +} + +// ------------------------------------------------------------------------------ +IMPL_LINK( UpdateRequiredDialog, startProgress, void*, _bLockInterface ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + bool bLockInterface = (bool) _bLockInterface; + + if ( m_bStartProgress && !m_bHasProgress ) + m_aTimeoutTimer.Start(); + + if ( m_bStopProgress ) + { + if ( m_aProgressBar.IsVisible() ) + m_aProgressBar.SetValue( 100 ); + m_xAbortChannel.clear(); + OSL_TRACE( " startProgress handler: stop\n" ); + } + else + { + OSL_TRACE( " startProgress handler: start\n" ); + } + + m_aCancelBtn.Enable( bLockInterface ); + m_aUpdateBtn.Enable( false ); + clearEventID(); + + return 0; +} + +// ------------------------------------------------------------------------------ +void UpdateRequiredDialog::showProgress( bool _bStart ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + bool bStart = _bStart; + + if ( bStart ) + { + m_nProgress = 0; + m_bStartProgress = true; + OSL_TRACE( "showProgress start\n" ); + } + else + { + m_nProgress = 100; + m_bStopProgress = true; + OSL_TRACE( "showProgress stop!\n" ); + } + + DialogHelper::PostUserEvent( LINK( this, UpdateRequiredDialog, startProgress ), (void*) bStart ); +} + +// ----------------------------------------------------------------------- +void UpdateRequiredDialog::updateProgress( const long nProgress ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + m_nProgress = nProgress; +} + +// ----------------------------------------------------------------------- +void UpdateRequiredDialog::updateProgress( const OUString &rText, + const uno::Reference< task::XAbortChannel > &xAbortChannel) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + m_xAbortChannel = xAbortChannel; + m_sProgressText = rText; + m_bProgressChanged = true; +} + +//------------------------------------------------------------------------------ +void UpdateRequiredDialog::updatePackageInfo( const uno::Reference< deployment::XPackage > &xPackage ) +{ + // We will remove all updated packages with satisfied dependencies, but + // we will show all disabled entries so the user sees the result + // of the 'disable all' button + const SolarMutexGuard aGuard; + if ( isEnabled( xPackage ) && checkDependencies( xPackage ) ) + m_pExtensionBox->removeEntry( xPackage ); + else + m_pExtensionBox->updateEntry( xPackage ); + + if ( ! hasActiveEntries() ) + { + m_aCloseBtn.SetText( m_sCloseText ); + m_aCloseBtn.GrabFocus(); + } +} + +// ----------------------------------------------------------------------- +IMPL_LINK( UpdateRequiredDialog, HandleUpdateBtn, void*, EMPTYARG ) +{ + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + std::vector< uno::Reference< deployment::XPackage > > vUpdateEntries; + sal_Int32 nCount = m_pExtensionBox->GetEntryCount(); + + for ( sal_Int32 i = 0; i < nCount; ++i ) + { + TEntry_Impl pEntry = m_pExtensionBox->GetEntryData( i ); + vUpdateEntries.push_back( pEntry->m_xPackage ); + } + + aGuard.clear(); + + m_pManager->getCmdQueue()->checkForUpdates( vUpdateEntries ); + + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( UpdateRequiredDialog, HandleCloseBtn, void*, EMPTYARG ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !isBusy() ) + { + if ( m_bHasLockedEntries ) + EndDialog( -1 ); + else if ( hasActiveEntries() ) + disableAllEntries(); + else + EndDialog( 0 ); + } + + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( UpdateRequiredDialog, HandleHyperlink, svt::FixedHyperlink*, pHyperlink ) +{ + openWebBrowser( pHyperlink->GetURL(), GetText() ); + + return 1; +} + +// ----------------------------------------------------------------------- +IMPL_LINK( UpdateRequiredDialog, TimeOutHdl, Timer*, EMPTYARG ) +{ + if ( m_bStopProgress ) + { + m_bHasProgress = false; + m_bStopProgress = false; + m_aProgressText.Hide(); + m_aProgressBar.Hide(); + m_aCancelBtn.Hide(); + } + else + { + if ( m_bProgressChanged ) + { + m_bProgressChanged = false; + m_aProgressText.SetText( m_sProgressText ); + } + + if ( m_bStartProgress ) + { + m_bStartProgress = false; + m_bHasProgress = true; + m_aProgressBar.Show(); + m_aProgressText.Show(); + m_aCancelBtn.Enable(); + m_aCancelBtn.Show(); + } + + if ( m_aProgressBar.IsVisible() ) + m_aProgressBar.SetValue( (USHORT) m_nProgress ); + + m_aTimeoutTimer.Start(); + } + + return 1; +} + +//------------------------------------------------------------------------------ +// VCL::Window / Dialog +void UpdateRequiredDialog::Resize() +{ + Size aTotalSize( GetOutputSizePixel() ); + Size aBtnSize( m_aHelpBtn.GetSizePixel() ); + + Point aPos( RSC_SP_DLG_INNERBORDER_LEFT, + aTotalSize.Height() - RSC_SP_DLG_INNERBORDER_BOTTOM - aBtnSize.Height() ); + + m_aHelpBtn.SetPosPixel( aPos ); + + aPos.X() = aTotalSize.Width() - RSC_SP_DLG_INNERBORDER_RIGHT - m_aCloseBtn.GetSizePixel().Width(); + m_aCloseBtn.SetPosPixel( aPos ); + + aPos.X() -= ( RSC_SP_CTRL_X + m_aUpdateBtn.GetSizePixel().Width() ); + m_aUpdateBtn.SetPosPixel( aPos ); + + Size aDivSize( aTotalSize.Width(), LINE_SIZE ); + aPos = Point( 0, aPos.Y() - LINE_SIZE - RSC_SP_DLG_INNERBORDER_BOTTOM ); + m_aDivider.SetPosSizePixel( aPos, aDivSize ); + + // Calc fixed text size + aPos = Point( RSC_SP_DLG_INNERBORDER_LEFT, RSC_SP_DLG_INNERBORDER_TOP ); + Size aFTSize = m_aUpdateNeeded.CalcMinimumSize( aTotalSize.Width() - RSC_SP_DLG_INNERBORDER_RIGHT - RSC_SP_DLG_INNERBORDER_LEFT ); + m_aUpdateNeeded.SetPosSizePixel( aPos, aFTSize ); + + // Calc list box size + Size aSize( aTotalSize.Width() - RSC_SP_DLG_INNERBORDER_LEFT - RSC_SP_DLG_INNERBORDER_RIGHT, + aTotalSize.Height() - 2*aBtnSize.Height() - LINE_SIZE - + 2*RSC_SP_DLG_INNERBORDER_TOP - 3*RSC_SP_DLG_INNERBORDER_BOTTOM - aFTSize.Height() ); + aPos.Y() += aFTSize.Height()+RSC_SP_DLG_INNERBORDER_TOP; + + m_pExtensionBox->SetPosSizePixel( aPos, aSize ); + + aPos.X() = aTotalSize.Width() - RSC_SP_DLG_INNERBORDER_RIGHT - aBtnSize.Width(); + aPos.Y() += aSize.Height()+RSC_SP_DLG_INNERBORDER_TOP; + m_aCancelBtn.SetPosPixel( aPos ); + + // Calc progress height + aFTSize = m_aProgressText.GetSizePixel(); + long nProgressHeight = aFTSize.Height(); + + if( IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) ) + { + ImplControlValue aValue; + bool bNativeOK; + Rectangle aControlRegion( Point( 0, 0 ), m_aProgressBar.GetSizePixel() ); + Rectangle aNativeControlRegion, aNativeContentRegion; + if( (bNativeOK = GetNativeControlRegion( CTRL_PROGRESS, PART_ENTIRE_CONTROL, aControlRegion, + CTRL_STATE_ENABLED, aValue, rtl::OUString(), + aNativeControlRegion, aNativeContentRegion ) ) != FALSE ) + { + nProgressHeight = aNativeControlRegion.GetHeight(); + } + } + + if ( nProgressHeight < PROGRESS_HEIGHT ) + nProgressHeight = PROGRESS_HEIGHT; + + aPos.X() -= ( RSC_SP_CTRL_GROUP_Y + PROGRESS_WIDTH ); + m_aProgressBar.SetPosSizePixel( Point( aPos.X(), aPos.Y() + ((aBtnSize.Height()-nProgressHeight)/2) ), + Size( PROGRESS_WIDTH, nProgressHeight ) ); + + aFTSize.Width() = aPos.X() - 2*RSC_SP_DLG_INNERBORDER_LEFT; + aPos.X() = RSC_SP_DLG_INNERBORDER_LEFT; + aPos.Y() += ( aBtnSize.Height() - aFTSize.Height() - 1 ) / 2; + m_aProgressText.SetPosSizePixel( aPos, aFTSize ); +} + +//------------------------------------------------------------------------------ +// VCL::Dialog +short UpdateRequiredDialog::Execute() +{ + if ( m_bHasLockedEntries ) + { + // Set other text, disable update btn, remove not shared entries from list; + m_aUpdateNeeded.SetText( DialogHelper::getResourceString( RID_STR_NO_ADMIN_PRIVILEGE ) ); + m_aCloseBtn.SetText( DialogHelper::getResourceString( RID_STR_EXIT_BTN ) ); + m_aUpdateBtn.Enable( false ); + m_pExtensionBox->RemoveUnlocked(); + Resize(); + } + + return Dialog::Execute(); +} + +//------------------------------------------------------------------------------ +// VCL::Dialog +BOOL UpdateRequiredDialog::Close() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !isBusy() ) + { + if ( m_bHasLockedEntries ) + EndDialog( -1 ); + else if ( hasActiveEntries() ) + disableAllEntries(); + else + EndDialog( 0 ); + } + + return false; +} + +//------------------------------------------------------------------------------ +// Check dependencies of all packages +//------------------------------------------------------------------------------ +bool UpdateRequiredDialog::isEnabled( const uno::Reference< deployment::XPackage > &xPackage ) const +{ + 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() ); + bRegistered = false; + } + + return bRegistered; +} + +//------------------------------------------------------------------------------ +bool UpdateRequiredDialog::checkDependencies( const uno::Reference< deployment::XPackage > &xPackage ) const +{ + if ( isEnabled( xPackage ) ) + { + bool bDependenciesValid = false; + try { + bDependenciesValid = xPackage->checkDependencies( uno::Reference< ucb::XCommandEnvironment >() ); + } + catch ( deployment::DeploymentException & ) {} + if ( ! bDependenciesValid ) + { + return false; + } + } + return true; +} + +//------------------------------------------------------------------------------ +bool UpdateRequiredDialog::hasActiveEntries() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + bool bRet = false; + long nCount = m_pExtensionBox->GetEntryCount(); + for ( long nIndex = 0; nIndex < nCount; nIndex++ ) + { + TEntry_Impl pEntry = m_pExtensionBox->GetEntryData( nIndex ); + + if ( !checkDependencies( pEntry->m_xPackage ) ) + { + bRet = true; + break; + } + } + + return bRet; +} + +//------------------------------------------------------------------------------ +void UpdateRequiredDialog::disableAllEntries() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + setBusy( true ); + + long nCount = m_pExtensionBox->GetEntryCount(); + for ( long nIndex = 0; nIndex < nCount; nIndex++ ) + { + TEntry_Impl pEntry = m_pExtensionBox->GetEntryData( nIndex ); + enablePackage( pEntry->m_xPackage, false ); + } + + setBusy( false ); + + if ( ! hasActiveEntries() ) + m_aCloseBtn.SetText( m_sCloseText ); +} + +//================================================================================= +// UpdateRequiredDialogService +//================================================================================= +UpdateRequiredDialogService::UpdateRequiredDialogService( uno::Sequence< uno::Any > const&, + uno::Reference< uno::XComponentContext > const& xComponentContext ) + : m_xComponentContext( xComponentContext ) +{ +} + +//------------------------------------------------------------------------------ +// XExecutableDialog +//------------------------------------------------------------------------------ +void UpdateRequiredDialogService::setTitle( OUString const & ) throw ( uno::RuntimeException ) +{ +} + +//------------------------------------------------------------------------------ +sal_Int16 UpdateRequiredDialogService::execute() throw ( uno::RuntimeException ) +{ + ::rtl::Reference< ::dp_gui::TheExtensionManager > xManager( TheExtensionManager::get( + m_xComponentContext, + uno::Reference< awt::XWindow >(), + OUString() ) ); + xManager->createDialog( true ); + sal_Int16 nRet = xManager->execute(); + + return nRet; +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +SelectedPackage::~SelectedPackage() {} + +} //namespace dp_gui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_dialog2.hxx b/desktop/source/deployment/gui/dp_gui_dialog2.hxx new file mode 100644 index 000000000000..bb8c9785d91b --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_dialog2.hxx @@ -0,0 +1,269 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_DP_GUI_DIALOG2_HXX +#define INCLUDED_DP_GUI_DIALOG2_HXX + +#include "vcl/dialog.hxx" +#include "vcl/button.hxx" +#include "vcl/fixed.hxx" +#include "vcl/timer.hxx" + +#include "svtools/fixedhyper.hxx" +#include "svtools/prgsbar.hxx" + +#include "osl/conditn.hxx" +#include "osl/mutex.hxx" + +#include "rtl/ref.hxx" +#include "rtl/ustring.hxx" + +#include "cppuhelper/implbase1.hxx" + +#include "com/sun/star/awt/XWindow.hpp" +#include "com/sun/star/deployment/XPackage.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/ui/dialogs/XExecutableDialog.hpp" +#include "com/sun/star/util/XModifyListener.hpp" + +namespace dp_gui { + +//============================================================================== +class ExtBoxWithBtns_Impl; +class ExtensionBox_Impl; +class TheExtensionManager; + +//============================================================================== +class DialogHelper +{ + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_xContext; + Dialog* m_pVCLWindow; + ULONG m_nEventID; + bool m_bIsBusy; + +public: + DialogHelper( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > &, + Dialog *pWindow ); + virtual ~DialogHelper(); + + void openWebBrowser( const ::rtl::OUString & sURL, const ::rtl::OUString & sTitle ) const; + Dialog* getWindow() const { return m_pVCLWindow; }; + void PostUserEvent( const Link& rLink, void* pCaller ); + void clearEventID() { m_nEventID = 0; } + + virtual void showProgress( bool bStart ) = 0; + virtual void updateProgress( const ::rtl::OUString &rText, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XAbortChannel > &xAbortChannel) = 0; + virtual void updateProgress( const long nProgress ) = 0; + + virtual void updatePackageInfo( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ) = 0; + virtual long addPackageToList( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage, + bool bLicenseMissing = false ) = 0; + + virtual void prepareChecking() = 0; + virtual void checkEntries() = 0; + + static ResId getResId( USHORT nId ); + static String getResourceString( USHORT id ); + static bool IsSharedPkgMgr( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &); + static bool continueOnSharedExtension( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &, + Window *pParent, + const USHORT nResID, + bool &bHadWarning ); + + void setBusy( const bool bBusy ) { m_bIsBusy = bBusy; } + bool isBusy() const { return m_bIsBusy; } + bool installExtensionWarn( const ::rtl::OUString &rExtensionURL ) const; + bool installForAllUsers( bool &bInstallForAll ) const; +}; + +//============================================================================== +class ExtMgrDialog : public ModelessDialog, + public DialogHelper +{ + ExtBoxWithBtns_Impl *m_pExtensionBox; + PushButton m_aAddBtn; + PushButton m_aUpdateBtn; + OKButton m_aCloseBtn; + HelpButton m_aHelpBtn; + FixedLine m_aDivider; + svt::FixedHyperlink m_aGetExtensions; + FixedText m_aProgressText; + ProgressBar m_aProgressBar; + CancelButton m_aCancelBtn; + const String m_sAddPackages; + String m_sProgressText; + String m_sLastFolderURL; + ::osl::Mutex m_aMutex; + bool m_bHasProgress; + bool m_bProgressChanged; + bool m_bStartProgress; + bool m_bStopProgress; + bool m_bUpdateWarning; + bool m_bEnableWarning; + bool m_bDisableWarning; + bool m_bDeleteWarning; + long m_nProgress; + Timer m_aTimeoutTimer; + TheExtensionManager *m_pManager; + + ::com::sun::star::uno::Reference< ::com::sun::star::task::XAbortChannel > m_xAbortChannel; + + bool removeExtensionWarn( const ::rtl::OUString &rExtensionTitle ) const; + + DECL_DLLPRIVATE_LINK( HandleAddBtn, void * ); + DECL_DLLPRIVATE_LINK( HandleUpdateBtn, void * ); + DECL_DLLPRIVATE_LINK( HandleCancelBtn, void * ); + DECL_DLLPRIVATE_LINK( HandleHyperlink, svt::FixedHyperlink * ); + DECL_DLLPRIVATE_LINK( TimeOutHdl, Timer* ); + DECL_DLLPRIVATE_LINK( startProgress, void * ); + +public: + ExtMgrDialog( Window * pParent, TheExtensionManager *pManager ); + virtual ~ExtMgrDialog(); + + virtual void Resize(); + virtual long Notify( NotifyEvent& rNEvt ); + virtual BOOL Close(); + + virtual void showProgress( bool bStart ); + virtual void updateProgress( const ::rtl::OUString &rText, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XAbortChannel > &xAbortChannel); + virtual void updateProgress( const long nProgress ); + + virtual void updatePackageInfo( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ); + + void setGetExtensionsURL( const ::rtl::OUString &rURL ); + virtual long addPackageToList( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &, + bool bLicenseMissing = false ); + bool enablePackage(const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage, + bool bEnable ); + bool removePackage(const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ); + bool updatePackage(const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ); + bool acceptLicense(const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ); + + virtual void prepareChecking(); + virtual void checkEntries(); + + ::com::sun::star::uno::Sequence< ::rtl::OUString > raiseAddPicker(); +}; + +//============================================================================== +class UpdateRequiredDialog : public ModalDialog, + public DialogHelper +{ + ExtensionBox_Impl *m_pExtensionBox; + FixedText m_aUpdateNeeded; + PushButton m_aUpdateBtn; + PushButton m_aCloseBtn; + HelpButton m_aHelpBtn; + CancelButton m_aCancelBtn; + FixedLine m_aDivider; + FixedText m_aProgressText; + ProgressBar m_aProgressBar; + const String m_sAddPackages; + const String m_sCloseText; + String m_sProgressText; + ::osl::Mutex m_aMutex; + bool m_bHasProgress; + bool m_bProgressChanged; + bool m_bStartProgress; + bool m_bStopProgress; + bool m_bUpdateWarning; + bool m_bDisableWarning; + bool m_bHasLockedEntries; + long m_nProgress; + Timer m_aTimeoutTimer; + TheExtensionManager *m_pManager; + + ::com::sun::star::uno::Reference< ::com::sun::star::task::XAbortChannel > m_xAbortChannel; + + DECL_DLLPRIVATE_LINK( HandleUpdateBtn, void * ); + DECL_DLLPRIVATE_LINK( HandleCloseBtn, void * ); + DECL_DLLPRIVATE_LINK( HandleCancelBtn, void * ); + DECL_DLLPRIVATE_LINK( TimeOutHdl, Timer* ); + DECL_DLLPRIVATE_LINK( startProgress, void * ); + DECL_DLLPRIVATE_LINK( HandleHyperlink, svt::FixedHyperlink * ); + + bool isEnabled( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ) const; + bool checkDependencies( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ) const; + bool hasActiveEntries(); + void disableAllEntries(); + +public: + UpdateRequiredDialog( Window * pParent, TheExtensionManager *pManager ); + virtual ~UpdateRequiredDialog(); + + virtual short Execute(); + virtual void Resize(); + virtual BOOL Close(); +// virtual long Notify( NotifyEvent& rNEvt ); + + virtual void showProgress( bool bStart ); + virtual void updateProgress( const ::rtl::OUString &rText, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XAbortChannel > &xAbortChannel); + virtual void updateProgress( const long nProgress ); + + virtual void updatePackageInfo( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ); + + void selectEntry( long nPos ); + virtual long addPackageToList( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &, + bool bLicenseMissing = false ); + bool enablePackage( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage, bool bEnable ); + bool updatePackage( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ); + + virtual void prepareChecking(); + virtual void checkEntries(); + + ::com::sun::star::uno::Sequence< ::rtl::OUString > raiseAddPicker(); + + bool installForAllUsers( bool &bInstallForAll ) const; + bool installExtensionWarn( const ::rtl::OUString &rExtensionURL ) const; +}; + +//============================================================================== +class UpdateRequiredDialogService : public ::cppu::WeakImplHelper1< ::com::sun::star::ui::dialogs::XExecutableDialog > +{ + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const m_xComponentContext; + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > m_xParent; + ::rtl::OUString m_sInitialTitle; + +public: + UpdateRequiredDialogService( ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > const & args, + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext> const & xComponentContext ); + + // XExecutableDialog + virtual void SAL_CALL setTitle( rtl::OUString const & title ) throw ( ::com::sun::star::uno::RuntimeException ); + virtual sal_Int16 SAL_CALL execute() throw ( ::com::sun::star::uno::RuntimeException ); +}; + +} // namespace dp_gui + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_dialog2.src b/desktop/source/deployment/gui/dp_gui_dialog2.src new file mode 100644 index 000000000000..b74a802ceb0f --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_dialog2.src @@ -0,0 +1,252 @@ +/************************************************************************* + * + * 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 "svtools/controldims.hrc" +#include "dp_gui.hrc" + +ModelessDialog RID_DLG_EXTENSION_MANAGER +{ + HelpId = HID_PACKAGE_MANAGER; + Text [ en-US ] = "Extension Manager"; + + Size = MAP_APPFONT( 300, 200 ); + OutputSize = TRUE; + SVLook = TRUE; + Moveable = TRUE; + Closeable = TRUE; + Sizeable = TRUE; + Hide = TRUE; + + PushButton RID_EM_BTN_ADD + { + TabStop = TRUE; + Text [ en-US ] = "~Add..."; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; + + PushButton RID_EM_BTN_CHECK_UPDATES + { + TabStop = TRUE; + Text [ en-US ] = "Check for ~Updates..."; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; + + FixedText RID_EM_FT_GET_EXTENSIONS + { + NoLabel = TRUE; + TabStop = TRUE; + Text [ en-US ] = "Get more extensions online..."; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_FIXEDTEXT_HEIGHT ); + }; + + FixedText RID_EM_FT_PROGRESS + { + Hide = TRUE; + Right = TRUE; + Text [ en-US ] = "Adding %EXTENSION_NAME"; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_FIXEDTEXT_HEIGHT ); + }; + + CancelButton RID_EM_BTN_CANCEL + { + TabStop = TRUE; + Hide = TRUE; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; + + OKButton RID_EM_BTN_CLOSE + { + TabStop = TRUE; + DefButton = TRUE; + Text [ en-US ] = "Close"; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; + + HelpButton RID_EM_BTN_HELP + { + TabStop = TRUE; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; +}; + +ModalDialog RID_DLG_UPDATE_REQUIRED +{ + HelpId = HID_PACKAGE_MANAGER_UPD_REQ; + Text [ en-US ] = "Extension Update Required"; + + Size = MAP_APPFONT( 300, 200 ); + OutputSize = TRUE; + SVLook = TRUE; + Moveable = TRUE; + Closeable = TRUE; + Sizeable = TRUE; + Hide = TRUE; + + FixedText RID_EM_FT_MSG + { + Text [ en-US ] = "%PRODUCTNAME has been updated to a new version. Some installed %PRODUCTNAME extensions are not compatible with this version and need to be updated before they can be used."; + WordBreak = TRUE; + NoLabel = TRUE; + Size = MAP_APPFONT( 280, 3*RSC_BS_CHARHEIGHT ); + Pos = MAP_APPFONT( 5, 5 ); + }; + + FixedText RID_EM_FT_PROGRESS + { + Hide = TRUE; + Right = TRUE; + Text [ en-US ] = "Adding %EXTENSION_NAME"; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_FIXEDTEXT_HEIGHT ); + }; + + HelpButton RID_EM_BTN_HELP + { + TabStop = TRUE; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; + + PushButton RID_EM_BTN_CHECK_UPDATES + { + TabStop = TRUE; + Text [ en-US ] = "Check for ~Updates..."; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; + + PushButton RID_EM_BTN_CLOSE + { + TabStop = TRUE; + DefButton = TRUE; + Text [ en-US ] = "Disable all"; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; + + CancelButton RID_EM_BTN_CANCEL + { + TabStop = TRUE; + Hide = TRUE; + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT ); + }; + +}; + +Image RID_IMG_WARNING +{ + ImageBitmap = Bitmap { File = "caution_16.png"; }; +}; + +Image RID_IMG_WARNING_HC +{ + ImageBitmap = Bitmap { File = "caution_16_h.png"; }; +}; + +Image RID_IMG_LOCKED +{ + ImageBitmap = Bitmap { File = "lock_16.png"; }; +}; + +Image RID_IMG_LOCKED_HC +{ + ImageBitmap = Bitmap { File = "lock_16_h.png"; }; +}; + +Image RID_IMG_SHARED +{ + ImageBitmap = Bitmap { File = "shared_16.png"; }; +}; + +Image RID_IMG_SHARED_HC +{ + ImageBitmap = Bitmap { File = "shared_16_h.png"; }; +}; + +Image RID_IMG_EXTENSION +{ + ImageBitmap = Bitmap { File = "extension_32.png"; }; +}; + +Image RID_IMG_EXTENSION_HC +{ + ImageBitmap = Bitmap { File = "extension_32_h.png"; }; +}; + +QueryBox RID_QUERYBOX_INSTALL_FOR_ALL +{ + Buttons = WB_YES_NO_CANCEL; + DefButton = WB_DEF_YES; + Message[en-US] = "Make sure that no further users are working with the same %PRODUCTNAME, when installing an extension for all users in a multi user environment.\n\nFor whom do you want to install the extension?\n"; +}; + + +// Dialog layout +// --------------------------------------------------- +// row 1 | multi line edit +// --------------------------------------------------- +// row 2 | fixed text +// --------------------------------------------------- +// row 3 | img | fixed text | fixed text | button +// ---------------------------------------------------- +// row 4 | img | fixed text | fixed text +// --------------------------------------------------- +// row 5 |fixed line +// --------------------------------------------------- +// row 6 | | |button | button +// --------------------------------------------------- +// | col 1 | col 2 | col3 | col4 | col5 + +//To change the overall size of the multi line edit change +//ROW1_HEIGHT and COL3_WIDTH + +#define ROW1_Y RSC_SP_DLG_INNERBORDER_TOP +#define ROW1_HEIGHT 16*RSC_CD_FIXEDTEXT_HEIGHT +#define ROW2_Y ROW1_Y+ROW1_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW2_HEIGHT 2*RSC_CD_FIXEDTEXT_HEIGHT +#define ROW3_Y ROW2_Y+ROW2_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW3_HEIGHT 3*RSC_CD_FIXEDTEXT_HEIGHT +#define ROW4_Y ROW3_Y+ROW3_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW4_HEIGHT 3*RSC_CD_FIXEDTEXT_HEIGHT +#define ROW5_Y ROW4_Y+ROW4_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW5_HEIGHT RSC_CD_FIXEDTEXT_HEIGHT +#define ROW6_Y ROW5_Y+ROW5_HEIGHT+RSC_SP_CTRL_GROUP_Y +#define ROW6_HEIGHT RSC_CD_PUSHBUTTON_HEIGHT + +#define LIC_DLG_HEIGHT ROW6_Y+ROW6_HEIGHT+RSC_SP_DLG_INNERBORDER_BOTTOM + +#define COL1_X RSC_SP_DLG_INNERBORDER_LEFT +#define IMG_ARROW_WIDTH 16 +#define COL1_WIDTH IMG_ARROW_WIDTH +#define COL2_X COL1_X+COL1_WIDTH +#define COL2_WIDTH 10 +#define COL3_X COL2_X+COL2_WIDTH+RSC_SP_CTRL_GROUP_X +#define COL3_WIDTH 150 +#define COL4_X COL3_X+COL3_WIDTH +#define COL4_WIDTH RSC_CD_PUSHBUTTON_WIDTH+RSC_SP_CTRL_GROUP_X +#define COL5_X COL4_X+COL4_WIDTH + +#define LIC_DLG_WIDTH COL5_X+RSC_CD_PUSHBUTTON_WIDTH+RSC_SP_DLG_INNERBORDER_RIGHT +#define BODYWIDTH LIC_DLG_WIDTH-RSC_SP_DLG_INNERBORDER_LEFT-RSC_SP_DLG_INNERBORDER_RIGHT + + diff --git a/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx new file mode 100644 index 000000000000..3674759f6f04 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx @@ -0,0 +1,1216 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#define _WIN32_WINNT 0x0500 + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + + + + +#include "sal/config.h" + +#include <cstddef> + +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/beans/NamedValue.hpp" + +#include "com/sun/star/deployment/DependencyException.hpp" +#include "com/sun/star/deployment/LicenseException.hpp" +#include "com/sun/star/deployment/VersionException.hpp" +#include "com/sun/star/deployment/InstallException.hpp" +#include "com/sun/star/deployment/PlatformException.hpp" + +#include "com/sun/star/deployment/ui/LicenseDialog.hpp" +#include "com/sun/star/deployment/DeploymentException.hpp" +#include "com/sun/star/deployment/UpdateInformationProvider.hpp" +#include "com/sun/star/deployment/XPackage.hpp" + +#include "com/sun/star/task/XAbortChannel.hpp" +#include "com/sun/star/task/XInteractionAbort.hpp" +#include "com/sun/star/task/XInteractionApprove.hpp" + +#include "com/sun/star/ucb/CommandAbortedException.hpp" +#include "com/sun/star/ucb/CommandFailedException.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" + +#include "com/sun/star/ui/dialogs/ExecutableDialogResults.hpp" + +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/uno/TypeClass.hpp" +#include "osl/diagnose.h" +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "ucbhelper/content.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "cppuhelper/implbase3.hxx" +#include "comphelper/anytostring.hxx" +#include "vcl/msgbox.hxx" +#include "toolkit/helper/vclunohelper.hxx" +#include "comphelper/processfactory.hxx" + +#include "dp_gui.h" +#include "dp_gui_thread.hxx" +#include "dp_gui_extensioncmdqueue.hxx" +#include "dp_gui_dependencydialog.hxx" +#include "dp_gui_dialog2.hxx" +#include "dp_gui_shared.hxx" +#include "dp_gui_theextmgr.hxx" +#include "dp_gui_updatedialog.hxx" +#include "dp_gui_updateinstalldialog.hxx" +#include "dp_dependencies.hxx" +#include "dp_identifier.hxx" +#include "dp_version.hxx" + +#include <queue> +#include <boost/shared_ptr.hpp> + +#if (defined(_MSC_VER) && (_MSC_VER < 1400)) +#define _WIN32_WINNT 0x0400 +#endif + +#ifdef WNT +#include "tools/prewin.h" +#include <objbase.h> +#include "tools/postwin.h" +#endif + + +using namespace ::com::sun::star; +using ::rtl::OUString; + +namespace { + +OUString getVersion( OUString const & sVersion ) +{ + return ( sVersion.getLength() == 0 ) ? OUString( RTL_CONSTASCII_USTRINGPARAM( "0" ) ) : sVersion; +} + +OUString getVersion( const uno::Reference< deployment::XPackage > &rPackage ) +{ + return getVersion( rPackage->getVersion()); +} +} + + +namespace dp_gui { + +//============================================================================== + +class ProgressCmdEnv + : public ::cppu::WeakImplHelper3< ucb::XCommandEnvironment, + task::XInteractionHandler, + ucb::XProgressHandler > +{ + uno::Reference< task::XInteractionHandler> m_xHandler; + uno::Reference< uno::XComponentContext > m_xContext; + uno::Reference< task::XAbortChannel> m_xAbortChannel; + + DialogHelper *m_pDialogHelper; + OUString m_sTitle; + bool m_bAborted; + bool m_bWarnUser; + sal_Int32 m_nCurrentProgress; + + void updateProgress(); + + void update_( uno::Any const & Status ) throw ( uno::RuntimeException ); + +public: + virtual ~ProgressCmdEnv(); + + /** When param bAskWhenInstalling = true, then the user is asked if he + agrees to install this extension. In case this extension is already installed + then the user is also notified and asked if he wants to replace that existing + extension. In first case an interaction request with an InstallException + will be handled and in the second case a VersionException will be handled. + */ + + ProgressCmdEnv( const uno::Reference< uno::XComponentContext > rContext, + DialogHelper *pDialogHelper, + const OUString &rTitle ) + : m_xContext( rContext ), + m_pDialogHelper( pDialogHelper ), + m_sTitle( rTitle ), + m_bAborted( false ), + m_bWarnUser( false ) + {} + + Dialog * activeDialog() { return m_pDialogHelper ? m_pDialogHelper->getWindow() : NULL; } + + void setTitle( const OUString& rNewTitle ) { m_sTitle = rNewTitle; } + void startProgress(); + void stopProgress(); + void progressSection( const OUString &rText, + const uno::Reference< task::XAbortChannel > &xAbortChannel = 0 ); + inline bool isAborted() const { return m_bAborted; } + inline void setWarnUser( bool bNewVal ) { m_bWarnUser = bNewVal; } + + // 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 ); +}; + +//------------------------------------------------------------------------------ +struct ExtensionCmd +{ + enum E_CMD_TYPE { ADD, ENABLE, DISABLE, REMOVE, CHECK_FOR_UPDATES, ACCEPT_LICENSE }; + + E_CMD_TYPE m_eCmdType; + bool m_bWarnUser; + OUString m_sExtensionURL; + OUString m_sRepository; + uno::Reference< deployment::XPackage > m_xPackage; + std::vector< uno::Reference< deployment::XPackage > > m_vExtensionList; + + ExtensionCmd( const E_CMD_TYPE eCommand, + const OUString &rExtensionURL, + const OUString &rRepository, + const bool bWarnUser ) + : m_eCmdType( eCommand ), + m_bWarnUser( bWarnUser ), + m_sExtensionURL( rExtensionURL ), + m_sRepository( rRepository ) {}; + ExtensionCmd( const E_CMD_TYPE eCommand, + const uno::Reference< deployment::XPackage > &rPackage ) + : m_eCmdType( eCommand ), + m_bWarnUser( false ), + m_xPackage( rPackage ) {}; + ExtensionCmd( const E_CMD_TYPE eCommand, + const std::vector<uno::Reference<deployment::XPackage > > &vExtensionList ) + : m_eCmdType( eCommand ), + m_bWarnUser( false ), + m_vExtensionList( vExtensionList ) {}; +}; + +typedef ::boost::shared_ptr< ExtensionCmd > TExtensionCmd; + +//------------------------------------------------------------------------------ +class ExtensionCmdQueue::Thread: public dp_gui::Thread +{ +public: + Thread( DialogHelper *pDialogHelper, + TheExtensionManager *pManager, + const uno::Reference< uno::XComponentContext > & rContext ); + + void addExtension( const OUString &rExtensionURL, + const OUString &rRepository, + const bool bWarnUser ); + void removeExtension( const uno::Reference< deployment::XPackage > &rPackage ); + void enableExtension( const uno::Reference< deployment::XPackage > &rPackage, + const bool bEnable ); + void checkForUpdates( const std::vector<uno::Reference<deployment::XPackage > > &vExtensionList ); + void acceptLicense( const uno::Reference< deployment::XPackage > &rPackage ); + void stop(); + bool isBusy(); + + static OUString searchAndReplaceAll( const OUString &rSource, + const OUString &rWhat, + const OUString &rWith ); +private: + Thread( Thread & ); // not defined + void operator =( Thread & ); // not defined + + virtual ~Thread(); + + virtual void execute(); + virtual void SAL_CALL onTerminated(); + + void _addExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const OUString &rPackageURL, + const OUString &rRepository, + const bool bWarnUser ); + void _removeExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const uno::Reference< deployment::XPackage > &xPackage ); + void _enableExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const uno::Reference< deployment::XPackage > &xPackage ); + void _disableExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const uno::Reference< deployment::XPackage > &xPackage ); + void _checkForUpdates( const std::vector<uno::Reference<deployment::XPackage > > &vExtensionList ); + void _acceptLicense( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const uno::Reference< deployment::XPackage > &xPackage ); + + enum Input { NONE, START, STOP }; + + uno::Reference< uno::XComponentContext > m_xContext; + std::queue< TExtensionCmd > m_queue; + + DialogHelper *m_pDialogHelper; + TheExtensionManager *m_pManager; + + const OUString m_sEnablingPackages; + const OUString m_sDisablingPackages; + const OUString m_sAddingPackages; + const OUString m_sRemovingPackages; + const OUString m_sDefaultCmd; + const OUString m_sAcceptLicense; + osl::Condition m_wakeup; + osl::Mutex m_mutex; + Input m_eInput; + bool m_bTerminated; + bool m_bStopped; + bool m_bWorking; +}; + +//------------------------------------------------------------------------------ +void ProgressCmdEnv::startProgress() +{ + m_nCurrentProgress = 0; + + if ( m_pDialogHelper ) + m_pDialogHelper->showProgress( true ); +} + +//------------------------------------------------------------------------------ +void ProgressCmdEnv::stopProgress() +{ + if ( m_pDialogHelper ) + m_pDialogHelper->showProgress( false ); +} + +//------------------------------------------------------------------------------ +void ProgressCmdEnv::progressSection( const OUString &rText, + const uno::Reference< task::XAbortChannel > &xAbortChannel ) +{ + m_xAbortChannel = xAbortChannel; + if (! m_bAborted) + { + m_nCurrentProgress = 0; + if ( m_pDialogHelper ) + { + m_pDialogHelper->updateProgress( rText, xAbortChannel ); + m_pDialogHelper->updateProgress( 5 ); + } + } +} + +//------------------------------------------------------------------------------ +void ProgressCmdEnv::updateProgress() +{ + if ( ! m_bAborted ) + { + long nProgress = ((m_nCurrentProgress*5) % 100) + 5; + if ( m_pDialogHelper ) + m_pDialogHelper->updateProgress( nProgress ); + } +} + +//------------------------------------------------------------------------------ +ProgressCmdEnv::~ProgressCmdEnv() +{ + // TODO: stop all threads and wait +} + + +//------------------------------------------------------------------------------ +// XCommandEnvironment +//------------------------------------------------------------------------------ +uno::Reference< task::XInteractionHandler > ProgressCmdEnv::getInteractionHandler() + throw ( uno::RuntimeException ) +{ + return this; +} + +//------------------------------------------------------------------------------ +uno::Reference< ucb::XProgressHandler > ProgressCmdEnv::getProgressHandler() + throw ( uno::RuntimeException ) +{ + return this; +} + +//------------------------------------------------------------------------------ +// XInteractionHandler +//------------------------------------------------------------------------------ +void ProgressCmdEnv::handle( uno::Reference< task::XInteractionRequest > const & xRequest ) + throw ( uno::RuntimeException ) +{ + uno::Any request( xRequest->getRequest() ); + OSL_ASSERT( request.getValueTypeClass() == uno::TypeClass_EXCEPTION ); + dp_misc::TRACE( OUSTR("[dp_gui_cmdenv.cxx] incoming request:\n") + + ::comphelper::anyToString(request) + OUSTR("\n")); + + lang::WrappedTargetException wtExc; + deployment::DependencyException depExc; + deployment::LicenseException licExc; + deployment::VersionException verExc; + deployment::InstallException instExc; + deployment::PlatformException platExc; + + // selections: + bool approve = false; + bool abort = false; + + if (request >>= wtExc) { + // handable deployment error signalled, e.g. + // bundle item registration failed, notify cause only: + uno::Any cause; + deployment::DeploymentException dpExc; + if (wtExc.TargetException >>= dpExc) + cause = dpExc.Cause; + else { + ucb::CommandFailedException cfExc; + if (wtExc.TargetException >>= cfExc) + cause = cfExc.Reason; + else + cause = wtExc.TargetException; + } + update_( cause ); + + // ignore intermediate errors of legacy packages, i.e. + // former pkgchk behaviour: + const uno::Reference< deployment::XPackage > xPackage( wtExc.Context, uno::UNO_QUERY ); + OSL_ASSERT( xPackage.is() ); + if ( xPackage.is() ) + { + const uno::Reference< deployment::XPackageTypeInfo > xPackageType( xPackage->getPackageType() ); + OSL_ASSERT( xPackageType.is() ); + if (xPackageType.is()) + { + approve = ( xPackage->isBundle() && + xPackageType->getMediaType().matchAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/" + "vnd.sun.star.legacy-package-bundle") )); + } + } + abort = !approve; + } + else if (request >>= depExc) + { + std::vector< rtl::OUString > deps; + for (sal_Int32 i = 0; i < depExc.UnsatisfiedDependencies.getLength(); + ++i) + { + deps.push_back( + dp_misc::Dependencies::getErrorText( depExc.UnsatisfiedDependencies[i]) ); + } + { + SolarMutexGuard guard; + short n = DependencyDialog( m_pDialogHelper? m_pDialogHelper->getWindow() : NULL, deps ).Execute(); + // Distinguish between closing the dialog and programatically + // canceling the dialog (headless VCL): + approve = n == RET_OK + || (n == RET_CANCEL && !Application::IsDialogCancelEnabled()); + } + } + else if (request >>= licExc) + { + uno::Reference< ui::dialogs::XExecutableDialog > xDialog( + deployment::ui::LicenseDialog::create( + m_xContext, VCLUnoHelper::GetInterface( m_pDialogHelper? m_pDialogHelper->getWindow() : NULL ), + licExc.ExtensionName, licExc.Text ) ); + sal_Int16 res = xDialog->execute(); + if ( res == ui::dialogs::ExecutableDialogResults::CANCEL ) + abort = true; + else if ( res == ui::dialogs::ExecutableDialogResults::OK ) + approve = true; + else + { + OSL_ASSERT(0); + } + } + else if (request >>= verExc) + { + sal_uInt32 id; + switch (dp_misc::compareVersions( + verExc.NewVersion, verExc.Deployed->getVersion() )) + { + case dp_misc::LESS: + id = RID_WARNINGBOX_VERSION_LESS; + break; + case dp_misc::EQUAL: + id = RID_WARNINGBOX_VERSION_EQUAL; + break; + default: // dp_misc::GREATER + id = RID_WARNINGBOX_VERSION_GREATER; + break; + } + OSL_ASSERT( verExc.Deployed.is() ); + bool bEqualNames = verExc.NewDisplayName.equals( + verExc.Deployed->getDisplayName()); + { + SolarMutexGuard guard; + WarningBox box( m_pDialogHelper? m_pDialogHelper->getWindow() : NULL, ResId(id, *DeploymentGuiResMgr::get())); + String s; + if (bEqualNames) + { + s = box.GetMessText(); + } + else if (id == RID_WARNINGBOX_VERSION_EQUAL) + { + //hypothetical: requires two instances of an extension with the same + //version to have different display names. Probably the developer forgot + //to change the version. + s = String(ResId(RID_STR_WARNINGBOX_VERSION_EQUAL_DIFFERENT_NAMES, *DeploymentGuiResMgr::get())); + } + else if (id == RID_WARNINGBOX_VERSION_LESS) + { + s = String(ResId(RID_STR_WARNINGBOX_VERSION_LESS_DIFFERENT_NAMES, *DeploymentGuiResMgr::get())); + } + else if (id == RID_WARNINGBOX_VERSION_GREATER) + { + s = String(ResId(RID_STR_WARNINGBOX_VERSION_GREATER_DIFFERENT_NAMES, *DeploymentGuiResMgr::get())); + } + s.SearchAndReplaceAllAscii( "$NAME", verExc.NewDisplayName); + s.SearchAndReplaceAllAscii( "$OLDNAME", verExc.Deployed->getDisplayName()); + s.SearchAndReplaceAllAscii( "$NEW", getVersion(verExc.NewVersion) ); + s.SearchAndReplaceAllAscii( "$DEPLOYED", getVersion(verExc.Deployed) ); + box.SetMessText(s); + approve = box.Execute() == RET_OK; + abort = !approve; + } + } + else if (request >>= instExc) + { + if ( ! m_bWarnUser ) + { + approve = true; + } + else + { + if ( m_pDialogHelper ) + { + SolarMutexGuard guard; + + approve = m_pDialogHelper->installExtensionWarn( instExc.displayName ); + } + else + approve = false; + abort = !approve; + } + } + else if (request >>= platExc) + { + SolarMutexGuard guard; + String sMsg( ResId( RID_STR_UNSUPPORTED_PLATFORM, *DeploymentGuiResMgr::get() ) ); + sMsg.SearchAndReplaceAllAscii( "%Name", platExc.package->getDisplayName() ); + ErrorBox box( m_pDialogHelper? m_pDialogHelper->getWindow() : NULL, WB_OK, sMsg ); + box.Execute(); + approve = true; + } + + if (approve == false && abort == false) + { + // forward to UUI handler: + if (! m_xHandler.is()) { + // late init: + uno::Sequence< uno::Any > handlerArgs( 1 ); + handlerArgs[ 0 ] <<= beans::PropertyValue( + OUSTR("Context"), -1, uno::Any( m_sTitle ), + beans::PropertyState_DIRECT_VALUE ); + m_xHandler.set( m_xContext->getServiceManager() + ->createInstanceWithArgumentsAndContext( + OUSTR("com.sun.star.uui.InteractionHandler"), + handlerArgs, m_xContext ), uno::UNO_QUERY_THROW ); + } + m_xHandler->handle( xRequest ); + } + else + { + // select: + uno::Sequence< uno::Reference< task::XInteractionContinuation > > conts( + xRequest->getContinuations() ); + uno::Reference< task::XInteractionContinuation > const * pConts = conts.getConstArray(); + sal_Int32 len = conts.getLength(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + if (approve) { + uno::Reference< task::XInteractionApprove > xInteractionApprove( pConts[ pos ], uno::UNO_QUERY ); + if (xInteractionApprove.is()) { + xInteractionApprove->select(); + // don't query again for ongoing continuations: + approve = false; + } + } + else if (abort) { + uno::Reference< task::XInteractionAbort > xInteractionAbort( pConts[ pos ], uno::UNO_QUERY ); + if (xInteractionAbort.is()) { + xInteractionAbort->select(); + // don't query again for ongoing continuations: + abort = false; + } + } + } + } +} + +//------------------------------------------------------------------------------ +// XProgressHandler +//------------------------------------------------------------------------------ +void ProgressCmdEnv::push( uno::Any const & rStatus ) + throw( uno::RuntimeException ) +{ + update_( rStatus ); +} + +//------------------------------------------------------------------------------ +void ProgressCmdEnv::update_( uno::Any const & rStatus ) + throw( uno::RuntimeException ) +{ + OUString text; + if ( rStatus.hasValue() && !( rStatus >>= text) ) + { + if ( rStatus.getValueTypeClass() == uno::TypeClass_EXCEPTION ) + text = static_cast< uno::Exception const *>( rStatus.getValue() )->Message; + if ( text.getLength() == 0 ) + text = ::comphelper::anyToString( rStatus ); // fallback + + const SolarMutexGuard aGuard; + const ::std::auto_ptr< ErrorBox > aBox( new ErrorBox( m_pDialogHelper? m_pDialogHelper->getWindow() : NULL, WB_OK, text ) ); + aBox->Execute(); + } + ++m_nCurrentProgress; + updateProgress(); +} + +//------------------------------------------------------------------------------ +void ProgressCmdEnv::update( uno::Any const & rStatus ) + throw( uno::RuntimeException ) +{ + update_( rStatus ); +} + +//------------------------------------------------------------------------------ +void ProgressCmdEnv::pop() + throw( uno::RuntimeException ) +{ + update_( uno::Any() ); // no message +} + +//------------------------------------------------------------------------------ +ExtensionCmdQueue::Thread::Thread( DialogHelper *pDialogHelper, + TheExtensionManager *pManager, + const uno::Reference< uno::XComponentContext > & rContext ) : + m_xContext( rContext ), + m_pDialogHelper( pDialogHelper ), + m_pManager( pManager ), + m_sEnablingPackages( DialogHelper::getResourceString( RID_STR_ENABLING_PACKAGES ) ), + m_sDisablingPackages( DialogHelper::getResourceString( RID_STR_DISABLING_PACKAGES ) ), + m_sAddingPackages( DialogHelper::getResourceString( RID_STR_ADDING_PACKAGES ) ), + m_sRemovingPackages( DialogHelper::getResourceString( RID_STR_REMOVING_PACKAGES ) ), + m_sDefaultCmd( DialogHelper::getResourceString( RID_STR_ADD_PACKAGES ) ), + m_sAcceptLicense( DialogHelper::getResourceString( RID_STR_ACCEPT_LICENSE ) ), + m_eInput( NONE ), + m_bTerminated( false ), + m_bStopped( false ), + m_bWorking( false ) +{ + OSL_ASSERT( pDialogHelper ); +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::addExtension( const ::rtl::OUString &rExtensionURL, + const ::rtl::OUString &rRepository, + const bool bWarnUser ) +{ + ::osl::MutexGuard aGuard( m_mutex ); + + //If someone called stop then we do not add the extension -> game over! + if ( m_bStopped ) + return; + + if ( rExtensionURL.getLength() ) + { + TExtensionCmd pEntry( new ExtensionCmd( ExtensionCmd::ADD, rExtensionURL, rRepository, bWarnUser ) ); + + m_queue.push( pEntry ); + m_eInput = START; + m_wakeup.set(); + } +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::removeExtension( const uno::Reference< deployment::XPackage > &rPackage ) +{ + ::osl::MutexGuard aGuard( m_mutex ); + + //If someone called stop then we do not remove the extension -> game over! + if ( m_bStopped ) + return; + + if ( rPackage.is() ) + { + TExtensionCmd pEntry( new ExtensionCmd( ExtensionCmd::REMOVE, rPackage ) ); + + m_queue.push( pEntry ); + m_eInput = START; + m_wakeup.set(); + } +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::acceptLicense( const uno::Reference< deployment::XPackage > &rPackage ) +{ + ::osl::MutexGuard aGuard( m_mutex ); + + //If someone called stop then we do not remove the extension -> game over! + if ( m_bStopped ) + return; + + if ( rPackage.is() ) + { + TExtensionCmd pEntry( new ExtensionCmd( ExtensionCmd::ACCEPT_LICENSE, rPackage ) ); + + m_queue.push( pEntry ); + m_eInput = START; + m_wakeup.set(); + } +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::enableExtension( const uno::Reference< deployment::XPackage > &rPackage, + const bool bEnable ) +{ + ::osl::MutexGuard aGuard( m_mutex ); + + //If someone called stop then we do not remove the extension -> game over! + if ( m_bStopped ) + return; + + if ( rPackage.is() ) + { + TExtensionCmd pEntry( new ExtensionCmd( bEnable ? ExtensionCmd::ENABLE : + ExtensionCmd::DISABLE, + rPackage ) ); + m_queue.push( pEntry ); + m_eInput = START; + m_wakeup.set(); + } +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::checkForUpdates( + const std::vector<uno::Reference<deployment::XPackage > > &vExtensionList ) +{ + ::osl::MutexGuard aGuard( m_mutex ); + + //If someone called stop then we do not update the extension -> game over! + if ( m_bStopped ) + return; + + TExtensionCmd pEntry( new ExtensionCmd( ExtensionCmd::CHECK_FOR_UPDATES, vExtensionList ) ); + m_queue.push( pEntry ); + m_eInput = START; + m_wakeup.set(); +} + +//------------------------------------------------------------------------------ +//Stopping this thread will not abort the installation of extensions. +void ExtensionCmdQueue::Thread::stop() +{ + osl::MutexGuard aGuard( m_mutex ); + m_bStopped = true; + m_eInput = STOP; + m_wakeup.set(); +} + +//------------------------------------------------------------------------------ +bool ExtensionCmdQueue::Thread::isBusy() +{ + osl::MutexGuard aGuard( m_mutex ); + return m_bWorking; +} + +//------------------------------------------------------------------------------ +ExtensionCmdQueue::Thread::~Thread() {} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::execute() +{ +#ifdef WNT + //Needed for use of the service "com.sun.star.system.SystemShellExecute" in + //DialogHelper::openWebBrowser + CoUninitialize(); + HRESULT r = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); +#endif + for (;;) + { + if ( m_wakeup.wait() != osl::Condition::result_ok ) + { + dp_misc::TRACE( "dp_gui::ExtensionCmdQueue::Thread::run: ignored " + "osl::Condition::wait failure\n" ); + } + m_wakeup.reset(); + + int nSize; + Input eInput; + { + osl::MutexGuard aGuard( m_mutex ); + eInput = m_eInput; + m_eInput = NONE; + nSize = m_queue.size(); + m_bWorking = false; + } + + // If this thread has been woken up by anything else except start, stop + // then input is NONE and we wait again. + // We only install the extension which are currently in the queue. + // The progressbar will be set to show the progress of the current number + // of extensions. If we allowed to add extensions now then the progressbar may + // have reached the end while we still install newly added extensions. + if ( ( eInput == NONE ) || ( nSize == 0 ) ) + continue; + if ( eInput == STOP ) + break; + + ::rtl::Reference< ProgressCmdEnv > currentCmdEnv( new ProgressCmdEnv( m_xContext, m_pDialogHelper, m_sDefaultCmd ) ); + + // Do not lock the following part with addExtension. addExtension may be called in the main thread. + // If the message box "Do you want to install the extension (or similar)" is shown and then + // addExtension is called, which then blocks the main thread, then we deadlock. + bool bStartProgress = true; + + while ( !currentCmdEnv->isAborted() && --nSize >= 0 ) + { + { + osl::MutexGuard aGuard( m_mutex ); + m_bWorking = true; + } + + try + { + TExtensionCmd pEntry; + { + ::osl::MutexGuard queueGuard( m_mutex ); + pEntry = m_queue.front(); + m_queue.pop(); + } + + if ( bStartProgress && ( pEntry->m_eCmdType != ExtensionCmd::CHECK_FOR_UPDATES ) ) + { + currentCmdEnv->startProgress(); + bStartProgress = false; + } + + switch ( pEntry->m_eCmdType ) { + case ExtensionCmd::ADD : + _addExtension( currentCmdEnv, pEntry->m_sExtensionURL, pEntry->m_sRepository, pEntry->m_bWarnUser ); + break; + case ExtensionCmd::REMOVE : + _removeExtension( currentCmdEnv, pEntry->m_xPackage ); + break; + case ExtensionCmd::ENABLE : + _enableExtension( currentCmdEnv, pEntry->m_xPackage ); + break; + case ExtensionCmd::DISABLE : + _disableExtension( currentCmdEnv, pEntry->m_xPackage ); + break; + case ExtensionCmd::CHECK_FOR_UPDATES : + _checkForUpdates( pEntry->m_vExtensionList ); + break; + case ExtensionCmd::ACCEPT_LICENSE : + _acceptLicense( currentCmdEnv, pEntry->m_xPackage ); + break; + } + } + //catch ( deployment::DeploymentException &) + //{ + //} + //catch ( lang::IllegalArgumentException &) + //{ + //} + catch ( ucb::CommandAbortedException & ) + { + //This exception is thrown when the user clicks cancel on the progressbar. + //Then we cancel the installation of all extensions and remove them from + //the queue. + { + ::osl::MutexGuard queueGuard2(m_mutex); + while ( --nSize >= 0 ) + m_queue.pop(); + } + break; + } + catch ( ucb::CommandFailedException & ) + { + //This exception is thrown when a user clicked cancel in the messagebox which was + //startet by the interaction handler. For example the user will be asked if he/she + //really wants to install the extension. + //These interaction are run for exectly one extension at a time. Therefore we continue + //with installing the remaining extensions. + continue; + } + catch ( uno::Exception & ) + { + //Todo display the user an error + //see also DialogImpl::SyncPushButton::Click() + uno::Any exc( ::cppu::getCaughtException() ); + OUString msg; + deployment::DeploymentException dpExc; + if ((exc >>= dpExc) && + dpExc.Cause.getValueTypeClass() == uno::TypeClass_EXCEPTION) + { + // notify error cause only: + msg = reinterpret_cast< uno::Exception const * >( dpExc.Cause.getValue() )->Message; + } + if (msg.getLength() == 0) // fallback for debugging purposes + msg = ::comphelper::anyToString(exc); + + const SolarMutexGuard guard; + ::std::auto_ptr<ErrorBox> box( + new ErrorBox( currentCmdEnv->activeDialog(), WB_OK, msg ) ); + if ( m_pDialogHelper ) + box->SetText( m_pDialogHelper->getWindow()->GetText() ); + box->Execute(); + //Continue with installation of the remaining extensions + } + { + osl::MutexGuard aGuard( m_mutex ); + m_bWorking = false; + } + } + + { + // when leaving the while loop with break, we should set working to false, too + osl::MutexGuard aGuard( m_mutex ); + m_bWorking = false; + } + + if ( !bStartProgress ) + currentCmdEnv->stopProgress(); + } + //end for + //enable all buttons +// m_pDialog->m_bAddingExtensions = false; +// m_pDialog->updateButtonStates(); +#ifdef WNT + CoUninitialize(); +#endif +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::_addExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const OUString &rPackageURL, + const OUString &rRepository, + const bool bWarnUser ) +{ + //check if we have a string in anyTitle. For example "unopkg gui \" caused anyTitle to be void + //and anyTitle.get<OUString> throws as RuntimeException. + uno::Any anyTitle; + try + { + anyTitle = ::ucbhelper::Content( rPackageURL, rCmdEnv.get() ).getPropertyValue( OUSTR("Title") ); + } + catch ( uno::Exception & ) + { + return; + } + + OUString sName; + if ( ! (anyTitle >>= sName) ) + { + OSL_ENSURE(0, "Could not get file name for extension."); + return; + } + + rCmdEnv->setWarnUser( bWarnUser ); + uno::Reference< deployment::XExtensionManager > xExtMgr = m_pManager->getExtensionManager(); + uno::Reference< task::XAbortChannel > xAbortChannel( xExtMgr->createAbortChannel() ); + OUString sTitle = searchAndReplaceAll( m_sAddingPackages, OUSTR("%EXTENSION_NAME"), sName ); + rCmdEnv->progressSection( sTitle, xAbortChannel ); + + try + { + xExtMgr->addExtension(rPackageURL, uno::Sequence<beans::NamedValue>(), + rRepository, xAbortChannel, rCmdEnv.get() ); + } + catch ( ucb::CommandFailedException & ) + { + // When the extension is already installed we'll get a dialog asking if we want to overwrite. If we then press + // cancel this exception is thrown. + } + catch ( ucb::CommandAbortedException & ) + { + // User clicked the cancel button + // TODO: handle cancel + } + rCmdEnv->setWarnUser( false ); +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::_removeExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const uno::Reference< deployment::XPackage > &xPackage ) +{ + uno::Reference< deployment::XExtensionManager > xExtMgr = m_pManager->getExtensionManager(); + uno::Reference< task::XAbortChannel > xAbortChannel( xExtMgr->createAbortChannel() ); + OUString sTitle = searchAndReplaceAll( m_sRemovingPackages, OUSTR("%EXTENSION_NAME"), xPackage->getDisplayName() ); + rCmdEnv->progressSection( sTitle, xAbortChannel ); + + OUString id( dp_misc::getIdentifier( xPackage ) ); + try + { + xExtMgr->removeExtension( id, xPackage->getName(), xPackage->getRepositoryName(), xAbortChannel, rCmdEnv.get() ); + } + catch ( deployment::DeploymentException & ) + {} + catch ( ucb::CommandFailedException & ) + {} + catch ( ucb::CommandAbortedException & ) + {} + + // Check, if there are still updates to be notified via menu bar icon + uno::Sequence< uno::Sequence< rtl::OUString > > aItemList; + UpdateDialog::createNotifyJob( false, aItemList ); +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::_checkForUpdates( + const std::vector<uno::Reference<deployment::XPackage > > &vExtensionList ) +{ + UpdateDialog* pUpdateDialog; + std::vector< UpdateData > vData; + + const SolarMutexGuard guard; + + pUpdateDialog = new UpdateDialog( m_xContext, m_pDialogHelper? m_pDialogHelper->getWindow() : NULL, vExtensionList, &vData ); + + pUpdateDialog->notifyMenubar( true, false ); // prepare the checking, if there updates to be notified via menu bar icon + + if ( ( pUpdateDialog->Execute() == RET_OK ) && !vData.empty() ) + { + // If there is at least one directly downloadable dialog then we + // open the install dialog. + ::std::vector< UpdateData > dataDownload; + int countWebsiteDownload = 0; + typedef std::vector< dp_gui::UpdateData >::const_iterator cit; + + for ( cit i = vData.begin(); i < vData.end(); i++ ) + { + if ( i->sWebsiteURL.getLength() > 0 ) + countWebsiteDownload ++; + else + dataDownload.push_back( *i ); + } + + short nDialogResult = RET_OK; + if ( !dataDownload.empty() ) + { + nDialogResult = UpdateInstallDialog( m_pDialogHelper? m_pDialogHelper->getWindow() : NULL, dataDownload, m_xContext ).Execute(); + pUpdateDialog->notifyMenubar( false, true ); // Check, if there are still pending updates to be notified via menu bar icon + } + else + pUpdateDialog->notifyMenubar( false, false ); // Check, if there are pending updates to be notified via menu bar icon + + //Now start the webbrowser and navigate to the websites where we get the updates + if ( RET_OK == nDialogResult ) + { + for ( cit i = vData.begin(); i < vData.end(); i++ ) + { + if ( m_pDialogHelper && ( i->sWebsiteURL.getLength() > 0 ) ) + m_pDialogHelper->openWebBrowser( i->sWebsiteURL, m_pDialogHelper->getWindow()->GetText() ); + } + } + } + else + pUpdateDialog->notifyMenubar( false, false ); // check if there updates to be notified via menu bar icon + + delete pUpdateDialog; +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::_enableExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const uno::Reference< deployment::XPackage > &xPackage ) +{ + if ( !xPackage.is() ) + return; + + uno::Reference< deployment::XExtensionManager > xExtMgr = m_pManager->getExtensionManager(); + uno::Reference< task::XAbortChannel > xAbortChannel( xExtMgr->createAbortChannel() ); + OUString sTitle = searchAndReplaceAll( m_sEnablingPackages, OUSTR("%EXTENSION_NAME"), xPackage->getDisplayName() ); + rCmdEnv->progressSection( sTitle, xAbortChannel ); + + try + { + xExtMgr->enableExtension( xPackage, xAbortChannel, rCmdEnv.get() ); + if ( m_pDialogHelper ) + m_pDialogHelper->updatePackageInfo( xPackage ); + } + catch ( ::ucb::CommandAbortedException & ) + {} +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::_disableExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const uno::Reference< deployment::XPackage > &xPackage ) +{ + if ( !xPackage.is() ) + return; + + uno::Reference< deployment::XExtensionManager > xExtMgr = m_pManager->getExtensionManager(); + uno::Reference< task::XAbortChannel > xAbortChannel( xExtMgr->createAbortChannel() ); + OUString sTitle = searchAndReplaceAll( m_sDisablingPackages, OUSTR("%EXTENSION_NAME"), xPackage->getDisplayName() ); + rCmdEnv->progressSection( sTitle, xAbortChannel ); + + try + { + xExtMgr->disableExtension( xPackage, xAbortChannel, rCmdEnv.get() ); + if ( m_pDialogHelper ) + m_pDialogHelper->updatePackageInfo( xPackage ); + } + catch ( ::ucb::CommandAbortedException & ) + {} +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::_acceptLicense( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, + const uno::Reference< deployment::XPackage > &xPackage ) +{ + if ( !xPackage.is() ) + return; + + uno::Reference< deployment::XExtensionManager > xExtMgr = m_pManager->getExtensionManager(); + uno::Reference< task::XAbortChannel > xAbortChannel( xExtMgr->createAbortChannel() ); + OUString sTitle = searchAndReplaceAll( m_sAcceptLicense, OUSTR("%EXTENSION_NAME"), xPackage->getDisplayName() ); + rCmdEnv->progressSection( sTitle, xAbortChannel ); + + try + { + xExtMgr->checkPrerequisitesAndEnable( xPackage, xAbortChannel, rCmdEnv.get() ); + if ( m_pDialogHelper ) + m_pDialogHelper->updatePackageInfo( xPackage ); + } + catch ( ::ucb::CommandAbortedException & ) + {} +} + +//------------------------------------------------------------------------------ +void ExtensionCmdQueue::Thread::onTerminated() +{ + ::osl::MutexGuard g(m_mutex); + m_bTerminated = true; +} + +//------------------------------------------------------------------------------ +OUString ExtensionCmdQueue::Thread::searchAndReplaceAll( const OUString &rSource, + const OUString &rWhat, + const OUString &rWith ) +{ + OUString aRet( rSource ); + sal_Int32 nLen = rWhat.getLength(); + + if ( !nLen ) + return aRet; + + sal_Int32 nIndex = rSource.indexOf( rWhat ); + while ( nIndex != -1 ) + { + aRet = aRet.replaceAt( nIndex, nLen, rWith ); + nIndex = aRet.indexOf( rWhat, nIndex + rWith.getLength() ); + } + return aRet; +} + + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +ExtensionCmdQueue::ExtensionCmdQueue( DialogHelper * pDialogHelper, + TheExtensionManager *pManager, + const uno::Reference< uno::XComponentContext > &rContext ) + : m_thread( new Thread( pDialogHelper, pManager, rContext ) ) +{ + m_thread->launch(); +} + +ExtensionCmdQueue::~ExtensionCmdQueue() { + stop(); +} + +void ExtensionCmdQueue::addExtension( const ::rtl::OUString & extensionURL, + const ::rtl::OUString & repository, + const bool bWarnUser ) +{ + m_thread->addExtension( extensionURL, repository, bWarnUser ); +} + +void ExtensionCmdQueue::removeExtension( const uno::Reference< deployment::XPackage > &rPackage ) +{ + m_thread->removeExtension( rPackage ); +} + +void ExtensionCmdQueue::enableExtension( const uno::Reference< deployment::XPackage > &rPackage, + const bool bEnable ) +{ + m_thread->enableExtension( rPackage, bEnable ); +} + +void ExtensionCmdQueue::checkForUpdates( const std::vector<uno::Reference<deployment::XPackage > > &vExtensionList ) +{ + m_thread->checkForUpdates( vExtensionList ); +} + +void ExtensionCmdQueue::acceptLicense( const uno::Reference< deployment::XPackage > &rPackage ) +{ + m_thread->acceptLicense( rPackage ); +} + +void ExtensionCmdQueue::syncRepositories( const uno::Reference< uno::XComponentContext > &xContext ) +{ + dp_misc::syncRepositories( new ProgressCmdEnv( xContext, NULL, OUSTR("Extension Manager") ) ); +} + +void ExtensionCmdQueue::stop() +{ + m_thread->stop(); +} + +bool ExtensionCmdQueue::isBusy() +{ + return m_thread->isBusy(); +} + +void handleInteractionRequest( const uno::Reference< uno::XComponentContext > & xContext, + const uno::Reference< task::XInteractionRequest > & xRequest ) +{ + ::rtl::Reference< ProgressCmdEnv > xCmdEnv( new ProgressCmdEnv( xContext, NULL, OUSTR("Extension Manager") ) ); + xCmdEnv->handle( xRequest ); +} + +} //namespace dp_gui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.hxx b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.hxx new file mode 100644 index 000000000000..8794c5113248 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.hxx @@ -0,0 +1,114 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_DP_GUI_EXTENSIONCMDQUEUE_HXX +#define INCLUDED_DP_GUI_EXTENSIONCMDQUEUE_HXX + +#include "sal/config.h" + +#include "com/sun/star/uno/Reference.hxx" +#include "rtl/ref.hxx" + +#include <vector> + +#include "dp_gui_updatedata.hxx" + +/// @HTML + +namespace com { namespace sun { namespace star { + namespace task { class XInteractionRequest; } + namespace uno { class XComponentContext; } +} } } + +namespace dp_gui { + +class DialogHelper; +class TheExtensionManager; + +/** + Manages installing of extensions in the GUI mode. Requests for installing + Extensions can be asynchronous. For example, the Extension Manager is running + in an office process and someone uses the system integration to install an Extension. + That is, the user double clicks an extension symbol in a file browser, which then + causes an invocation of "unopkg gui ext". When at that time the Extension Manager + already performs a task, triggered by the user (for example, add, update, disable, + enable) then adding of the extension will be postponed until the user has finished + the task. + + This class also ensures that the extensions are not installed in the main thread. + Doing so would cause a deadlock because of the progress bar which needs to be constantly + updated. +*/ +class ExtensionCmdQueue { + +public: + /** + Create an instance. + */ + ExtensionCmdQueue( DialogHelper * pDialogHelper, + TheExtensionManager *pManager, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > & rContext); + + ~ExtensionCmdQueue(); + + /** + */ + void addExtension( const ::rtl::OUString &rExtensionURL, + const ::rtl::OUString &rRepository, + const bool bWarnUser ); + void removeExtension( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &rPackage ); + void enableExtension( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &rPackage, + const bool bEnable ); + void checkForUpdates(const std::vector< ::com::sun::star::uno::Reference< + ::com::sun::star::deployment::XPackage > > &vList ); + void acceptLicense( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &rPackage ); + static void syncRepositories( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > & xContext ); + /** + This call does not block. It signals the internal thread + that it should install the remaining extensions and then terminate. + */ + void stop(); + + bool isBusy(); +private: + ExtensionCmdQueue(ExtensionCmdQueue &); // not defined + void operator =(ExtensionCmdQueue &); // not defined + + class Thread; + + rtl::Reference< Thread > m_thread; +}; + +void handleInteractionRequest( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > & xContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionRequest > & xRequest ); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_extlistbox.cxx b/desktop/source/deployment/gui/dp_gui_extlistbox.cxx new file mode 100644 index 000000000000..05511135e2dd --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_extlistbox.cxx @@ -0,0 +1,1223 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "svtools/controldims.hrc" + +#include "dp_gui.h" +#include "dp_gui_extlistbox.hxx" +#include "dp_gui_theextmgr.hxx" +#include "dp_gui_dialog2.hxx" +#include "dp_dependencies.hxx" + +#include "comphelper/processfactory.hxx" +#include "com/sun/star/i18n/CollatorOptions.hpp" +#include "com/sun/star/deployment/DependencyException.hpp" +#include "com/sun/star/deployment/DeploymentException.hpp" + + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + +#define USER_PACKAGE_MANAGER OUSTR("user") +#define SHARED_PACKAGE_MANAGER OUSTR("shared") +#define BUNDLED_PACKAGE_MANAGER OUSTR("bundled") + +using namespace ::com::sun::star; + +namespace dp_gui { + +//------------------------------------------------------------------------------ +// struct Entry_Impl +//------------------------------------------------------------------------------ +Entry_Impl::Entry_Impl( const uno::Reference< deployment::XPackage > &xPackage, + const PackageState eState, const bool bReadOnly ) : + m_bActive( false ), + m_bLocked( bReadOnly ), + m_bHasOptions( false ), + m_bUser( false ), + m_bShared( false ), + m_bNew( false ), + m_bChecked( false ), + m_bMissingDeps( false ), + m_bHasButtons( false ), + m_bMissingLic( false ), + m_eState( eState ), + m_pPublisher( NULL ), + m_xPackage( xPackage ) +{ + try + { + m_sTitle = xPackage->getDisplayName(); + m_sVersion = xPackage->getVersion(); + m_sDescription = xPackage->getDescription(); + + beans::StringPair aInfo( m_xPackage->getPublisherInfo() ); + m_sPublisher = aInfo.First; + m_sPublisherURL = aInfo.Second; + + // get the icons for the package if there are any + uno::Reference< graphic::XGraphic > xGraphic = xPackage->getIcon( false ); + if ( xGraphic.is() ) + m_aIcon = Image( xGraphic ); + + xGraphic = xPackage->getIcon( true ); + if ( xGraphic.is() ) + m_aIconHC = Image( xGraphic ); + else + m_aIconHC = m_aIcon; + + if ( eState == AMBIGUOUS ) + m_sErrorText = DialogHelper::getResourceString( RID_STR_ERROR_UNKNOWN_STATUS ); + else if ( eState == NOT_REGISTERED ) + checkDependencies(); + } + catch (deployment::ExtensionRemovedException &) {} + catch (uno::RuntimeException &) {} +} + +//------------------------------------------------------------------------------ +Entry_Impl::~Entry_Impl() +{} + +//------------------------------------------------------------------------------ +StringCompare Entry_Impl::CompareTo( const CollatorWrapper *pCollator, const TEntry_Impl pEntry ) const +{ + StringCompare eCompare = (StringCompare) pCollator->compareString( m_sTitle, pEntry->m_sTitle ); + if ( eCompare == COMPARE_EQUAL ) + { + eCompare = m_sVersion.CompareTo( pEntry->m_sVersion ); + if ( eCompare == COMPARE_EQUAL ) + { + sal_Int32 nCompare = m_xPackage->getRepositoryName().compareTo( pEntry->m_xPackage->getRepositoryName() ); + if ( nCompare < 0 ) + eCompare = COMPARE_LESS; + else if ( nCompare > 0 ) + eCompare = COMPARE_GREATER; + } + } + return eCompare; +} + +//------------------------------------------------------------------------------ +void Entry_Impl::checkDependencies() +{ + try { + m_xPackage->checkDependencies( uno::Reference< ucb::XCommandEnvironment >() ); + } + catch ( deployment::DeploymentException &e ) + { + deployment::DependencyException depExc; + if ( e.Cause >>= depExc ) + { + rtl::OUString aMissingDep( DialogHelper::getResourceString( RID_STR_ERROR_MISSING_DEPENDENCIES ) ); + for ( sal_Int32 i = 0; i < depExc.UnsatisfiedDependencies.getLength(); ++i ) + { + aMissingDep += OUSTR("\n"); + aMissingDep += dp_misc::Dependencies::getErrorText( depExc.UnsatisfiedDependencies[i]); + } + aMissingDep += OUSTR("\n"); + m_sErrorText = aMissingDep; + m_bMissingDeps = true; + } + } +} +//------------------------------------------------------------------------------ +// ExtensionRemovedListener +//------------------------------------------------------------------------------ +void ExtensionRemovedListener::disposing( lang::EventObject const & rEvt ) + throw ( uno::RuntimeException ) +{ + uno::Reference< deployment::XPackage > xPackage( rEvt.Source, uno::UNO_QUERY ); + + if ( xPackage.is() ) + { + m_pParent->removeEntry( xPackage ); + } +} + +//------------------------------------------------------------------------------ +ExtensionRemovedListener::~ExtensionRemovedListener() +{ +} + +//------------------------------------------------------------------------------ +// ExtensionBox_Impl +//------------------------------------------------------------------------------ +ExtensionBox_Impl::ExtensionBox_Impl( Dialog* pParent, TheExtensionManager *pManager ) : + IExtensionListBox( pParent, WB_BORDER | WB_TABSTOP | WB_CHILDDLGCTRL ), + m_bHasScrollBar( false ), + m_bHasActive( false ), + m_bNeedsRecalc( true ), + m_bHasNew( false ), + m_bInCheckMode( false ), + m_bAdjustActive( false ), + m_bInDelete( false ), + m_nActive( 0 ), + m_nTopIndex( 0 ), + m_nActiveHeight( 0 ), + m_nExtraHeight( 2 ), + m_aSharedImage( DialogHelper::getResId( RID_IMG_SHARED ) ), + m_aSharedImageHC( DialogHelper::getResId( RID_IMG_SHARED_HC ) ), + m_aLockedImage( DialogHelper::getResId( RID_IMG_LOCKED ) ), + m_aLockedImageHC( DialogHelper::getResId( RID_IMG_LOCKED_HC ) ), + m_aWarningImage( DialogHelper::getResId( RID_IMG_WARNING ) ), + m_aWarningImageHC( DialogHelper::getResId( RID_IMG_WARNING_HC ) ), + m_aDefaultImage( DialogHelper::getResId( RID_IMG_EXTENSION ) ), + m_aDefaultImageHC( DialogHelper::getResId( RID_IMG_EXTENSION_HC ) ), + m_pScrollBar( NULL ), + m_pManager( pManager ) +{ + SetHelpId( HID_EXTENSION_MANAGER_LISTBOX ); + + m_pScrollBar = new ScrollBar( this, WB_VERT ); + m_pScrollBar->SetScrollHdl( LINK( this, ExtensionBox_Impl, ScrollHdl ) ); + m_pScrollBar->EnableDrag(); + + SetPaintTransparent( true ); + SetPosPixel( Point( RSC_SP_DLG_INNERBORDER_LEFT, RSC_SP_DLG_INNERBORDER_TOP ) ); + long nIconHeight = 2*TOP_OFFSET + SMALL_ICON_SIZE; + long nTitleHeight = 2*TOP_OFFSET + GetTextHeight(); + if ( nIconHeight < nTitleHeight ) + m_nStdHeight = nTitleHeight; + else + m_nStdHeight = nIconHeight; + m_nStdHeight += GetTextHeight() + TOP_OFFSET; + + nIconHeight = ICON_HEIGHT + 2*TOP_OFFSET + 1; + if ( m_nStdHeight < nIconHeight ) + m_nStdHeight = nIconHeight; + + m_nActiveHeight = m_nStdHeight; + + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + if( IsControlBackground() ) + SetBackground( GetControlBackground() ); + else + SetBackground( rStyleSettings.GetFieldColor() ); + + m_xRemoveListener = new ExtensionRemovedListener( this ); + + m_pLocale = new lang::Locale( Application::GetSettings().GetLocale() ); + m_pCollator = new CollatorWrapper( ::comphelper::getProcessServiceFactory() ); + m_pCollator->loadDefaultCollator( *m_pLocale, i18n::CollatorOptions::CollatorOptions_IGNORE_CASE ); + + Show(); +} + +//------------------------------------------------------------------------------ +ExtensionBox_Impl::~ExtensionBox_Impl() +{ + if ( ! m_bInDelete ) + DeleteRemoved(); + + m_bInDelete = true; + + typedef std::vector< TEntry_Impl >::iterator ITER; + + for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex ) + { + if ( (*iIndex)->m_pPublisher ) + { + delete (*iIndex)->m_pPublisher; + (*iIndex)->m_pPublisher = NULL; + } + (*iIndex)->m_xPackage->removeEventListener( uno::Reference< lang::XEventListener > ( m_xRemoveListener, uno::UNO_QUERY ) ); + } + + m_vEntries.clear(); + + delete m_pScrollBar; + + m_xRemoveListener.clear(); + + delete m_pLocale; + delete m_pCollator; +} + +//------------------------------------------------------------------------------ +sal_Int32 ExtensionBox_Impl::getItemCount() const +{ + return static_cast< sal_Int32 >( m_vEntries.size() ); +} + +//------------------------------------------------------------------------------ +sal_Int32 ExtensionBox_Impl::getSelIndex() const +{ + if ( m_bHasActive ) + { + OSL_ASSERT( m_nActive >= -1); + return static_cast< sal_Int32 >( m_nActive ); + } + else + return static_cast< sal_Int32 >( EXTENSION_LISTBOX_ENTRY_NOTFOUND ); +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::checkIndex( sal_Int32 nIndex ) const +{ + if ( nIndex < 0 ) + throw lang::IllegalArgumentException( OUSTR("The list index starts with 0"),0, 0 ); + if ( static_cast< sal_uInt32 >( nIndex ) >= m_vEntries.size()) + throw lang::IllegalArgumentException( OUSTR("There is no element at the provided position." + "The position exceeds the number of available list entries"),0, 0 ); +} + +//------------------------------------------------------------------------------ +rtl::OUString ExtensionBox_Impl::getItemName( sal_Int32 nIndex ) const +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + checkIndex( nIndex ); + return m_vEntries[ nIndex ]->m_sTitle; +} + +//------------------------------------------------------------------------------ +rtl::OUString ExtensionBox_Impl::getItemVersion( sal_Int32 nIndex ) const +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + checkIndex( nIndex ); + return m_vEntries[ nIndex ]->m_sVersion; +} + +//------------------------------------------------------------------------------ +rtl::OUString ExtensionBox_Impl::getItemDescription( sal_Int32 nIndex ) const +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + checkIndex( nIndex ); + return m_vEntries[ nIndex ]->m_sDescription; +} + +//------------------------------------------------------------------------------ +rtl::OUString ExtensionBox_Impl::getItemPublisher( sal_Int32 nIndex ) const +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + checkIndex( nIndex ); + return m_vEntries[ nIndex ]->m_sPublisher; +} + +//------------------------------------------------------------------------------ +rtl::OUString ExtensionBox_Impl::getItemPublisherLink( sal_Int32 nIndex ) const +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + checkIndex( nIndex ); + return m_vEntries[ nIndex ]->m_sPublisherURL; +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::select( sal_Int32 nIndex ) +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + checkIndex( nIndex ); + selectEntry( nIndex ); +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::select( const rtl::OUString & sName ) +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + typedef ::std::vector< TEntry_Impl >::const_iterator It; + + for ( It iIter = m_vEntries.begin(); iIter < m_vEntries.end(); iIter++ ) + { + if ( sName.equals( (*iIter)->m_sTitle ) ) + { + long nPos = iIter - m_vEntries.begin(); + selectEntry( nPos ); + break; + } + } +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Title + description +void ExtensionBox_Impl::CalcActiveHeight( const long nPos ) +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + + // get title height + long aTextHeight; + long nIconHeight = 2*TOP_OFFSET + SMALL_ICON_SIZE; + long nTitleHeight = 2*TOP_OFFSET + GetTextHeight(); + if ( nIconHeight < nTitleHeight ) + aTextHeight = nTitleHeight; + else + aTextHeight = nIconHeight; + + // calc description height + Size aSize = GetOutputSizePixel(); + if ( m_bHasScrollBar ) + aSize.Width() -= m_pScrollBar->GetSizePixel().Width(); + + aSize.Width() -= ICON_OFFSET; + aSize.Height() = 10000; + + rtl::OUString aText( m_vEntries[ nPos ]->m_sErrorText ); + if ( aText.getLength() ) + aText += OUSTR("\n"); + aText += m_vEntries[ nPos ]->m_sDescription; + + Rectangle aRect = GetTextRect( Rectangle( Point(), aSize ), aText, + TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK ); + aTextHeight += aRect.GetHeight(); + + if ( aTextHeight < m_nStdHeight ) + aTextHeight = m_nStdHeight; + + if ( m_vEntries[ nPos ]->m_bHasButtons ) + m_nActiveHeight = aTextHeight + m_nExtraHeight; + else + m_nActiveHeight = aTextHeight + 2; +} + +//------------------------------------------------------------------------------ +const Size ExtensionBox_Impl::GetMinOutputSizePixel() const +{ + return Size( 200, 80 ); +} + +//------------------------------------------------------------------------------ +Rectangle ExtensionBox_Impl::GetEntryRect( const long nPos ) const +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + + Size aSize( GetOutputSizePixel() ); + + if ( m_bHasScrollBar ) + aSize.Width() -= m_pScrollBar->GetSizePixel().Width(); + + if ( m_vEntries[ nPos ]->m_bActive ) + aSize.Height() = m_nActiveHeight; + else + aSize.Height() = m_nStdHeight; + + Point aPos( 0, -m_nTopIndex + nPos * m_nStdHeight ); + if ( m_bHasActive && ( nPos < m_nActive ) ) + aPos.Y() += m_nActiveHeight - m_nStdHeight; + + return Rectangle( aPos, aSize ); +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::DeleteRemoved() +{ + const ::osl::MutexGuard aGuard( m_entriesMutex ); + + m_bInDelete = true; + + if ( ! m_vRemovedEntries.empty() ) + { + typedef std::vector< TEntry_Impl >::iterator ITER; + + for ( ITER iIndex = m_vRemovedEntries.begin(); iIndex < m_vRemovedEntries.end(); ++iIndex ) + { + if ( (*iIndex)->m_pPublisher ) + { + delete (*iIndex)->m_pPublisher; + (*iIndex)->m_pPublisher = NULL; + } + } + + m_vRemovedEntries.clear(); + } + + m_bInDelete = false; +} + +//------------------------------------------------------------------------------ +//This function may be called with nPos < 0 +void ExtensionBox_Impl::selectEntry( const long nPos ) +{ + //ToDo whe should not use the guard at such a big scope here. + //Currently it is used to gard m_vEntries and m_nActive. m_nActive will be + //modified in this function. + //It would be probably best to always use a copy of m_vEntries + //and some other state variables from ExtensionBox_Impl for + //the whole painting operation. See issue i86993 + ::osl::ClearableMutexGuard guard(m_entriesMutex); + + if ( m_bInCheckMode ) + return; + + if ( m_bHasActive ) + { + if ( nPos == m_nActive ) + return; + + m_bHasActive = false; + m_vEntries[ m_nActive ]->m_bActive = false; + } + + if ( ( nPos >= 0 ) && ( nPos < (long) m_vEntries.size() ) ) + { + m_bHasActive = true; + m_nActive = nPos; + m_vEntries[ nPos ]->m_bActive = true; + + if ( IsReallyVisible() ) + { + m_bAdjustActive = true; + } + } + + if ( IsReallyVisible() ) + { + m_bNeedsRecalc = true; + Invalidate(); + } + + guard.clear(); +} + +// ----------------------------------------------------------------------- +void ExtensionBox_Impl::DrawRow( const Rectangle& rRect, const TEntry_Impl pEntry ) +{ + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + + if ( pEntry->m_bActive ) + SetTextColor( rStyleSettings.GetHighlightTextColor() ); + else if ( ( pEntry->m_eState != REGISTERED ) && ( pEntry->m_eState != NOT_AVAILABLE ) ) + SetTextColor( rStyleSettings.GetDisableColor() ); + else if ( IsControlForeground() ) + SetTextColor( GetControlForeground() ); + else + SetTextColor( rStyleSettings.GetFieldTextColor() ); + + if ( pEntry->m_bActive ) + { + SetLineColor(); + SetFillColor( rStyleSettings.GetHighlightColor() ); + DrawRect( rRect ); + } + else + { + if( IsControlBackground() ) + SetBackground( GetControlBackground() ); + else + SetBackground( rStyleSettings.GetFieldColor() ); + + SetTextFillColor(); + Erase( rRect ); + } + + // Draw extension icon + Point aPos( rRect.TopLeft() ); + aPos += Point( TOP_OFFSET, TOP_OFFSET ); + Image aImage; + if ( ! pEntry->m_aIcon ) + aImage = isHCMode() ? m_aDefaultImageHC : m_aDefaultImage; + else + aImage = isHCMode() ? pEntry->m_aIconHC : pEntry->m_aIcon; + Size aImageSize = aImage.GetSizePixel(); + if ( ( aImageSize.Width() <= ICON_WIDTH ) && ( aImageSize.Height() <= ICON_HEIGHT ) ) + DrawImage( Point( aPos.X()+((ICON_WIDTH-aImageSize.Width())/2), aPos.Y()+((ICON_HEIGHT-aImageSize.Height())/2) ), aImage ); + else + DrawImage( aPos, Size( ICON_WIDTH, ICON_HEIGHT ), aImage ); + + // Setup fonts + Font aStdFont( GetFont() ); + Font aBoldFont( aStdFont ); + aBoldFont.SetWeight( WEIGHT_BOLD ); + SetFont( aBoldFont ); + long aTextHeight = GetTextHeight(); + + // Init publisher link here + if ( !pEntry->m_pPublisher && pEntry->m_sPublisher.Len() ) + { + pEntry->m_pPublisher = new svt::FixedHyperlink( this ); + pEntry->m_pPublisher->SetBackground(); + pEntry->m_pPublisher->SetPaintTransparent( true ); + pEntry->m_pPublisher->SetURL( pEntry->m_sPublisherURL ); + pEntry->m_pPublisher->SetDescription( pEntry->m_sPublisher ); + Size aSize = FixedText::CalcMinimumTextSize( pEntry->m_pPublisher ); + pEntry->m_pPublisher->SetSizePixel( aSize ); + + if ( m_aClickHdl.IsSet() ) + pEntry->m_pPublisher->SetClickHdl( m_aClickHdl ); + } + + // Get max title width + long nMaxTitleWidth = rRect.GetWidth() - ICON_OFFSET; + nMaxTitleWidth -= ( 2 * SMALL_ICON_SIZE ) + ( 4 * SPACE_BETWEEN ); + if ( pEntry->m_pPublisher ) + { + nMaxTitleWidth -= pEntry->m_pPublisher->GetSizePixel().Width() + (2*SPACE_BETWEEN); + } + + long aVersionWidth = GetTextWidth( pEntry->m_sVersion ); + long aTitleWidth = GetTextWidth( pEntry->m_sTitle ) + (aTextHeight / 3); + + aPos = rRect.TopLeft() + Point( ICON_OFFSET, TOP_OFFSET ); + + if ( aTitleWidth > nMaxTitleWidth - aVersionWidth ) + { + aTitleWidth = nMaxTitleWidth - aVersionWidth - (aTextHeight / 3); + String aShortTitle = GetEllipsisString( pEntry->m_sTitle, aTitleWidth ); + DrawText( aPos, aShortTitle ); + aTitleWidth += (aTextHeight / 3); + } + else + DrawText( aPos, pEntry->m_sTitle ); + + SetFont( aStdFont ); + DrawText( Point( aPos.X() + aTitleWidth, aPos.Y() ), pEntry->m_sVersion ); + + long nIconHeight = TOP_OFFSET + SMALL_ICON_SIZE; + long nTitleHeight = TOP_OFFSET + GetTextHeight(); + if ( nIconHeight < nTitleHeight ) + aTextHeight = nTitleHeight; + else + aTextHeight = nIconHeight; + + // draw description + String sDescription; + if ( pEntry->m_sErrorText.Len() ) + { + if ( pEntry->m_bActive ) + sDescription = pEntry->m_sErrorText + OUSTR("\n") + pEntry->m_sDescription; + else + sDescription = pEntry->m_sErrorText; + } + else + sDescription = pEntry->m_sDescription; + + aPos.Y() += aTextHeight; + if ( pEntry->m_bActive ) + { + long nExtraHeight = 0; + + if ( pEntry->m_bHasButtons ) + nExtraHeight = m_nExtraHeight; + + DrawText( Rectangle( aPos.X(), aPos.Y(), rRect.Right(), rRect.Bottom() - nExtraHeight ), + sDescription, TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK ); + } + else + { + const long nWidth = GetTextWidth( sDescription ); + if ( nWidth > rRect.GetWidth() - aPos.X() ) + sDescription = GetEllipsisString( sDescription, rRect.GetWidth() - aPos.X() ); + DrawText( aPos, sDescription ); + } + + // Draw publisher link + if ( pEntry->m_pPublisher ) + { + pEntry->m_pPublisher->Show(); + aPos = rRect.TopLeft() + Point( ICON_OFFSET + nMaxTitleWidth + (2*SPACE_BETWEEN), TOP_OFFSET ); + pEntry->m_pPublisher->SetPosPixel( aPos ); + } + + // Draw status icons + if ( !pEntry->m_bUser ) + { + aPos = rRect.TopRight() + Point( -(RIGHT_ICON_OFFSET + SMALL_ICON_SIZE), TOP_OFFSET ); + if ( pEntry->m_bLocked ) + DrawImage( aPos, Size( SMALL_ICON_SIZE, SMALL_ICON_SIZE ), isHCMode() ? m_aLockedImageHC : m_aLockedImage ); + else + DrawImage( aPos, Size( SMALL_ICON_SIZE, SMALL_ICON_SIZE ), isHCMode() ? m_aSharedImageHC : m_aSharedImage ); + } + if ( ( pEntry->m_eState == AMBIGUOUS ) || pEntry->m_bMissingDeps || pEntry->m_bMissingLic ) + { + aPos = rRect.TopRight() + Point( -(RIGHT_ICON_OFFSET + SPACE_BETWEEN + 2*SMALL_ICON_SIZE), TOP_OFFSET ); + DrawImage( aPos, Size( SMALL_ICON_SIZE, SMALL_ICON_SIZE ), isHCMode() ? m_aWarningImageHC : m_aWarningImage ); + } + + SetLineColor( Color( COL_LIGHTGRAY ) ); + DrawLine( rRect.BottomLeft(), rRect.BottomRight() ); +} + +// ----------------------------------------------------------------------- +void ExtensionBox_Impl::RecalcAll() +{ + if ( m_bHasActive ) + CalcActiveHeight( m_nActive ); + + SetupScrollBar(); + + if ( m_bHasActive ) + { + Rectangle aEntryRect = GetEntryRect( m_nActive ); + + if ( m_bAdjustActive ) + { + m_bAdjustActive = false; + + // If the top of the selected entry isn't visible, make it visible + if ( aEntryRect.Top() < 0 ) + { + m_nTopIndex += aEntryRect.Top(); + aEntryRect.Move( 0, -aEntryRect.Top() ); + } + + // If the bottom of the selected entry isn't visible, make it visible even if now the top + // isn't visible any longer ( the buttons are more important ) + Size aOutputSize = GetOutputSizePixel(); + if ( aEntryRect.Bottom() > aOutputSize.Height() ) + { + m_nTopIndex += ( aEntryRect.Bottom() - aOutputSize.Height() ); + aEntryRect.Move( 0, -( aEntryRect.Bottom() - aOutputSize.Height() ) ); + } + + // If there is unused space below the last entry but all entries don't fit into the box, + // move the content down to use the whole space + const long nTotalHeight = GetTotalHeight(); + if ( m_bHasScrollBar && ( aOutputSize.Height() + m_nTopIndex > nTotalHeight ) ) + { + long nOffset = m_nTopIndex; + m_nTopIndex = nTotalHeight - aOutputSize.Height(); + nOffset -= m_nTopIndex; + aEntryRect.Move( 0, nOffset ); + } + + if ( m_bHasScrollBar ) + m_pScrollBar->SetThumbPos( m_nTopIndex ); + } + } + + m_bNeedsRecalc = false; +} + +// ----------------------------------------------------------------------- +bool ExtensionBox_Impl::HandleTabKey( bool ) +{ + return false; +} + +// ----------------------------------------------------------------------- +bool ExtensionBox_Impl::HandleCursorKey( USHORT nKeyCode ) +{ + if ( m_vEntries.empty() ) + return true; + + long nSelect = 0; + + if ( m_bHasActive ) + { + long nPageSize = GetOutputSizePixel().Height() / m_nStdHeight; + if ( nPageSize < 2 ) + nPageSize = 2; + + if ( ( nKeyCode == KEY_DOWN ) || ( nKeyCode == KEY_RIGHT ) ) + nSelect = m_nActive + 1; + else if ( ( nKeyCode == KEY_UP ) || ( nKeyCode == KEY_LEFT ) ) + nSelect = m_nActive - 1; + else if ( nKeyCode == KEY_HOME ) + nSelect = 0; + else if ( nKeyCode == KEY_END ) + nSelect = m_vEntries.size() - 1; + else if ( nKeyCode == KEY_PAGEUP ) + nSelect = m_nActive - nPageSize + 1; + else if ( nKeyCode == KEY_PAGEDOWN ) + nSelect = m_nActive + nPageSize - 1; + } + else // when there is no selected entry, we will select the first or the last. + { + if ( ( nKeyCode == KEY_DOWN ) || ( nKeyCode == KEY_PAGEDOWN ) || ( nKeyCode == KEY_HOME ) ) + nSelect = 0; + else if ( ( nKeyCode == KEY_UP ) || ( nKeyCode == KEY_PAGEUP ) || ( nKeyCode == KEY_END ) ) + nSelect = m_vEntries.size() - 1; + } + + if ( nSelect < 0 ) + nSelect = 0; + if ( nSelect >= (long) m_vEntries.size() ) + nSelect = m_vEntries.size() - 1; + + selectEntry( nSelect ); + + return true; +} + +// ----------------------------------------------------------------------- +void ExtensionBox_Impl::Paint( const Rectangle &/*rPaintRect*/ ) +{ + if ( !m_bInDelete ) + DeleteRemoved(); + + if ( m_bNeedsRecalc ) + RecalcAll(); + + Point aStart( 0, -m_nTopIndex ); + Size aSize( GetOutputSizePixel() ); + + if ( m_bHasScrollBar ) + aSize.Width() -= m_pScrollBar->GetSizePixel().Width(); + + const ::osl::MutexGuard aGuard( m_entriesMutex ); + + typedef std::vector< TEntry_Impl >::iterator ITER; + for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex ) + { + aSize.Height() = (*iIndex)->m_bActive ? m_nActiveHeight : m_nStdHeight; + Rectangle aEntryRect( aStart, aSize ); + DrawRow( aEntryRect, *iIndex ); + aStart.Y() += aSize.Height(); + } +} + +// ----------------------------------------------------------------------- +long ExtensionBox_Impl::GetTotalHeight() const +{ + long nHeight = m_vEntries.size() * m_nStdHeight; + + if ( m_bHasActive ) + { + nHeight += m_nActiveHeight - m_nStdHeight; + } + + return nHeight; +} + +// ----------------------------------------------------------------------- +void ExtensionBox_Impl::SetupScrollBar() +{ + const Size aSize = GetOutputSizePixel(); + const long nScrBarSize = GetSettings().GetStyleSettings().GetScrollBarSize(); + const long nTotalHeight = GetTotalHeight(); + const bool bNeedsScrollBar = ( nTotalHeight > aSize.Height() ); + + if ( bNeedsScrollBar ) + { + if ( m_nTopIndex + aSize.Height() > nTotalHeight ) + m_nTopIndex = nTotalHeight - aSize.Height(); + + m_pScrollBar->SetPosSizePixel( Point( aSize.Width() - nScrBarSize, 0 ), + Size( nScrBarSize, aSize.Height() ) ); + m_pScrollBar->SetRangeMax( nTotalHeight ); + m_pScrollBar->SetVisibleSize( aSize.Height() ); + m_pScrollBar->SetPageSize( ( aSize.Height() * 4 ) / 5 ); + m_pScrollBar->SetLineSize( m_nStdHeight ); + m_pScrollBar->SetThumbPos( m_nTopIndex ); + + if ( !m_bHasScrollBar ) + m_pScrollBar->Show(); + } + else if ( m_bHasScrollBar ) + { + m_pScrollBar->Hide(); + m_nTopIndex = 0; + } + + m_bHasScrollBar = bNeedsScrollBar; +} + +// ----------------------------------------------------------------------- +void ExtensionBox_Impl::Resize() +{ + RecalcAll(); +} + +//------------------------------------------------------------------------------ +long ExtensionBox_Impl::PointToPos( const Point& rPos ) +{ + long nPos = ( rPos.Y() + m_nTopIndex ) / m_nStdHeight; + + if ( m_bHasActive && ( nPos > m_nActive ) ) + { + if ( rPos.Y() + m_nTopIndex <= m_nActive*m_nStdHeight + m_nActiveHeight ) + nPos = m_nActive; + else + nPos = ( rPos.Y() + m_nTopIndex - (m_nActiveHeight - m_nStdHeight) ) / m_nStdHeight; + } + + return nPos; +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::MouseButtonDown( const MouseEvent& rMEvt ) +{ + long nPos = PointToPos( rMEvt.GetPosPixel() ); + + if ( rMEvt.IsLeft() ) + { + if ( rMEvt.IsMod1() && m_bHasActive ) + selectEntry( m_vEntries.size() ); // Selecting an not existing entry will deselect the current one + else + selectEntry( nPos ); + } +} + +//------------------------------------------------------------------------------ +long ExtensionBox_Impl::Notify( NotifyEvent& rNEvt ) +{ + if ( !m_bInDelete ) + DeleteRemoved(); + + bool bHandled = false; + + if ( rNEvt.GetType() == EVENT_KEYINPUT ) + { + const KeyEvent* pKEvt = rNEvt.GetKeyEvent(); + KeyCode aKeyCode = pKEvt->GetKeyCode(); + USHORT nKeyCode = aKeyCode.GetCode(); + + if ( nKeyCode == KEY_TAB ) + bHandled = HandleTabKey( aKeyCode.IsShift() ); + else if ( aKeyCode.GetGroup() == KEYGROUP_CURSOR ) + bHandled = HandleCursorKey( nKeyCode ); + } + + if ( rNEvt.GetType() == EVENT_COMMAND ) + { + if ( m_bHasScrollBar && + ( rNEvt.GetCommandEvent()->GetCommand() == COMMAND_WHEEL ) ) + { + const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData(); + if ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) + { + long nThumbPos = m_pScrollBar->GetThumbPos(); + if ( pData->GetDelta() < 0 ) + m_pScrollBar->DoScroll( nThumbPos + m_nStdHeight ); + else + m_pScrollBar->DoScroll( nThumbPos - m_nStdHeight ); + bHandled = true; + } + } + } + + if ( !bHandled ) + return Control::Notify( rNEvt ); + else + return true; +} + +//------------------------------------------------------------------------------ +bool ExtensionBox_Impl::FindEntryPos( const TEntry_Impl pEntry, const long nStart, + const long nEnd, long &nPos ) +{ + nPos = nStart; + if ( nStart > nEnd ) + return false; + + StringCompare eCompare; + + if ( nStart == nEnd ) + { + eCompare = pEntry->CompareTo( m_pCollator, m_vEntries[ nStart ] ); + if ( eCompare == COMPARE_LESS ) + return false; + else if ( eCompare == COMPARE_EQUAL ) + { + //Workaround. See i86963. + if (pEntry->m_xPackage != m_vEntries[nStart]->m_xPackage) + return false; + + if ( m_bInCheckMode ) + m_vEntries[ nStart ]->m_bChecked = true; + return true; + } + else + { + nPos = nStart + 1; + return false; + } + } + + const long nMid = nStart + ( ( nEnd - nStart ) / 2 ); + eCompare = pEntry->CompareTo( m_pCollator, m_vEntries[ nMid ] ); + + if ( eCompare == COMPARE_LESS ) + return FindEntryPos( pEntry, nStart, nMid-1, nPos ); + else if ( eCompare == COMPARE_GREATER ) + return FindEntryPos( pEntry, nMid+1, nEnd, nPos ); + else + { + //Workaround.See i86963. + if (pEntry->m_xPackage != m_vEntries[nMid]->m_xPackage) + return false; + + if ( m_bInCheckMode ) + m_vEntries[ nMid ]->m_bChecked = true; + nPos = nMid; + return true; + } +} + +//------------------------------------------------------------------------------ +long ExtensionBox_Impl::addEntry( const uno::Reference< deployment::XPackage > &xPackage, + bool bLicenseMissing ) +{ + long nPos = 0; + PackageState eState = m_pManager->getPackageState( xPackage ); + bool bLocked = m_pManager->isReadOnly( xPackage ); + + TEntry_Impl pEntry( new Entry_Impl( xPackage, eState, bLocked ) ); + + // Don't add empty entries + if ( ! pEntry->m_sTitle.Len() ) + return 0; + + xPackage->addEventListener( uno::Reference< lang::XEventListener > ( m_xRemoveListener, uno::UNO_QUERY ) ); + + ::osl::ClearableMutexGuard guard(m_entriesMutex); + if ( m_vEntries.empty() ) + { + m_vEntries.push_back( pEntry ); + } + else + { + if ( !FindEntryPos( pEntry, 0, m_vEntries.size()-1, nPos ) ) + { + m_vEntries.insert( m_vEntries.begin()+nPos, pEntry ); + } + else if ( !m_bInCheckMode ) + { + OSL_ENSURE( 0, "ExtensionBox_Impl::addEntry(): Will not add duplicate entries" ); + } + } + + pEntry->m_bHasOptions = m_pManager->supportsOptions( xPackage ); + pEntry->m_bUser = xPackage->getRepositoryName().equals( USER_PACKAGE_MANAGER ); + pEntry->m_bShared = xPackage->getRepositoryName().equals( SHARED_PACKAGE_MANAGER ); + pEntry->m_bNew = m_bInCheckMode; + pEntry->m_bMissingLic = bLicenseMissing; + + if ( bLicenseMissing ) + pEntry->m_sErrorText = DialogHelper::getResourceString( RID_STR_ERROR_MISSING_LICENSE ); + + //access to m_nActive must be guarded + if ( !m_bInCheckMode && m_bHasActive && ( m_nActive >= nPos ) ) + m_nActive += 1; + + guard.clear(); + + if ( IsReallyVisible() ) + Invalidate(); + + m_bNeedsRecalc = true; + + return nPos; +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::updateEntry( const uno::Reference< deployment::XPackage > &xPackage ) +{ + typedef std::vector< TEntry_Impl >::iterator ITER; + for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex ) + { + if ( (*iIndex)->m_xPackage == xPackage ) + { + PackageState eState = m_pManager->getPackageState( xPackage ); + (*iIndex)->m_bHasOptions = m_pManager->supportsOptions( xPackage ); + (*iIndex)->m_eState = eState; + (*iIndex)->m_sTitle = xPackage->getDisplayName(); + (*iIndex)->m_sVersion = xPackage->getVersion(); + (*iIndex)->m_sDescription = xPackage->getDescription(); + + if ( eState == REGISTERED ) + (*iIndex)->m_bMissingLic = false; + + if ( eState == AMBIGUOUS ) + (*iIndex)->m_sErrorText = DialogHelper::getResourceString( RID_STR_ERROR_UNKNOWN_STATUS ); + else if ( ! (*iIndex)->m_bMissingLic ) + (*iIndex)->m_sErrorText = String(); + + if ( IsReallyVisible() ) + Invalidate(); + break; + } + } +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::removeEntry( const uno::Reference< deployment::XPackage > &xPackage ) +{ + if ( ! m_bInDelete ) + { + ::osl::ClearableMutexGuard aGuard( m_entriesMutex ); + + typedef std::vector< TEntry_Impl >::iterator ITER; + + for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex ) + { + if ( (*iIndex)->m_xPackage == xPackage ) + { + long nPos = iIndex - m_vEntries.begin(); + + // Entries mustn't removed here, because they contain a hyperlink control + // which can only be deleted when the thread has the solar mutex. Therefor + // the entry will be moved into the m_vRemovedEntries list which will be + // cleared on the next paint event + m_vRemovedEntries.push_back( *iIndex ); + m_vEntries.erase( iIndex ); + + m_bNeedsRecalc = true; + + if ( IsReallyVisible() ) + Invalidate(); + + if ( m_bHasActive ) + { + if ( nPos < m_nActive ) + m_nActive -= 1; + else if ( ( nPos == m_nActive ) && + ( nPos == (long) m_vEntries.size() ) ) + m_nActive -= 1; + + m_bHasActive = false; + //clear before calling out of this method + aGuard.clear(); + selectEntry( m_nActive ); + } + break; + } + } + } +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::RemoveUnlocked() +{ + bool bAllRemoved = false; + + while ( ! bAllRemoved ) + { + bAllRemoved = true; + + ::osl::ClearableMutexGuard aGuard( m_entriesMutex ); + + typedef std::vector< TEntry_Impl >::iterator ITER; + + for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex ) + { + if ( !(*iIndex)->m_bLocked ) + { + bAllRemoved = false; + uno::Reference< deployment::XPackage> xPackage = (*iIndex)->m_xPackage; + aGuard.clear(); + removeEntry( xPackage ); + break; + } + } + } +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::prepareChecking() +{ + m_bInCheckMode = true; + typedef std::vector< TEntry_Impl >::iterator ITER; + for ( ITER iIndex = m_vEntries.begin(); iIndex < m_vEntries.end(); ++iIndex ) + { + (*iIndex)->m_bChecked = false; + (*iIndex)->m_bNew = false; + } +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::checkEntries() +{ + long nNewPos = -1; + long nPos = 0; + bool bNeedsUpdate = false; + + ::osl::ClearableMutexGuard guard(m_entriesMutex); + typedef std::vector< TEntry_Impl >::iterator ITER; + ITER iIndex = m_vEntries.begin(); + while ( iIndex < m_vEntries.end() ) + { + if ( (*iIndex)->m_bChecked == false ) + { + (*iIndex)->m_bChecked = true; + bNeedsUpdate = true; + nPos = iIndex-m_vEntries.begin(); + if ( (*iIndex)->m_bNew ) + { // add entry to list and correct active pos + if ( nNewPos == - 1) + nNewPos = nPos; + if ( nPos <= m_nActive ) + m_nActive += 1; + iIndex++; + } + else + { // remove entry from list + if ( nPos < m_nActive ) + m_nActive -= 1; + else if ( ( nPos == m_nActive ) && ( nPos == (long) m_vEntries.size() - 1 ) ) + m_nActive -= 1; + m_vRemovedEntries.push_back( *iIndex ); + m_vEntries.erase( iIndex ); + iIndex = m_vEntries.begin() + nPos; + } + } + else + iIndex++; + } + guard.clear(); + + m_bInCheckMode = false; + + if ( nNewPos != - 1) + selectEntry( nNewPos ); + + if ( bNeedsUpdate ) + { + m_bNeedsRecalc = true; + if ( IsReallyVisible() ) + Invalidate(); + } +} +//------------------------------------------------------------------------------ +bool ExtensionBox_Impl::isHCMode() +{ + return (bool)GetSettings().GetStyleSettings().GetHighContrastMode(); +} + +//------------------------------------------------------------------------------ +void ExtensionBox_Impl::SetScrollHdl( const Link& rLink ) +{ + if ( m_pScrollBar ) + m_pScrollBar->SetScrollHdl( rLink ); +} + +// ----------------------------------------------------------------------- +void ExtensionBox_Impl::DoScroll( long nDelta ) +{ + m_nTopIndex += nDelta; + Point aNewSBPt( m_pScrollBar->GetPosPixel() ); + + Rectangle aScrRect( Point(), GetOutputSizePixel() ); + aScrRect.Right() -= m_pScrollBar->GetSizePixel().Width(); + Scroll( 0, -nDelta, aScrRect ); + + m_pScrollBar->SetPosPixel( aNewSBPt ); +} + +// ----------------------------------------------------------------------- +IMPL_LINK( ExtensionBox_Impl, ScrollHdl, ScrollBar*, pScrBar ) +{ + DoScroll( pScrBar->GetDelta() ); + + return 1; +} + +} //namespace dp_gui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_extlistbox.hxx b/desktop/source/deployment/gui/dp_gui_extlistbox.hxx new file mode 100644 index 000000000000..4726a0c9e20d --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_extlistbox.hxx @@ -0,0 +1,273 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "rtl/ustring.hxx" +#include "vcl/scrbar.hxx" +#include "vcl/fixed.hxx" +#include "vcl/dialog.hxx" + +#include "svtools/extensionlistbox.hxx" +#include "svtools/fixedhyper.hxx" +#include "cppuhelper/implbase1.hxx" +#include "unotools/collatorwrapper.hxx" + +#include "com/sun/star/lang/Locale.hpp" +#include "com/sun/star/lang/XEventListener.hpp" +#include "com/sun/star/deployment/XPackage.hpp" + +#include <boost/shared_ptr.hpp> + +namespace dp_gui { + +#define SMALL_ICON_SIZE 16 +#define TOP_OFFSET 5 +#define ICON_HEIGHT 42 +#define ICON_WIDTH 47 +#define ICON_OFFSET 72 +#define RIGHT_ICON_OFFSET 5 +#define SPACE_BETWEEN 3 + +class TheExtensionManager; + +typedef ::boost::shared_ptr< svt::FixedHyperlink > TFixedHyperlink; + +//------------------------------------------------------------------------------ +// struct Entry_Impl +//------------------------------------------------------------------------------ +struct Entry_Impl; + +typedef ::boost::shared_ptr< Entry_Impl > TEntry_Impl; + +struct Entry_Impl +{ + bool m_bActive :1; + bool m_bLocked :1; + bool m_bHasOptions :1; + bool m_bUser :1; + bool m_bShared :1; + bool m_bNew :1; + bool m_bChecked :1; + bool m_bMissingDeps :1; + bool m_bHasButtons :1; + bool m_bMissingLic :1; + PackageState m_eState; + String m_sTitle; + String m_sVersion; + String m_sDescription; + String m_sPublisher; + String m_sPublisherURL; + String m_sErrorText; + Image m_aIcon; + Image m_aIconHC; + svt::FixedHyperlink *m_pPublisher; + + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage> m_xPackage; + + Entry_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage, + const PackageState eState, const bool bReadOnly ); + ~Entry_Impl(); + + StringCompare CompareTo( const CollatorWrapper *pCollator, const TEntry_Impl pEntry ) const; + void checkDependencies(); +}; + +//------------------------------------------------------------------------------ +// class ExtensionBox_Impl +//------------------------------------------------------------------------------ + +class ExtensionBox_Impl; + +//------------------------------------------------------------------------------ +class ExtensionRemovedListener : public ::cppu::WeakImplHelper1< ::com::sun::star::lang::XEventListener > +{ + ExtensionBox_Impl *m_pParent; + +public: + + ExtensionRemovedListener( ExtensionBox_Impl *pParent ) { m_pParent = pParent; } + ~ExtensionRemovedListener(); + + //=================================================================================== + // XEventListener + virtual void SAL_CALL disposing( ::com::sun::star::lang::EventObject const & evt ) + throw (::com::sun::star::uno::RuntimeException); +}; + +//------------------------------------------------------------------------------ +class ExtensionBox_Impl : public ::svt::IExtensionListBox +{ + bool m_bHasScrollBar; + bool m_bHasActive; + bool m_bNeedsRecalc; + bool m_bHasNew; + bool m_bInCheckMode; + bool m_bAdjustActive; + bool m_bInDelete; + //Must be guarded together with m_vEntries to ensure a valid index at all times. + //Use m_entriesMutex as guard. + long m_nActive; + long m_nTopIndex; + long m_nStdHeight; + long m_nActiveHeight; + long m_nExtraHeight; + Size m_aOutputSize; + Image m_aSharedImage; + Image m_aSharedImageHC; + Image m_aLockedImage; + Image m_aLockedImageHC; + Image m_aWarningImage; + Image m_aWarningImageHC; + Image m_aDefaultImage; + Image m_aDefaultImageHC; + Link m_aClickHdl; + + ScrollBar *m_pScrollBar; + + com::sun::star::uno::Reference< ExtensionRemovedListener > m_xRemoveListener; + + TheExtensionManager *m_pManager; + //This mutex is used for synchronizing access to m_vEntries. + //Currently it is used to synchronize adding, removing entries and + //functions like getItemName, getItemDescription, etc. to prevent + //that m_vEntries is accessed at an invalid index. + //ToDo: There are many more places where m_vEntries is read and which may + //fail. For example the Paint method is probable called from the main thread + //while new entries are added / removed in a separate thread. + mutable ::osl::Mutex m_entriesMutex; + std::vector< TEntry_Impl > m_vEntries; + std::vector< TEntry_Impl > m_vRemovedEntries; + + ::com::sun::star::lang::Locale *m_pLocale; + CollatorWrapper *m_pCollator; + + void CalcActiveHeight( const long nPos ); + long GetTotalHeight() const; + void SetupScrollBar(); + void DrawRow( const Rectangle& rRect, const TEntry_Impl pEntry ); + bool HandleTabKey( bool bReverse ); + bool HandleCursorKey( USHORT nKeyCode ); + bool FindEntryPos( const TEntry_Impl pEntry, long nStart, long nEnd, long &nFound ); + bool isHCMode(); + void DeleteRemoved(); + + //----------------- + DECL_DLLPRIVATE_LINK( ScrollHdl, ScrollBar * ); + + //Index starts with 1. + //Throws an com::sun::star::lang::IllegalArgumentException, when the index is invalid. + void checkIndex(sal_Int32 pos) const; + + +public: + ExtensionBox_Impl( Dialog* pParent, TheExtensionManager *pManager ); + ~ExtensionBox_Impl(); + + virtual void MouseButtonDown( const MouseEvent& rMEvt ); + virtual void Paint( const Rectangle &rPaintRect ); + virtual void Resize(); + virtual long Notify( NotifyEvent& rNEvt ); + + const Size GetMinOutputSizePixel() const; + void SetExtraSize( long nSize ) { m_nExtraHeight = nSize; } + TEntry_Impl GetEntryData( long nPos ) { return m_vEntries[ nPos ]; } + long GetEntryCount() { return (long) m_vEntries.size(); } + Rectangle GetEntryRect( const long nPos ) const; + bool HasActive() { return m_bHasActive; } + long PointToPos( const Point& rPos ); + void SetScrollHdl( const Link& rLink ); + void DoScroll( long nDelta ); + void SetHyperlinkHdl( const Link& rLink ){ m_aClickHdl = rLink; } + virtual void RecalcAll(); + void RemoveUnlocked(); + + //----------------- + virtual void selectEntry( const long nPos ); + long addEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage, + bool bLicenseMissing = false ); + void updateEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ); + void removeEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ); + + void prepareChecking(); + void checkEntries(); + + TheExtensionManager* getExtensionManager() const { return m_pManager; } + + //=================================================================================== + //These functions are used for automatic testing + + /** @return The count of the entries in the list box. */ + virtual sal_Int32 getItemCount() const; + + /** @return The index of the first selected entry in the list box. + When nothing is selected, which is the case when getItemCount returns '0', + then this function returns EXTENSION_LISTBOX_ENTRY_NOTFOUND */ + virtual sal_Int32 getSelIndex() const; + + /** @return The item name of the entry with the given index + The index starts with 0. + Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */ + virtual ::rtl::OUString getItemName( sal_Int32 index ) const; + + /** @return The version string of the entry with the given index + The index starts with 0. + Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */ + virtual ::rtl::OUString getItemVersion( sal_Int32 index ) const; + + /** @return The description string of the entry with the given index + The index starts with 0. + Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */ + virtual ::rtl::OUString getItemDescription( sal_Int32 index ) const; + + /** @return The publisher string of the entry with the given index + The index starts with 0. + Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */ + virtual ::rtl::OUString getItemPublisher( sal_Int32 index ) const; + + /** @return The link behind the publisher text of the entry with the given index + The index starts with 0. + Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */ + virtual ::rtl::OUString getItemPublisherLink( sal_Int32 index ) const; + + /** The entry at the given position will be selected + Index starts with 0. + Throws an com::sun::star::lang::IllegalArgumentException, when the position is invalid. */ + virtual void select( sal_Int32 pos ); + + /** The first found entry with the given name will be selected + When there was no entry found with the name, the selection doesn't change. + Please note that there might be more than one entry with the same + name, because: + 1. the name is not unique + 2. one extension can be installed as user and shared extension. + */ + virtual void select( const ::rtl::OUString & sName ); +}; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_service.cxx b/desktop/source/deployment/gui/dp_gui_service.cxx new file mode 100644 index 000000000000..a01b8b309d00 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_service.cxx @@ -0,0 +1,379 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_gui_shared.hxx" +#include "dp_gui.h" +#include "dp_gui_theextmgr.hxx" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "unotools/configmgr.hxx" +#include "comphelper/servicedecl.hxx" +#include "comphelper/unwrapargs.hxx" +#include <i18npool/mslangid.hxx> +#include "vcl/svapp.hxx" +#include "vcl/msgbox.hxx" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/task/XJobExecutor.hpp" +#include "com/sun/star/ui/dialogs/XAsynchronousExecutableDialog.hpp" + +#include "boost/bind.hpp" +#include "license_dialog.hxx" +#include "dp_gui_dialog2.hxx" +#include "dp_gui_extensioncmdqueue.hxx" + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +using ::rtl::OUString; + +namespace css = ::com::sun::star; +namespace dp_gui { + +//============================================================================== +class MyApp : public Application, private boost::noncopyable +{ +public: + MyApp(); + virtual ~MyApp(); + + // Application + virtual void Main(); +}; + +//______________________________________________________________________________ +MyApp::~MyApp() +{ +} + +//______________________________________________________________________________ +MyApp::MyApp() +{ +} + +//______________________________________________________________________________ +void MyApp::Main() +{ +} + +//############################################################################## + +namespace +{ + struct ProductName + : public rtl::Static< String, ProductName > {}; + 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 > {}; +} + +void ReplaceProductNameHookProc( String& rStr ) +{ + static int nAll = 0, nPro = 0; + + nAll++; + if ( rStr.SearchAscii( "%PRODUCT" ) != STRING_NOTFOUND ) + { + String &rProductName = ProductName::get(); + String &rVersion = Version::get(); + String &rAboutBoxVersion = AboutBoxVersion::get(); + String &rExtension = Extension::get(); + String &rOOOVendor = OOOVendor::get(); + + if ( !rProductName.Len() ) + { + rtl::OUString aTmp; + Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME ); + aRet >>= aTmp; + rProductName = aTmp; + + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTVERSION ); + aRet >>= aTmp; + rVersion = aTmp; + + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::ABOUTBOXPRODUCTVERSION ); + aRet >>= aTmp; + rAboutBoxVersion = aTmp; + + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::OOOVENDOR ); + aRet >>= aTmp; + rOOOVendor = aTmp; + + if ( !rExtension.Len() ) + { + aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTEXTENSION ); + aRet >>= aTmp; + rExtension = aTmp; + } + } + + nPro++; + rStr.SearchAndReplaceAllAscii( "%PRODUCTNAME", rProductName ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTVERSION", rVersion ); + rStr.SearchAndReplaceAllAscii( "%ABOUTBOXPRODUCTVERSION", rAboutBoxVersion ); + rStr.SearchAndReplaceAllAscii( "%OOOVENDOR", rOOOVendor ); + rStr.SearchAndReplaceAllAscii( "%PRODUCTEXTENSION", rExtension ); + } +} + +//============================================================================== +class ServiceImpl + : public ::cppu::WeakImplHelper2<ui::dialogs::XAsynchronousExecutableDialog, + task::XJobExecutor> +{ + Reference<XComponentContext> const m_xComponentContext; + boost::optional< Reference<awt::XWindow> > /* const */ m_parent; + boost::optional<OUString> /* const */ m_view; + /* if true then this service is running in an unopkg process and not in an office process */ + boost::optional<sal_Bool> /* const */ m_unopkg; + boost::optional<OUString> m_extensionURL; + OUString m_initialTitle; + bool m_bShowUpdateOnly; + +public: + ServiceImpl( Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ); + + // XAsynchronousExecutableDialog + virtual void SAL_CALL setDialogTitle( OUString const & aTitle ) + throw (RuntimeException); + virtual void SAL_CALL startExecuteModal( + Reference< ui::dialogs::XDialogClosedListener > const & xListener ) + throw (RuntimeException); + + // XJobExecutor + virtual void SAL_CALL trigger( OUString const & event ) + throw (RuntimeException); +}; + +//______________________________________________________________________________ +ServiceImpl::ServiceImpl( Sequence<Any> const& args, + Reference<XComponentContext> const& xComponentContext) + : m_xComponentContext(xComponentContext), + m_bShowUpdateOnly( false ) +{ + try { + comphelper::unwrapArgs( args, m_parent, m_view, m_unopkg ); + return; + } catch (css::lang::IllegalArgumentException & ) { + } + try { + comphelper::unwrapArgs( args, m_extensionURL); + } catch (css::lang::IllegalArgumentException & ) { + } + + ResHookProc pProc = ResMgr::GetReadStringHook(); + if ( !pProc ) + ResMgr::SetReadStringHook( ReplaceProductNameHookProc ); +} + +// XAsynchronousExecutableDialog +//______________________________________________________________________________ +void ServiceImpl::setDialogTitle( OUString const & title ) + throw (RuntimeException) +{ + if ( dp_gui::TheExtensionManager::s_ExtMgr.is() ) + { + const SolarMutexGuard guard; + ::rtl::Reference< ::dp_gui::TheExtensionManager > dialog( + ::dp_gui::TheExtensionManager::get( m_xComponentContext, + m_parent ? *m_parent : Reference<awt::XWindow>(), + m_extensionURL ? *m_extensionURL : OUString() ) ); + dialog->SetText( title ); + } + else + m_initialTitle = title; +} + +//______________________________________________________________________________ +void ServiceImpl::startExecuteModal( + Reference< ui::dialogs::XDialogClosedListener > const & xListener ) + throw (RuntimeException) +{ + bool bCloseDialog = true; // only used if m_bShowUpdateOnly is true + ::std::auto_ptr<Application> app; + //ToDo: synchronize access to s_dialog !!! + if (! dp_gui::TheExtensionManager::s_ExtMgr.is()) + { + const bool bAppUp = (GetpApp() != 0); + bool bOfficePipePresent; + try { + bOfficePipePresent = dp_misc::office_is_running(); + } + catch (Exception & exc) { + if (bAppUp) { + const SolarMutexGuard guard; + std::auto_ptr<ErrorBox> box( + new ErrorBox( Application::GetActiveTopWindow(), + WB_OK, exc.Message ) ); + box->Execute(); + } + throw; + } + + if (! bOfficePipePresent) { + OSL_ASSERT( ! bAppUp ); + app.reset( new MyApp ); + if (! InitVCL( Reference<lang::XMultiServiceFactory>( + m_xComponentContext->getServiceManager(), + UNO_QUERY_THROW ) )) + throw RuntimeException( OUSTR("Cannot initialize VCL!"), + static_cast<OWeakObject *>(this) ); + AllSettings as = app->GetSettings(); + OUString slang; + if (! (::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::LOCALE ) >>= slang)) + throw RuntimeException( OUSTR("Cannot determine language!"), + static_cast<OWeakObject *>(this) ); + as.SetUILanguage( MsLangId::convertIsoStringToLanguage( slang ) ); + app->SetSettings( as ); + String sTitle = ::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::PRODUCTNAME).get<OUString>() + + String(static_cast<sal_Unicode>(' ')) + + ::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::PRODUCTVERSION).get<OUString>(); + app->SetDisplayName(sTitle); + ExtensionCmdQueue::syncRepositories( m_xComponentContext ); + } + } + else + { + // When m_bShowUpdateOnly is set, we are inside the office and the user clicked + // the update notification icon in the menu bar. We must not close the extensions + // dialog after displaying the update dialog when it has been visible before + if ( m_bShowUpdateOnly ) + bCloseDialog = ! dp_gui::TheExtensionManager::s_ExtMgr->isVisible(); + } + + { + const SolarMutexGuard guard; + ::rtl::Reference< ::dp_gui::TheExtensionManager > myExtMgr( + ::dp_gui::TheExtensionManager::get( + m_xComponentContext, + m_parent ? *m_parent : Reference<awt::XWindow>(), + m_extensionURL ? *m_extensionURL : OUString() ) ); + myExtMgr->createDialog( false ); + if (m_initialTitle.getLength() > 0) { + myExtMgr->SetText( m_initialTitle ); + m_initialTitle = OUString(); + } + if ( m_bShowUpdateOnly ) + { + myExtMgr->checkUpdates( true, !bCloseDialog ); + if ( bCloseDialog ) + myExtMgr->Close(); + else + myExtMgr->ToTop( TOTOP_RESTOREWHENMIN ); + } + else + { + myExtMgr->Show(); + myExtMgr->ToTop( TOTOP_RESTOREWHENMIN ); + } + } + + if (app.get() != 0) { + Application::Execute(); + DeInitVCL(); + } + + if (xListener.is()) + xListener->dialogClosed( + ui::dialogs::DialogClosedEvent( + static_cast< ::cppu::OWeakObject * >(this), + sal_Int16(0)) ); +} + +// XJobExecutor +//______________________________________________________________________________ +void ServiceImpl::trigger( OUString const &rEvent ) throw (RuntimeException) +{ + if ( rEvent == OUSTR("SHOW_UPDATE_DIALOG") ) + m_bShowUpdateOnly = true; + else + m_bShowUpdateOnly = false; + + startExecuteModal( Reference< ui::dialogs::XDialogClosedListener >() ); +} + +namespace sdecl = comphelper::service_decl; +sdecl::class_<ServiceImpl, sdecl::with_args<true> > serviceSI; +sdecl::ServiceDecl const serviceDecl( + serviceSI, + "com.sun.star.comp.deployment.ui.PackageManagerDialog", + "com.sun.star.deployment.ui.PackageManagerDialog" ); + +sdecl::class_<LicenseDialog, sdecl::with_args<true> > licenseSI; +sdecl::ServiceDecl const licenseDecl( + licenseSI, + "com.sun.star.comp.deployment.ui.LicenseDialog", + "com.sun.star.deployment.ui.LicenseDialog" ); + +sdecl::class_<UpdateRequiredDialogService, sdecl::with_args<true> > updateSI; +sdecl::ServiceDecl const updateDecl( + updateSI, + "com.sun.star.comp.deployment.ui.UpdateRequiredDialog", + "com.sun.star.deployment.ui.UpdateRequiredDialog" ); +} // namespace dp_gui + +extern "C" { + +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +sal_Bool SAL_CALL component_writeInfo( + lang::XMultiServiceFactory * pServiceManager, + registry::XRegistryKey * pRegistryKey ) +{ + return component_writeInfoHelper( + pServiceManager, pRegistryKey, dp_gui::serviceDecl, dp_gui::licenseDecl, dp_gui::updateDecl ); +} + +void * SAL_CALL component_getFactory( + sal_Char const * pImplName, + lang::XMultiServiceFactory * pServiceManager, + registry::XRegistryKey * pRegistryKey ) +{ + return component_getFactoryHelper( + pImplName, pServiceManager, pRegistryKey, dp_gui::serviceDecl, dp_gui::licenseDecl, dp_gui::updateDecl ); +} + +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_shared.hxx b/desktop/source/deployment/gui/dp_gui_shared.hxx new file mode 100644 index 000000000000..af3a0bd5b980 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_shared.hxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if !defined INCLUDED_DP_GUI_SHARED_HXX +#define INCLUDED_DP_GUI_SHARED_HXX + +#include "unotools/configmgr.hxx" +#include "rtl/instance.hxx" +#include "tools/resmgr.hxx" + + +namespace css = ::com::sun::star; + +namespace dp_gui { + +struct DeploymentGuiResMgr : + public ::rtl::StaticWithInit< ResMgr *, DeploymentGuiResMgr > { + ResMgr * operator () () { + return ResMgr::CreateResMgr( "deploymentgui" ); + } +}; + +struct BrandName : public ::rtl::StaticWithInit<const ::rtl::OUString, BrandName> { + const ::rtl::OUString operator () () { + return ::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::PRODUCTNAME ).get< ::rtl::OUString >(); + } +}; + +class DpGuiResId : public ResId +{ +public: + DpGuiResId( USHORT nId ):ResId( nId, *DeploymentGuiResMgr::get() ) {} +}; + +} // namespace dp_gui + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_system.cxx b/desktop/source/deployment/gui/dp_gui_system.cxx new file mode 100644 index 000000000000..0e6416f1616d --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_system.cxx @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_gui_system.hxx" +#ifdef WNT +#define WIN32_LEAN_AND_MEAN +#ifdef _MSC_VER +#pragma warning(push,1) /* disable warnings within system headers */ +#endif +#include <windows.h> +#ifdef _MSC_VER +#pragma warning(pop) +#endif +#endif + +namespace dp_gui { + +//We cannot distinguish Vista and 2008 Server +bool isVista() +{ +#ifdef WNT + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + return osvi.dwMajorVersion >= 6; +#else + return false; +#endif +} + +} //namespace dp_gui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_system.hxx b/desktop/source/deployment/gui/dp_gui_system.hxx new file mode 100644 index 000000000000..8c8feb43cf00 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_system.hxx @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_DEPLOYMENT_GUI_DP_GUI_SYSTEM_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_SYSTEM_HXX + + +/// @HTML +namespace dp_gui { +bool isVista(); + +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_theextmgr.cxx b/desktop/source/deployment/gui/dp_gui_theextmgr.cxx new file mode 100644 index 000000000000..564580c520bc --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_theextmgr.cxx @@ -0,0 +1,533 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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/svapp.hxx" +#include "vcl/msgbox.hxx" + +#include "osl/mutex.hxx" + +#include "toolkit/helper/vclunohelper.hxx" + +#include "com/sun/star/beans/XPropertySet.hpp" + +#include "dp_gui_dialog2.hxx" +#include "dp_gui_extensioncmdqueue.hxx" +#include "dp_gui_theextmgr.hxx" +#include "dp_gui_theextmgr.hxx" +#include "dp_identifier.hxx" +#include "dp_update.hxx" + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + +#define USER_PACKAGE_MANAGER OUSTR("user") +#define SHARED_PACKAGE_MANAGER OUSTR("shared") +#define BUNDLED_PACKAGE_MANAGER OUSTR("bundled") + +using namespace ::com::sun::star; +using ::rtl::OUString; + +namespace dp_gui { + +//------------------------------------------------------------------------------ + +::rtl::Reference< TheExtensionManager > TheExtensionManager::s_ExtMgr; + +//------------------------------------------------------------------------------ +// TheExtensionManager +//------------------------------------------------------------------------------ + +TheExtensionManager::TheExtensionManager( Window *pParent, + const uno::Reference< uno::XComponentContext > &xContext ) : + m_xContext( xContext ), + m_pParent( pParent ), + m_pExtMgrDialog( NULL ), + m_pUpdReqDialog( NULL ), + m_pExecuteCmdQueue( NULL ) +{ + m_xExtensionManager = deployment::ExtensionManager::get( xContext ); + m_xExtensionManager->addModifyListener( this ); + + uno::Reference< lang::XMultiServiceFactory > xConfig( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.configuration.ConfigurationProvider"), xContext ), uno::UNO_QUERY_THROW); + uno::Any args[1]; + beans::PropertyValue aValue( OUSTR("nodepath"), 0, uno::Any( OUSTR("/org.openoffice.Office.OptionsDialog/Nodes") ), + beans::PropertyState_DIRECT_VALUE ); + args[0] <<= aValue; + m_xNameAccessNodes = uno::Reference< container::XNameAccess >( + xConfig->createInstanceWithArguments( OUSTR("com.sun.star.configuration.ConfigurationAccess"), + uno::Sequence< uno::Any >( args, 1 )), uno::UNO_QUERY_THROW); + + // get the 'get more extensions here' url + uno::Reference< container::XNameAccess > xNameAccessRepositories; + beans::PropertyValue aValue2( OUSTR("nodepath"), 0, uno::Any( OUSTR("/org.openoffice.Office.ExtensionManager/ExtensionRepositories") ), + beans::PropertyState_DIRECT_VALUE ); + args[0] <<= aValue2; + xNameAccessRepositories = uno::Reference< container::XNameAccess > ( + xConfig->createInstanceWithArguments( OUSTR("com.sun.star.configuration.ConfigurationAccess"), + uno::Sequence< uno::Any >( args, 1 )), uno::UNO_QUERY_THROW); + try + { //throws css::container::NoSuchElementException, css::lang::WrappedTargetException + uno::Any value = xNameAccessRepositories->getByName( OUSTR( "WebsiteLink" ) ); + m_sGetExtensionsURL = value.get< OUString > (); + } + catch ( uno::Exception& ) + {} + + if ( dp_misc::office_is_running() ) + { + // the registration should be done after the construction has been ended + // otherwise an exception prevents object creation, but it is registered as a listener + m_xDesktop.set( xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.frame.Desktop"), xContext ), uno::UNO_QUERY ); + if ( m_xDesktop.is() ) + m_xDesktop->addTerminateListener( this ); + } +} + +//------------------------------------------------------------------------------ +TheExtensionManager::~TheExtensionManager() +{ + if ( m_pUpdReqDialog ) + delete m_pUpdReqDialog; + if ( m_pExtMgrDialog ) + delete m_pExtMgrDialog; + if ( m_pExecuteCmdQueue ) + delete m_pExecuteCmdQueue; +} + +//------------------------------------------------------------------------------ +void TheExtensionManager::createDialog( const bool bCreateUpdDlg ) +{ + const SolarMutexGuard guard; + + if ( bCreateUpdDlg ) + { + if ( !m_pUpdReqDialog ) + { + m_pUpdReqDialog = new UpdateRequiredDialog( NULL, this ); + delete m_pExecuteCmdQueue; + m_pExecuteCmdQueue = new ExtensionCmdQueue( (DialogHelper*) m_pUpdReqDialog, this, m_xContext ); + createPackageList(); + } + } + else if ( !m_pExtMgrDialog ) + { + m_pExtMgrDialog = new ExtMgrDialog( m_pParent, this ); + delete m_pExecuteCmdQueue; + m_pExecuteCmdQueue = new ExtensionCmdQueue( (DialogHelper*) m_pExtMgrDialog, this, m_xContext ); + m_pExtMgrDialog->setGetExtensionsURL( m_sGetExtensionsURL ); + createPackageList(); + } +} + +//------------------------------------------------------------------------------ +void TheExtensionManager::Show() +{ + const SolarMutexGuard guard; + + getDialog()->Show(); +} + +//------------------------------------------------------------------------------ +void TheExtensionManager::SetText( const ::rtl::OUString &rTitle ) +{ + const SolarMutexGuard guard; + + getDialog()->SetText( rTitle ); +} + +//------------------------------------------------------------------------------ +void TheExtensionManager::ToTop( USHORT nFlags ) +{ + const SolarMutexGuard guard; + + getDialog()->ToTop( nFlags ); +} + +//------------------------------------------------------------------------------ +bool TheExtensionManager::Close() +{ + if ( m_pExtMgrDialog ) + return m_pExtMgrDialog->Close(); + else if ( m_pUpdReqDialog ) + return m_pUpdReqDialog->Close(); + else + return true; +} + +//------------------------------------------------------------------------------ +sal_Int16 TheExtensionManager::execute() +{ + sal_Int16 nRet = 0; + + if ( m_pUpdReqDialog ) + { + nRet = m_pUpdReqDialog->Execute(); + delete m_pUpdReqDialog; + m_pUpdReqDialog = NULL; + } + + return nRet; +} + +//------------------------------------------------------------------------------ +bool TheExtensionManager::isVisible() +{ + return getDialog()->IsVisible(); +} + +//------------------------------------------------------------------------------ +bool TheExtensionManager::checkUpdates( bool /* bShowUpdateOnly */, bool /*bParentVisible*/ ) +{ + std::vector< uno::Reference< deployment::XPackage > > vEntries; + uno::Sequence< uno::Sequence< uno::Reference< deployment::XPackage > > > xAllPackages; + + try { + xAllPackages = m_xExtensionManager->getAllExtensions( uno::Reference< task::XAbortChannel >(), + uno::Reference< ucb::XCommandEnvironment >() ); + } catch ( deployment::DeploymentException & ) { + return false; + } catch ( ucb::CommandFailedException & ) { + return false; + } catch ( ucb::CommandAbortedException & ) { + return false; + } catch ( lang::IllegalArgumentException & e ) { + throw uno::RuntimeException( e.Message, e.Context ); + } + + for ( sal_Int32 i = 0; i < xAllPackages.getLength(); ++i ) + { + uno::Reference< deployment::XPackage > xPackage = dp_misc::getExtensionWithHighestVersion(xAllPackages[i]); + OSL_ASSERT(xPackage.is()); + if ( xPackage.is() ) + { + vEntries.push_back( xPackage ); + } + } + + m_pExecuteCmdQueue->checkForUpdates( vEntries ); + return true; +} + +//------------------------------------------------------------------------------ +bool TheExtensionManager::installPackage( const OUString &rPackageURL, bool bWarnUser ) +{ + if ( rPackageURL.getLength() == 0 ) + return false; + + createDialog( false ); + + bool bInstall = true; + bool bInstallForAll = false; + + // DV! missing function is read only repository from extension manager + if ( !bWarnUser && ! m_xExtensionManager->isReadOnlyRepository( SHARED_PACKAGE_MANAGER ) ) + bInstall = getDialogHelper()->installForAllUsers( bInstallForAll ); + + if ( !bInstall ) + return false; + + if ( bInstallForAll ) + m_pExecuteCmdQueue->addExtension( rPackageURL, SHARED_PACKAGE_MANAGER, false ); + else + m_pExecuteCmdQueue->addExtension( rPackageURL, USER_PACKAGE_MANAGER, bWarnUser ); + + return true; +} + +//------------------------------------------------------------------------------ +bool TheExtensionManager::queryTermination() +{ + if ( dp_misc::office_is_running() ) + return true; + // the standalone application unopkg must not close ( and quit ) the dialog + // when there are still actions in the queue + return true; +} + +//------------------------------------------------------------------------------ +void TheExtensionManager::terminateDialog() +{ + if ( ! dp_misc::office_is_running() ) + { + const SolarMutexGuard guard; + delete m_pExtMgrDialog; + m_pExtMgrDialog = NULL; + delete m_pUpdReqDialog; + m_pUpdReqDialog = NULL; + Application::Quit(); + } +} + +//------------------------------------------------------------------------------ +void TheExtensionManager::createPackageList() +{ + uno::Sequence< uno::Sequence< uno::Reference< deployment::XPackage > > > xAllPackages; + + try { + xAllPackages = m_xExtensionManager->getAllExtensions( uno::Reference< task::XAbortChannel >(), + uno::Reference< ucb::XCommandEnvironment >() ); + } catch ( deployment::DeploymentException & ) { + return; + } catch ( ucb::CommandFailedException & ) { + return; + } catch ( ucb::CommandAbortedException & ) { + return; + } catch ( lang::IllegalArgumentException & e ) { + throw uno::RuntimeException( e.Message, e.Context ); + } + + for ( sal_Int32 i = 0; i < xAllPackages.getLength(); ++i ) + { + uno::Sequence< uno::Reference< deployment::XPackage > > xPackageList = xAllPackages[i]; + + for ( sal_Int32 j = 0; j < xPackageList.getLength(); ++j ) + { + uno::Reference< deployment::XPackage > xPackage = xPackageList[j]; + if ( xPackage.is() ) + { + PackageState eState = getPackageState( xPackage ); + getDialogHelper()->addPackageToList( xPackage ); + // When the package is enabled, we can stop here, otherwise we have to look for + // another version of this package + if ( ( eState == REGISTERED ) || ( eState == NOT_AVAILABLE ) ) + break; + } + } + } + + uno::Sequence< uno::Reference< deployment::XPackage > > xNoLicPackages; + xNoLicPackages = m_xExtensionManager->getExtensionsWithUnacceptedLicenses( SHARED_PACKAGE_MANAGER, + uno::Reference< ucb::XCommandEnvironment >() ); + for ( sal_Int32 i = 0; i < xNoLicPackages.getLength(); ++i ) + { + uno::Reference< deployment::XPackage > xPackage = xNoLicPackages[i]; + if ( xPackage.is() ) + { + getDialogHelper()->addPackageToList( xPackage, true ); + } + } +} + +//------------------------------------------------------------------------------ +PackageState TheExtensionManager::getPackageState( const uno::Reference< deployment::XPackage > &xPackage ) const +{ + 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 ) + return AMBIGUOUS; + else + return reg.Value ? REGISTERED : NOT_REGISTERED; + } + else + return NOT_AVAILABLE; + } + catch ( uno::RuntimeException & ) { + throw; + } + catch ( uno::Exception & exc) { + (void) exc; + OSL_ENSURE( 0, ::rtl::OUStringToOString( exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + return NOT_AVAILABLE; + } +} + +//------------------------------------------------------------------------------ +bool TheExtensionManager::isReadOnly( const uno::Reference< deployment::XPackage > &xPackage ) const +{ + if ( m_xExtensionManager.is() && xPackage.is() ) + { + return m_xExtensionManager->isReadOnlyRepository( xPackage->getRepositoryName() ); + } + else + return true; +} + +//------------------------------------------------------------------------------ +// The function investigates if the extension supports options. +bool TheExtensionManager::supportsOptions( const uno::Reference< deployment::XPackage > &xPackage ) const +{ + bool bOptions = false; + + if ( ! xPackage->isBundle() ) + return false; + + beans::Optional< OUString > aId = xPackage->getIdentifier(); + + //a bundle must always have an id + OSL_ASSERT( aId.IsPresent ); + + //iterate over all available nodes + uno::Sequence< OUString > seqNames = m_xNameAccessNodes->getElementNames(); + + for ( int i = 0; i < seqNames.getLength(); i++ ) + { + uno::Any anyNode = m_xNameAccessNodes->getByName( seqNames[i] ); + //If we have a node then then it must contain the set of leaves. This is part of OptionsDialog.xcs + uno::Reference< XInterface> xIntNode = anyNode.get< uno::Reference< XInterface > >(); + uno::Reference< container::XNameAccess > xNode( xIntNode, uno::UNO_QUERY_THROW ); + + uno::Any anyLeaves = xNode->getByName( OUSTR("Leaves") ); + uno::Reference< XInterface > xIntLeaves = anyLeaves.get< uno::Reference< XInterface > >(); + uno::Reference< container::XNameAccess > xLeaves( xIntLeaves, uno::UNO_QUERY_THROW ); + + //iterate over all available leaves + uno::Sequence< OUString > seqLeafNames = xLeaves->getElementNames(); + for ( int j = 0; j < seqLeafNames.getLength(); j++ ) + { + uno::Any anyLeaf = xLeaves->getByName( seqLeafNames[j] ); + uno::Reference< XInterface > xIntLeaf = anyLeaf.get< uno::Reference< XInterface > >(); + uno::Reference< beans::XPropertySet > xLeaf( xIntLeaf, uno::UNO_QUERY_THROW ); + //investigate the Id property if it matches the extension identifier which + //has been passed in. + uno::Any anyValue = xLeaf->getPropertyValue( OUSTR("Id") ); + + OUString sId = anyValue.get< OUString >(); + if ( sId == aId.Value ) + { + bOptions = true; + break; + } + } + if ( bOptions ) + break; + } + return bOptions; +} + +//------------------------------------------------------------------------------ +// XEventListener +void TheExtensionManager::disposing( lang::EventObject const & rEvt ) + throw ( uno::RuntimeException ) +{ + bool shutDown = (rEvt.Source == m_xDesktop); + + if ( shutDown && m_xDesktop.is() ) + { + m_xDesktop->removeTerminateListener( this ); + m_xDesktop.clear(); + } + + if ( shutDown ) + { + if ( dp_misc::office_is_running() ) + { + const SolarMutexGuard guard; + delete m_pExtMgrDialog; + m_pExtMgrDialog = NULL; + delete m_pUpdReqDialog; + m_pUpdReqDialog = NULL; + } + s_ExtMgr.clear(); + } +} + +//------------------------------------------------------------------------------ +// XTerminateListener +void TheExtensionManager::queryTermination( ::lang::EventObject const & ) + throw ( frame::TerminationVetoException, uno::RuntimeException ) +{ + DialogHelper *pDialogHelper = getDialogHelper(); + + if ( m_pExecuteCmdQueue->isBusy() || ( pDialogHelper && pDialogHelper->isBusy() ) ) + { + ToTop( TOTOP_RESTOREWHENMIN ); + throw frame::TerminationVetoException( + OUSTR("The office cannot be closed while the Extension Manager is running"), + uno::Reference<XInterface>(static_cast<frame::XTerminateListener*>(this), uno::UNO_QUERY)); + } + else + { + if ( m_pExtMgrDialog ) + m_pExtMgrDialog->Close(); + if ( m_pUpdReqDialog ) + m_pUpdReqDialog->Close(); + } +} + +//------------------------------------------------------------------------------ +void TheExtensionManager::notifyTermination( ::lang::EventObject const & rEvt ) + throw ( uno::RuntimeException ) +{ + disposing( rEvt ); +} + +//------------------------------------------------------------------------------ +// XModifyListener +void TheExtensionManager::modified( ::lang::EventObject const & /*rEvt*/ ) + throw ( uno::RuntimeException ) +{ + getDialogHelper()->prepareChecking(); + createPackageList(); + getDialogHelper()->checkEntries(); +} + +//------------------------------------------------------------------------------ +::rtl::Reference< TheExtensionManager > TheExtensionManager::get( const uno::Reference< uno::XComponentContext > &xContext, + const uno::Reference< awt::XWindow > &xParent, + const OUString & extensionURL ) +{ + if ( s_ExtMgr.is() ) + { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + if ( extensionURL.getLength() ) + s_ExtMgr->installPackage( extensionURL, true ); + return s_ExtMgr; + } + + Window * pParent = DIALOG_NO_PARENT; + if ( xParent.is() ) + pParent = VCLUnoHelper::GetWindow(xParent); + + ::rtl::Reference<TheExtensionManager> that( new TheExtensionManager( pParent, xContext ) ); + + const SolarMutexGuard guard; + if ( ! s_ExtMgr.is() ) + { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + s_ExtMgr = that; + } + + if ( extensionURL.getLength() ) + s_ExtMgr->installPackage( extensionURL, true ); + + return s_ExtMgr; +} + +} //namespace dp_gui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_theextmgr.hxx b/desktop/source/deployment/gui/dp_gui_theextmgr.hxx new file mode 100644 index 000000000000..13ba06d0b3d0 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_theextmgr.hxx @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_DP_GUI_THEEXTMGR_HXX +#define INCLUDED_DP_GUI_THEEXTMGR_HXX + +#include "comphelper/sequence.hxx" + +#include "cppuhelper/implbase2.hxx" + +#include "com/sun/star/container/XNameAccess.hpp" +#include "com/sun/star/deployment/XExtensionManager.hpp" +#include "com/sun/star/deployment/ExtensionManager.hpp" +#include "com/sun/star/frame/XDesktop.hpp" +#include "com/sun/star/frame/XTerminateListener.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/util/XModifyListener.hpp" + +#include "dp_gui.h" +#include "dp_gui_dialog2.hxx" +#include "dp_gui_updatedata.hxx" + +//============================================================================== +namespace dp_gui { + +//------------------------------------------------------------------------------ +class ExtensionCmdQueue; + +//------------------------------------------------------------------------------ +class TheExtensionManager : + public ::cppu::WeakImplHelper2< ::com::sun::star::frame::XTerminateListener, + ::com::sun::star::util::XModifyListener > +{ +private: + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_xContext; + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDesktop > m_xDesktop; + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XExtensionManager > m_xExtensionManager; + ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > m_xNameAccessNodes; + + Window *m_pParent; + ExtMgrDialog *m_pExtMgrDialog; + UpdateRequiredDialog *m_pUpdReqDialog; + ExtensionCmdQueue *m_pExecuteCmdQueue; + + ::rtl::OUString m_sGetExtensionsURL; + + void createPackageList(); + +public: + static ::rtl::Reference<TheExtensionManager> s_ExtMgr; + + TheExtensionManager( Window * pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > &xContext ); + ~TheExtensionManager(); + + void createDialog( const bool bCreateUpdDlg ); + sal_Int16 execute(); + + Dialog* getDialog() { return m_pExtMgrDialog ? (Dialog*) m_pExtMgrDialog : (Dialog*) m_pUpdReqDialog; } + DialogHelper* getDialogHelper() { return m_pExtMgrDialog ? (DialogHelper*) m_pExtMgrDialog : (DialogHelper*) m_pUpdReqDialog; } + ExtensionCmdQueue* getCmdQueue() const { return m_pExecuteCmdQueue; } + + void SetText( const ::rtl::OUString &rTitle ); + void Show(); + void ToTop( USHORT nFlags ); + bool Close(); + bool isVisible(); + + //----------------- + bool checkUpdates( bool showUpdateOnly, bool parentVisible ); + bool installPackage( const ::rtl::OUString &rPackageURL, bool bWarnUser = false ); + + bool queryTermination(); + void terminateDialog(); + + // Tools + bool supportsOptions( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ) const; + PackageState getPackageState( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ) const; + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > getContext() const { return m_xContext; } + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XExtensionManager > getExtensionManager() const { return m_xExtensionManager; } + bool isReadOnly( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ) const; + + //----------------- + static ::rtl::Reference<TheExtensionManager> get( + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext> const & xContext, + ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow> const & xParent = 0, + ::rtl::OUString const & view = ::rtl::OUString() ); + + // XEventListener + virtual void SAL_CALL disposing( ::com::sun::star::lang::EventObject const & evt ) + throw (::com::sun::star::uno::RuntimeException); + + // XTerminateListener + virtual void SAL_CALL queryTermination( ::com::sun::star::lang::EventObject const & evt ) + throw (::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL notifyTermination( ::com::sun::star::lang::EventObject const & evt ) + throw (::com::sun::star::uno::RuntimeException); + + // XModifyListener + virtual void SAL_CALL modified( ::com::sun::star::lang::EventObject const & evt ) + throw (::com::sun::star::uno::RuntimeException); +}; + +} // namespace dp_gui + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_thread.cxx b/desktop/source/deployment/gui/dp_gui_thread.cxx new file mode 100644 index 000000000000..3bf0ff0d6c75 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_thread.cxx @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "sal/config.h" + +#include <cstddef> +#include <new> + +#include "osl/thread.hxx" +#include "salhelper/simplereferenceobject.hxx" + +#include "dp_gui_thread.hxx" + +using dp_gui::Thread; + +Thread::Thread() {} + +void Thread::launch() { + // Assumption is that osl::Thread::create returns normally iff it causes + // osl::Thread::run to start executing: + acquire(); + try { + create(); + } catch (...) { + release(); + throw; + } +} + +void * Thread::operator new(std::size_t size) + throw (std::bad_alloc) +{ + return SimpleReferenceObject::operator new(size); +} + +void Thread::operator delete(void * p) throw () { + SimpleReferenceObject::operator delete(p); +} + +Thread::~Thread() {} + +void Thread::run() { + try { + execute(); + } catch (...) { + // Work around the problem that onTerminated is not called if run throws + // an exception: + onTerminated(); + throw; + } +} + +void Thread::onTerminated() { + release(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_thread.hxx b/desktop/source/deployment/gui/dp_gui_thread.hxx new file mode 100644 index 000000000000..eb4fe43c9496 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_thread.hxx @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_DEPLOYMENT_GUI_DP_GUI_THREAD_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_THREAD_HXX + +#include "sal/config.h" + +#include <cstddef> +#include <new> +#include "osl/thread.hxx" +#include "sal/types.h" +#include "salhelper/simplereferenceobject.hxx" + +/// @HTML + +namespace dp_gui { + +/** + A safe encapsulation of <code>osl::Thread</code>. +*/ +class Thread: public salhelper::SimpleReferenceObject, private osl::Thread { +public: + Thread(); + + /** + Launch the thread. + + <p>This function must be called at most once.</p> + */ + void launch(); + + using osl::Thread::join; + + static void * operator new(std::size_t size) throw (std::bad_alloc); + + static void operator delete(void * p) throw (); + +protected: + virtual ~Thread(); + + /** + The main function executed by the thread. + + <p>Any exceptions terminate the thread and are effectively ignored.</p> + */ + virtual void execute() = 0; + +private: + Thread(Thread &); // not defined + void operator =(Thread &); // not defined + + virtual void SAL_CALL run(); + + virtual void SAL_CALL onTerminated(); +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_updatedata.hxx b/desktop/source/deployment/gui/dp_gui_updatedata.hxx new file mode 100644 index 000000000000..314f44935878 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_updatedata.hxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +#if ! defined INCLUDED_DP_GUI_UPDATEDATA_HXX +#define INCLUDED_DP_GUI_UPDATEDATA_HXX + +#include "sal/config.h" +#include "rtl/ustring.hxx" +#include "com/sun/star/uno/Reference.hxx" + +#include <boost/shared_ptr.hpp> + + +namespace com { namespace sun { namespace star { namespace deployment { + class XPackage; +}}}} +namespace com { namespace sun { namespace star { namespace xml { namespace dom { + class XNode; +}}}}} + + +namespace dp_gui { + +struct UpdateData +{ + UpdateData( ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > const & aExt): + bIsShared(false), aInstalledPackage(aExt){}; + + //When entries added to the listbox then there can be one for the user update and one + //for the shared update. However, both list entries will contain the same UpdateData. + //isShared is used to indicate which one is used for the shared entry. + bool bIsShared; + + //The currently installed extension which is going to be updated. If the extension exist in + //multiple repositories then it is the one with the highest version. + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > aInstalledPackage; + + //The version of the update + ::rtl::OUString updateVersion; + + //For online update + // ====================== + // The content of the update information. + //Only if aUpdateInfo is set then there is an online update available with a better version + //than any of the currently installed extensions with the same identifier. + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > aUpdateInfo; + //The URL of the locally downloaded extension. It will only be set if there were no errors + //during the download + ::rtl::OUString sLocalURL; + //The URL of the website wher the download can be obtained. + ::rtl::OUString sWebsiteURL; + + //For local update + //===================== + //The locale extension which is used as update for the user or shared repository. + //If set then the data for the online update (aUpdateInfo, sLocalURL, sWebsiteURL) + //are to be ignored. + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > + aUpdateSource; +}; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_updatedialog.cxx b/desktop/source/deployment/gui/dp_gui_updatedialog.cxx new file mode 100644 index 000000000000..91f1aff66384 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_updatedialog.cxx @@ -0,0 +1,1268 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "sal/config.h" + +#include <cstddef> +#include <limits> +#include <map> +#include <memory> +#include <utility> +#include <vector> + + +#include "boost/optional.hpp" +#include "com/sun/star/awt/Rectangle.hpp" +#include "com/sun/star/awt/WindowAttribute.hpp" +#include "com/sun/star/awt/WindowClass.hpp" +#include "com/sun/star/awt/WindowDescriptor.hpp" +#include "com/sun/star/awt/XThrobber.hpp" +#include "com/sun/star/awt/XToolkit.hpp" +#include "com/sun/star/awt/XWindow.hpp" +#include "com/sun/star/awt/XWindowPeer.hpp" +#include "com/sun/star/beans/NamedValue.hpp" +#include "com/sun/star/beans/Optional.hpp" +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/container/XNameAccess.hpp" +#include "com/sun/star/deployment/DeploymentException.hpp" +#include "com/sun/star/deployment/UpdateInformationProvider.hpp" +#include "com/sun/star/deployment/XPackage.hpp" +#include "com/sun/star/deployment/XExtensionManager.hpp" +#include "com/sun/star/deployment/ExtensionManager.hpp" +#include "com/sun/star/deployment/XUpdateInformationProvider.hpp" +#include "com/sun/star/frame/XDesktop.hpp" +#include "com/sun/star/frame/XDispatch.hpp" +#include "com/sun/star/frame/XDispatchProvider.hpp" +#include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "com/sun/star/lang/XMultiComponentFactory.hpp" +#include "com/sun/star/system/SystemShellExecuteFlags.hpp" +#include "com/sun/star/system/XSystemShellExecute.hpp" +#include "com/sun/star/task/XAbortChannel.hpp" +#include "com/sun/star/task/XJob.hpp" +#include "com/sun/star/ucb/CommandAbortedException.hpp" +#include "com/sun/star/ucb/CommandFailedException.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/util/URL.hpp" +#include "com/sun/star/util/XURLTransformer.hpp" +#include "com/sun/star/xml/dom/XElement.hpp" +#include "com/sun/star/xml/dom/XNode.hpp" +#include "osl/diagnose.h" +#include "rtl/bootstrap.hxx" +#include "rtl/ref.hxx" +#include "rtl/string.h" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "svtools/svlbitm.hxx" +#include "svtools/svlbox.hxx" +#include <svtools/controldims.hrc> +#include "svx/checklbx.hxx" +#include "tools/gen.hxx" +#include "tools/link.hxx" +#include "tools/resid.hxx" +#include "tools/resmgr.hxx" +#include "tools/solar.h" +#include "tools/string.hxx" +#include "vcl/button.hxx" +#include "vcl/dialog.hxx" +#include "vcl/fixed.hxx" +#include "vcl/image.hxx" +#include "vcl/msgbox.hxx" +#include "vcl/svapp.hxx" +#include "osl/mutex.hxx" + +#include "comphelper/processfactory.hxx" + +#include "dp_dependencies.hxx" +#include "dp_descriptioninfoset.hxx" +#include "dp_identifier.hxx" +#include "dp_version.hxx" +#include "dp_misc.h" +#include "dp_update.hxx" + +#include "dp_gui.h" +#include "dp_gui.hrc" +#include "dp_gui_thread.hxx" +#include "dp_gui_updatedata.hxx" +#include "dp_gui_updatedialog.hxx" +#include "dp_gui_shared.hxx" +#include "dp_gui_system.hxx" + +class KeyEvent; +class MouseEvent; +class Window; +namespace com { namespace sun { namespace star { namespace uno { + class XComponentContext; +} } } } + +namespace css = ::com::sun::star; + +using dp_gui::UpdateDialog; + +namespace { + +static sal_Unicode const LF = 0x000A; +static sal_Unicode const CR = 0x000D; + +enum Kind { ENABLED_UPDATE, DISABLED_UPDATE, GENERAL_ERROR, SPECIFIC_ERROR }; + +rtl::OUString confineToParagraph(rtl::OUString const & text) { + // Confine arbitrary text to a single paragraph in a dp_gui::AutoScrollEdit. + // This assumes that U+000A and U+000D are the only paragraph separators in + // a dp_gui::AutoScrollEdit, and that replacing them with a single space + // each is acceptable: + return text.replace(LF, ' ').replace(CR, ' '); +} +} + +struct UpdateDialog::DisabledUpdate { + rtl::OUString name; + css::uno::Sequence< rtl::OUString > unsatisfiedDependencies; + // We also want to show release notes and publisher for disabled updates + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > aUpdateInfo; +}; + +struct UpdateDialog::SpecificError { + rtl::OUString name; + rtl::OUString message; +}; + +union UpdateDialog::IndexUnion{ + std::vector< dp_gui::UpdateData >::size_type enabledUpdate; + std::vector< UpdateDialog::DisabledUpdate >::size_type disabledUpdate; + std::vector< rtl::OUString >::size_type generalError; + std::vector< UpdateDialog::SpecificError >::size_type specificError; +}; + +struct UpdateDialog::Index { + static std::auto_ptr< UpdateDialog::Index const > newEnabledUpdate( + std::vector< dp_gui::UpdateData >::size_type n); + + static std::auto_ptr< UpdateDialog::Index const > newDisabledUpdate( + std::vector< UpdateDialog::DisabledUpdate >::size_type n); + + static std::auto_ptr< UpdateDialog::Index const > newGeneralError( + std::vector< rtl::OUString >::size_type n); + + static std::auto_ptr< UpdateDialog::Index const > newSpecificError( + std::vector< UpdateDialog::SpecificError >::size_type n); + + Kind kind; + IndexUnion index; + +private: + explicit Index(Kind theKind); +}; + +std::auto_ptr< UpdateDialog::Index const > +UpdateDialog::Index::newEnabledUpdate( + std::vector< dp_gui::UpdateData >::size_type n) +{ + UpdateDialog::Index * p = new UpdateDialog::Index(ENABLED_UPDATE); + p->index.enabledUpdate = n; + return std::auto_ptr< UpdateDialog::Index const >(p); +} + +std::auto_ptr< UpdateDialog::Index const > +UpdateDialog::Index::newDisabledUpdate( + std::vector< UpdateDialog::DisabledUpdate >::size_type n) +{ + UpdateDialog::Index * p = new UpdateDialog::Index(DISABLED_UPDATE); + p->index.disabledUpdate = n; + return std::auto_ptr< UpdateDialog::Index const >(p); +} + +std::auto_ptr< UpdateDialog::Index const > UpdateDialog::Index::newGeneralError( + std::vector< rtl::OUString >::size_type n) +{ + UpdateDialog::Index * p = new UpdateDialog::Index(GENERAL_ERROR); + p->index.generalError = n; + return std::auto_ptr< UpdateDialog::Index const >(p); +} + +std::auto_ptr< UpdateDialog::Index const > +UpdateDialog::Index::newSpecificError( + std::vector< UpdateDialog::SpecificError >::size_type n) +{ + UpdateDialog::Index * p = new UpdateDialog::Index(SPECIFIC_ERROR); + p->index.specificError = n; + return std::auto_ptr< UpdateDialog::Index const >(p); +} + +UpdateDialog::Index::Index(Kind theKind): kind(theKind) {} + +class UpdateDialog::Thread: public dp_gui::Thread { +public: + Thread( + css::uno::Reference< css::uno::XComponentContext > const & context, + UpdateDialog & dialog, + const std::vector< css::uno::Reference< css::deployment::XPackage > > & vExtensionList); + + void stop(); + +private: + Thread(UpdateDialog::Thread &); // not defined + void operator =(UpdateDialog::Thread &); // not defined + + struct Entry { + explicit Entry( + css::uno::Reference< css::deployment::XPackage > const & thePackage, + rtl::OUString const & theVersion); + + css::uno::Reference< css::deployment::XPackage > package; + rtl::OUString version; + //Indicates that the extension provides its own update URLs. + //If this is true, then we must not use the default update + //URL to find the update information. + bool bProvidesOwnUpdate; + css::uno::Reference< css::xml::dom::XNode > info; + UpdateDialog::DisabledUpdate disableUpdate; + dp_gui::UpdateData updateData; + }; + + // A multimap in case an extension is installed in "user", "shared" or "bundled" + typedef std::map< rtl::OUString, Entry > Map; + + virtual ~Thread(); + + virtual void execute(); + + void handleSpecificError( + css::uno::Reference< css::deployment::XPackage > const & package, + css::uno::Any const & exception) const; + + css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > + getUpdateInformation( + css::uno::Reference< css::deployment::XPackage > const & package, + css::uno::Sequence< rtl::OUString > const & urls, + rtl::OUString const & identifier) const; + + void getOwnUpdateInformation( + css::uno::Reference< css::deployment::XPackage > const & package, + Map * map); + + ::rtl::OUString getUpdateDisplayString( + dp_gui::UpdateData const & data, ::rtl::OUString const & version = ::rtl::OUString()) const; + + void prepareUpdateData( + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > const & updateInfo, + UpdateDialog::DisabledUpdate & out_du, + dp_gui::UpdateData & out_data) const; + + bool update( + UpdateDialog::DisabledUpdate const & du, + dp_gui::UpdateData const & data) const; + + css::uno::Reference< css::uno::XComponentContext > m_context; + UpdateDialog & m_dialog; + std::vector< css::uno::Reference< css::deployment::XPackage > > m_vExtensionList; + css::uno::Reference< css::deployment::XUpdateInformationProvider > m_updateInformation; + css::uno::Reference< css::task::XInteractionHandler > m_xInteractionHdl; + + // guarded by Application::GetSolarMutex(): + css::uno::Reference< css::task::XAbortChannel > m_abort; + bool m_stop; +}; + +UpdateDialog::Thread::Thread( + css::uno::Reference< css::uno::XComponentContext > const & context, + UpdateDialog & dialog, + const std::vector< css::uno::Reference< css::deployment::XPackage > > &vExtensionList): + m_context(context), + m_dialog(dialog), + m_vExtensionList(vExtensionList), + m_updateInformation( + css::deployment::UpdateInformationProvider::create(context)), + m_stop(false) +{ + if( m_context.is() ) + { + css::uno::Reference< css::lang::XMultiComponentFactory > xServiceManager( m_context->getServiceManager() ); + + if( xServiceManager.is() ) + { + m_xInteractionHdl = css::uno::Reference< css::task::XInteractionHandler > ( + xServiceManager->createInstanceWithContext( OUSTR( "com.sun.star.task.InteractionHandler" ), m_context), + css::uno::UNO_QUERY ); + if ( m_xInteractionHdl.is() ) + m_updateInformation->setInteractionHandler( m_xInteractionHdl ); + } + } +} + +void UpdateDialog::Thread::stop() { + css::uno::Reference< css::task::XAbortChannel > abort; + { + SolarMutexGuard g; + abort = m_abort; + m_stop = true; + } + if (abort.is()) { + abort->sendAbort(); + } + m_updateInformation->cancel(); +} + +UpdateDialog::Thread::Entry::Entry( + css::uno::Reference< css::deployment::XPackage > const & thePackage, + rtl::OUString const & theVersion): + + package(thePackage), + version(theVersion), + bProvidesOwnUpdate(false), + updateData(thePackage) +{ +} + +UpdateDialog::Thread::~Thread() +{ + if ( m_xInteractionHdl.is() ) + m_updateInformation->setInteractionHandler( css::uno::Reference< css::task::XInteractionHandler > () ); +} + +void UpdateDialog::Thread::execute() +{ + { + SolarMutexGuard g; + if ( m_stop ) { + return; + } + } + css::uno::Reference<css::deployment::XExtensionManager> extMgr = + css::deployment::ExtensionManager::get(m_context); + + std::vector<std::pair<css::uno::Reference<css::deployment::XPackage>, css::uno::Any > > errors; + + dp_misc::UpdateInfoMap updateInfoMap = dp_misc::getOnlineUpdateInfos( + m_context, extMgr, m_updateInformation, &m_vExtensionList, errors); + + typedef std::vector<std::pair<css::uno::Reference<css::deployment::XPackage>, + css::uno::Any> >::const_iterator ITERROR; + for (ITERROR ite = errors.begin(); ite != errors.end(); ite ++) + handleSpecificError(ite->first, ite->second); + + for (dp_misc::UpdateInfoMap::iterator i(updateInfoMap.begin()); i != updateInfoMap.end(); i++) + { + dp_misc::UpdateInfo const & info = i->second; + UpdateData updateData(info.extension); + DisabledUpdate disableUpdate; + //determine if online updates meet the requirements + prepareUpdateData(info.info, disableUpdate, updateData); + + //determine if the update is installed in the user or shared repository + rtl::OUString sOnlineVersion; + if (info.info.is()) + sOnlineVersion = info.version; + rtl::OUString sVersionUser; + rtl::OUString sVersionShared; + rtl::OUString sVersionBundled; + css::uno::Sequence< css::uno::Reference< css::deployment::XPackage> > extensions; + try { + extensions = extMgr->getExtensionsWithSameIdentifier( + dp_misc::getIdentifier(info.extension), info.extension->getName(), + css::uno::Reference<css::ucb::XCommandEnvironment>()); + } catch (css::lang::IllegalArgumentException& ) { + OSL_ASSERT(0); + } + OSL_ASSERT(extensions.getLength() == 3); + if (extensions[0].is() ) + sVersionUser = extensions[0]->getVersion(); + if (extensions[1].is() ) + sVersionShared = extensions[1]->getVersion(); + if (extensions[2].is() ) + sVersionBundled = extensions[2]->getVersion(); + + bool bSharedReadOnly = extMgr->isReadOnlyRepository(OUSTR("shared")); + + dp_misc::UPDATE_SOURCE sourceUser = dp_misc::isUpdateUserExtension( + bSharedReadOnly, sVersionUser, sVersionShared, sVersionBundled, sOnlineVersion); + dp_misc::UPDATE_SOURCE sourceShared = dp_misc::isUpdateSharedExtension( + bSharedReadOnly, sVersionShared, sVersionBundled, sOnlineVersion); + + css::uno::Reference<css::deployment::XPackage> updateSource; + if (sourceUser != dp_misc::UPDATE_SOURCE_NONE) + { + if (sourceUser == dp_misc::UPDATE_SOURCE_SHARED) + { + updateData.aUpdateSource = extensions[1]; + updateData.updateVersion = extensions[1]->getVersion(); + } + else if (sourceUser == dp_misc::UPDATE_SOURCE_BUNDLED) + { + updateData.aUpdateSource = extensions[2]; + updateData.updateVersion = extensions[2]->getVersion(); + } + if (!update(disableUpdate, updateData)) + return; + } + + if (sourceShared != dp_misc::UPDATE_SOURCE_NONE) + { + if (sourceShared == dp_misc::UPDATE_SOURCE_BUNDLED) + { + updateData.aUpdateSource = extensions[2]; + updateData.updateVersion = extensions[2]->getVersion(); + } + updateData.bIsShared = true; + if (!update(disableUpdate, updateData)) + return; + } + } + + + SolarMutexGuard g; + if (!m_stop) { + m_dialog.checkingDone(); + } +} + +//Parameter package can be null +void UpdateDialog::Thread::handleSpecificError( + css::uno::Reference< css::deployment::XPackage > const & package, + css::uno::Any const & exception) const +{ + UpdateDialog::SpecificError data; + if (package.is()) + data.name = package->getDisplayName(); + css::uno::Exception e; + if (exception >>= e) { + data.message = e.Message; + } + SolarMutexGuard g; + if (!m_stop) { + m_dialog.addSpecificError(data); + } +} + +::rtl::OUString UpdateDialog::Thread::getUpdateDisplayString( + dp_gui::UpdateData const & data, ::rtl::OUString const & version) const +{ + OSL_ASSERT(data.aInstalledPackage.is()); + rtl::OUStringBuffer b(data.aInstalledPackage->getDisplayName()); + b.append(static_cast< sal_Unicode >(' ')); + { + SolarMutexGuard g; + if(!m_stop) + b.append(m_dialog.m_version); + } + b.append(static_cast< sal_Unicode >(' ')); + if (version.getLength()) + b.append(version); + else + b.append(data.updateVersion); + + if (data.sWebsiteURL.getLength()) + { + b.append(static_cast< sal_Unicode >(' ')); + { + SolarMutexGuard g; + if(!m_stop) + b.append(m_dialog.m_browserbased); + } + } + return b.makeStringAndClear(); +} + +/** out_data will only be filled if all dependencies are ok. + */ +void UpdateDialog::Thread::prepareUpdateData( + css::uno::Reference< css::xml::dom::XNode > const & updateInfo, + UpdateDialog::DisabledUpdate & out_du, + dp_gui::UpdateData & out_data) const +{ + if (!updateInfo.is()) + return; + dp_misc::DescriptionInfoset infoset(m_context, updateInfo); + OSL_ASSERT(infoset.getVersion().getLength() != 0); + css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > ds( + dp_misc::Dependencies::check(infoset)); + + out_du.aUpdateInfo = updateInfo; + out_du.unsatisfiedDependencies.realloc(ds.getLength()); + for (sal_Int32 i = 0; i < ds.getLength(); ++i) { + out_du.unsatisfiedDependencies[i] = dp_misc::Dependencies::getErrorText(ds[i]); + } + + const ::boost::optional< ::rtl::OUString> updateWebsiteURL(infoset.getLocalizedUpdateWebsiteURL()); + + out_du.name = getUpdateDisplayString(out_data, infoset.getVersion()); + + if (out_du.unsatisfiedDependencies.getLength() == 0) + { + out_data.aUpdateInfo = updateInfo; + out_data.updateVersion = infoset.getVersion(); + if (updateWebsiteURL) + out_data.sWebsiteURL = *updateWebsiteURL; + } +} + +bool UpdateDialog::Thread::update( + UpdateDialog::DisabledUpdate const & du, + dp_gui::UpdateData const & data) const +{ + bool ret = false; + if (du.unsatisfiedDependencies.getLength() == 0) + { + SolarMutexGuard g; + if (!m_stop) { + m_dialog.addEnabledUpdate(getUpdateDisplayString(data), data); + } + ret = !m_stop; + } else { + SolarMutexGuard g; + if (!m_stop) { + m_dialog.addDisabledUpdate(du); + } + ret = !m_stop; + } + return ret; +} + +// UpdateDialog ---------------------------------------------------------- +UpdateDialog::UpdateDialog( + css::uno::Reference< css::uno::XComponentContext > const & context, + Window * parent, + const std::vector<css::uno::Reference< css::deployment::XPackage > > &vExtensionList, + std::vector< dp_gui::UpdateData > * updateData): + ModalDialog(parent,DpGuiResId(RID_DLG_UPDATE)), + m_context(context), + m_checking(this, DpGuiResId(RID_DLG_UPDATE_CHECKING)), + m_update(this, DpGuiResId(RID_DLG_UPDATE_UPDATE)), + m_updates( + *this, DpGuiResId(RID_DLG_UPDATE_UPDATES), + Image(DpGuiResId(RID_DLG_UPDATE_NORMALALERT)), + Image(DpGuiResId(RID_DLG_UPDATE_HIGHCONTRASTALERT))), + m_all(this, DpGuiResId(RID_DLG_UPDATE_ALL)), + m_description(this, DpGuiResId(RID_DLG_UPDATE_DESCRIPTION)), + m_PublisherLabel(this, DpGuiResId(RID_DLG_UPDATE_PUBLISHER_LABEL)), + m_PublisherLink(this, DpGuiResId(RID_DLG_UPDATE_PUBLISHER_LINK)), + m_ReleaseNotesLabel(this, DpGuiResId(RID_DLG_UPDATE_RELEASENOTES_LABEL)), + m_ReleaseNotesLink(this, DpGuiResId(RID_DLG_UPDATE_RELEASENOTES_LINK)), + m_descriptions(this, DpGuiResId(RID_DLG_UPDATE_DESCRIPTIONS)), + m_line(this, DpGuiResId(RID_DLG_UPDATE_LINE)), + m_help(this, DpGuiResId(RID_DLG_UPDATE_HELP)), + m_ok(this, DpGuiResId(RID_DLG_UPDATE_OK)), + m_cancel(this, DpGuiResId(RID_DLG_UPDATE_CANCEL)), + m_error(String(DpGuiResId(RID_DLG_UPDATE_ERROR))), + m_none(String(DpGuiResId(RID_DLG_UPDATE_NONE))), + m_noInstallable(String(DpGuiResId(RID_DLG_UPDATE_NOINSTALLABLE))), + m_failure(String(DpGuiResId(RID_DLG_UPDATE_FAILURE))), + m_unknownError(String(DpGuiResId(RID_DLG_UPDATE_UNKNOWNERROR))), + m_noDescription(String(DpGuiResId(RID_DLG_UPDATE_NODESCRIPTION))), + m_noInstall(String(DpGuiResId(RID_DLG_UPDATE_NOINSTALL))), + m_noDependency(String(DpGuiResId(RID_DLG_UPDATE_NODEPENDENCY))), + m_noDependencyCurVer(String(DpGuiResId(RID_DLG_UPDATE_NODEPENDENCY_CUR_VER))), + m_browserbased(String(DpGuiResId(RID_DLG_UPDATE_BROWSERBASED))), + m_version(String(DpGuiResId(RID_DLG_UPDATE_VERSION))), + m_updateData(*updateData), + m_thread( + new UpdateDialog::Thread( + context, *this, vExtensionList)), + m_nFirstLineDelta(0), + m_nOneLineMissing(0) + // TODO: check! +// , +// m_extensionManagerDialog(extensionManagerDialog) +{ + OSL_ASSERT(updateData != NULL); + + m_xExtensionManager = css::deployment::ExtensionManager::get( context ); + + css::uno::Reference< css::awt::XToolkit > toolkit; + try { + toolkit = css::uno::Reference< css::awt::XToolkit >( + (css::uno::Reference< css::lang::XMultiComponentFactory >( + m_context->getServiceManager(), + css::uno::UNO_QUERY_THROW)-> + createInstanceWithContext( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.Toolkit")), + m_context)), + css::uno::UNO_QUERY_THROW); + } catch (css::uno::RuntimeException &) { + throw; + } catch (css::uno::Exception & e) { + throw css::uno::RuntimeException(e.Message, e.Context); + } + Control c(this, DpGuiResId(RID_DLG_UPDATE_THROBBER)); + Point pos(c.GetPosPixel()); + Size size(c.GetSizePixel()); + try { + m_throbber = css::uno::Reference< css::awt::XThrobber >( + toolkit->createWindow( + css::awt::WindowDescriptor( + css::awt::WindowClass_SIMPLE, + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Throbber")), + GetComponentInterface(), 0, + css::awt::Rectangle( + pos.X(), pos.Y(), size.Width(), size.Height()), + css::awt::WindowAttribute::SHOW)), + css::uno::UNO_QUERY_THROW); + } catch (css::lang::IllegalArgumentException & e) { + throw css::uno::RuntimeException(e.Message, e.Context); + } + m_updates.SetSelectHdl(LINK(this, UpdateDialog, selectionHandler)); + m_all.SetToggleHdl(LINK(this, UpdateDialog, allHandler)); + m_ok.SetClickHdl(LINK(this, UpdateDialog, okHandler)); + m_cancel.SetClickHdl(LINK(this, UpdateDialog, cancelHandler)); + if ( ! dp_misc::office_is_running()) + m_help.Disable(); + FreeResource(); + + initDescription(); +} + +UpdateDialog::~UpdateDialog() { + for (USHORT i = 0; i < m_updates.getItemCount(); ++i) { + delete static_cast< UpdateDialog::Index const * >( + m_updates.GetEntryData(i)); + } +} + +BOOL UpdateDialog::Close() { + m_thread->stop(); + return ModalDialog::Close(); +} + +short UpdateDialog::Execute() { + m_throbber->start(); + m_thread->launch(); + return ModalDialog::Execute(); +} + +UpdateDialog::CheckListBox::CheckListBox( + UpdateDialog & dialog, ResId const & resource, + Image const & normalStaticImage, Image const & highContrastStaticImage): + SvxCheckListBox( + &dialog, resource, normalStaticImage, highContrastStaticImage), + m_dialog(dialog) +{} + +UpdateDialog::CheckListBox::~CheckListBox() {} + +USHORT UpdateDialog::CheckListBox::getItemCount() const { + ULONG i = GetEntryCount(); + OSL_ASSERT(i <= std::numeric_limits< USHORT >::max()); + return sal::static_int_cast< USHORT >(i); +} + +void UpdateDialog::CheckListBox::MouseButtonDown(MouseEvent const & event) { + // When clicking on a selected entry in an SvxCheckListBox, the entry's + // checkbox is toggled on mouse button down: + SvxCheckListBox::MouseButtonDown(event); + m_dialog.enableOk(); +} + +void UpdateDialog::CheckListBox::MouseButtonUp(MouseEvent const & event) { + // When clicking on an entry's checkbox in an SvxCheckListBox, the entry's + // checkbox is toggled on mouse button up: + SvxCheckListBox::MouseButtonUp(event); + m_dialog.enableOk(); +} + +void UpdateDialog::CheckListBox::KeyInput(KeyEvent const & event) { + SvxCheckListBox::KeyInput(event); + m_dialog.enableOk(); +} + +void UpdateDialog::insertItem( + rtl::OUString const & name, USHORT position, + std::auto_ptr< UpdateDialog::Index const > index, SvLBoxButtonKind kind) +{ + m_updates.InsertEntry( + name, position, + const_cast< void * >(static_cast< void const * >(index.release())), + kind); + //TODO #i72487#: UpdateDialog::Index potentially leaks as the exception + // behavior of SvxCheckListBox::InsertEntry is unspecified +} + +void UpdateDialog::addAdditional( + rtl::OUString const & name, USHORT position, + std::auto_ptr< UpdateDialog::Index const > index, SvLBoxButtonKind kind) +{ + m_all.Enable(); + if (m_all.IsChecked()) { + insertItem(name, position, index, kind); + m_update.Enable(); + m_updates.Enable(); + m_description.Enable(); + m_descriptions.Enable(); + } +} + +void UpdateDialog::addEnabledUpdate( + rtl::OUString const & name, dp_gui::UpdateData const & data) +{ + std::vector< dp_gui::UpdateData >::size_type n = m_enabledUpdates.size(); + m_enabledUpdates.push_back(data); + insertItem( + name, sal::static_int_cast< USHORT >(n), + UpdateDialog::Index::newEnabledUpdate(n), + SvLBoxButtonKind_enabledCheckbox); + // position overflow is rather harmless + m_updates.CheckEntryPos(sal::static_int_cast< USHORT >(n)); + //TODO #i72487#: fragile computation; insertItem should instead return + // pos + m_update.Enable(); + m_updates.Enable(); + m_description.Enable(); + m_descriptions.Enable(); +} + +void UpdateDialog::addDisabledUpdate(UpdateDialog::DisabledUpdate const & data) +{ + std::vector< UpdateDialog::DisabledUpdate >::size_type n = + m_disabledUpdates.size(); + m_disabledUpdates.push_back(data); + addAdditional( + data.name, sal::static_int_cast< USHORT >(m_enabledUpdates.size() + n), + UpdateDialog::Index::newDisabledUpdate(n), + SvLBoxButtonKind_disabledCheckbox); + // position overflow is rather harmless +} + +void UpdateDialog::addSpecificError(UpdateDialog::SpecificError const & data) { + std::vector< UpdateDialog::SpecificError >::size_type n = + m_specificErrors.size(); + m_specificErrors.push_back(data); + addAdditional( + data.name, LISTBOX_APPEND, UpdateDialog::Index::newSpecificError(n), + SvLBoxButtonKind_staticImage); +} + +void UpdateDialog::checkingDone() { + m_checking.Hide(); + m_throbber->stop(); + css::uno::Reference< css::awt::XWindow >( + m_throbber, css::uno::UNO_QUERY_THROW)->setVisible(false); + if (m_updates.getItemCount() == 0) + { + clearDescription(); + m_description.Enable(); + m_descriptions.Enable(); + showDescription( + ( m_disabledUpdates.empty() && m_generalErrors.empty() && m_specificErrors.empty() ) + ? m_none : m_noInstallable, false ); + } + enableOk(); +} + +void UpdateDialog::enableOk() { + if (!m_checking.IsVisible()) { + m_ok.Enable(m_updates.GetCheckedEntryCount() != 0); + } +} + +// ********************************************************************************* +void UpdateDialog::createNotifyJob( bool bPrepareOnly, + css::uno::Sequence< css::uno::Sequence< rtl::OUString > > &rItemList ) +{ + if ( !dp_misc::office_is_running() ) + return; + + // notify update check job + try + { + css::uno::Reference< css::lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); + css::uno::Reference< css::lang::XMultiServiceFactory > xConfigProvider( + xFactory->createInstance( OUSTR( "com.sun.star.configuration.ConfigurationProvider" )), + css::uno::UNO_QUERY_THROW); + + css::beans::PropertyValue aProperty; + aProperty.Name = OUSTR( "nodepath" ); + aProperty.Value = css::uno::makeAny( OUSTR("org.openoffice.Office.Addons/AddonUI/OfficeHelp/UpdateCheckJob") ); + + css::uno::Sequence< css::uno::Any > aArgumentList( 1 ); + aArgumentList[0] = css::uno::makeAny( aProperty ); + + css::uno::Reference< css::container::XNameAccess > xNameAccess( + xConfigProvider->createInstanceWithArguments( + OUSTR("com.sun.star.configuration.ConfigurationAccess"), aArgumentList ), + css::uno::UNO_QUERY_THROW ); + + css::util::URL aURL; + xNameAccess->getByName(OUSTR("URL")) >>= aURL.Complete; + + css::uno::Reference < css::util::XURLTransformer > xTransformer( xFactory->createInstance( OUSTR( "com.sun.star.util.URLTransformer" ) ), + css::uno::UNO_QUERY_THROW ); + + xTransformer->parseStrict(aURL); + + css::uno::Reference < css::frame::XDesktop > xDesktop( xFactory->createInstance( OUSTR( "com.sun.star.frame.Desktop" ) ), + css::uno::UNO_QUERY_THROW ); + css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider( xDesktop->getCurrentFrame(), + css::uno::UNO_QUERY_THROW ); + css::uno::Reference< css::frame::XDispatch > xDispatch = xDispatchProvider->queryDispatch(aURL, rtl::OUString(), 0); + + if( xDispatch.is() ) + { + css::uno::Sequence< css::beans::PropertyValue > aPropList(2); + aProperty.Name = OUSTR( "updateList" ); + aProperty.Value = css::uno::makeAny( rItemList ); + aPropList[0] = aProperty; + aProperty.Name = OUSTR( "prepareOnly" ); + aProperty.Value = css::uno::makeAny( bPrepareOnly ); + aPropList[1] = aProperty; + + xDispatch->dispatch(aURL, aPropList ); + } + } + catch( const css::uno::Exception& e ) + { + dp_misc::TRACE( OUSTR("Caught exception: ") + + e.Message + OUSTR("\n thread terminated.\n\n")); + } +} + +// ********************************************************************************* +void UpdateDialog::notifyMenubar( bool bPrepareOnly, bool bRecheckOnly ) +{ + if ( !dp_misc::office_is_running() ) + return; + + css::uno::Sequence< css::uno::Sequence< rtl::OUString > > aItemList; + sal_Int32 nCount = 0; + + if ( ! bRecheckOnly ) + { + for ( sal_Int16 i = 0; i < m_updates.getItemCount(); ++i ) + { + css::uno::Sequence< rtl::OUString > aItem(2); + + UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >(m_updates.GetEntryData(i)); + + if ( p->kind == ENABLED_UPDATE ) + { + dp_gui::UpdateData aUpdData = m_enabledUpdates[ p->index.enabledUpdate ]; + aItem[0] = dp_misc::getIdentifier( aUpdData.aInstalledPackage ); + + dp_misc::DescriptionInfoset aInfoset( m_context, aUpdData.aUpdateInfo ); + aItem[1] = aInfoset.getVersion(); + } + else if ( p->kind == DISABLED_UPDATE ) + continue; + else + continue; + + aItemList.realloc( nCount + 1 ); + aItemList[ nCount ] = aItem; + nCount += 1; + } + } + createNotifyJob( bPrepareOnly, aItemList ); +} + +// ********************************************************************************* + +void UpdateDialog::initDescription() +{ + m_PublisherLabel.Hide(); + m_PublisherLink.Hide(); + m_ReleaseNotesLabel.Hide(); + m_ReleaseNotesLink.Hide(); + m_descriptions.Hide(); + + Link aLink = LINK( this, UpdateDialog, hyperlink_clicked ); + m_PublisherLink.SetClickHdl( aLink ); + m_ReleaseNotesLink.SetClickHdl( aLink ); + + long nTextWidth = m_PublisherLabel.GetCtrlTextWidth( m_PublisherLabel.GetText() ); + long nTemp = m_ReleaseNotesLabel.GetTextWidth( m_ReleaseNotesLabel.GetText() ); + if ( nTemp > nTextWidth ) + nTextWidth = nTemp; + nTextWidth = nTextWidth * 110 / 100; + + Size aNewSize = m_PublisherLabel.GetSizePixel(); + if ( nTextWidth > aNewSize.Width() ) + { + long nDelta = nTextWidth - aNewSize.Width(); + aNewSize.Width() = nTextWidth; + m_PublisherLabel.SetSizePixel( aNewSize ); + m_ReleaseNotesLabel.SetSizePixel( aNewSize ); + + aNewSize = m_PublisherLink.GetSizePixel(); + aNewSize.Width() = aNewSize.Width() - nDelta; + Point aNewPos = m_PublisherLink.GetPosPixel(); + aNewPos.X() = aNewPos.X() + nDelta; + m_PublisherLink.SetPosSizePixel( aNewPos, aNewSize ); + aNewPos.Y() = m_ReleaseNotesLink.GetPosPixel().Y(); + m_ReleaseNotesLink.SetPosSizePixel( aNewPos, aNewSize ); + } + + m_aFirstLinePos = m_descriptions.GetPosPixel(); + m_aFirstLineSize = m_descriptions.GetSizePixel(); + Size aMarginSize = LogicToPixel( Size( RSC_SP_CTRL_GROUP_X, RSC_SP_CTRL_GROUP_Y ), MAP_APPFONT ); + Point aThirdLinePos = m_ReleaseNotesLabel.GetPosPixel(); + aThirdLinePos.Y() = aThirdLinePos.Y() + m_ReleaseNotesLabel.GetSizePixel().Height() + aMarginSize.Height(); + m_nFirstLineDelta = aThirdLinePos.Y() - m_aFirstLinePos.Y(); + m_nOneLineMissing = m_ReleaseNotesLabel.GetPosPixel().Y() - m_PublisherLabel.GetPosPixel().Y(); +} + +void UpdateDialog::clearDescription() +{ + String sEmpty; + m_PublisherLabel.Hide(); + m_PublisherLink.Hide(); + m_PublisherLink.SetDescription( sEmpty ); + m_PublisherLink.SetURL( sEmpty ); + m_ReleaseNotesLabel.Hide(); + m_ReleaseNotesLink.Hide(); + m_ReleaseNotesLink.SetURL( sEmpty ); + if ( m_PublisherLabel.GetPosPixel().Y() == m_ReleaseNotesLabel.GetPosPixel().Y() ) + { + Point aNewPos = m_ReleaseNotesLabel.GetPosPixel(); + aNewPos.Y() += m_nOneLineMissing; + m_ReleaseNotesLabel.SetPosPixel( aNewPos ); + aNewPos = m_ReleaseNotesLink.GetPosPixel(); + aNewPos.Y() += m_nOneLineMissing; + m_ReleaseNotesLink.SetPosPixel( aNewPos ); + } + m_descriptions.Hide(); + m_descriptions.Clear(); + m_descriptions.SetPosSizePixel( m_aFirstLinePos, m_aFirstLineSize ); +} + +bool UpdateDialog::showDescription(css::uno::Reference< css::xml::dom::XNode > const & aUpdateInfo) +{ + dp_misc::DescriptionInfoset infoset(m_context, aUpdateInfo); + return showDescription(infoset.getLocalizedPublisherNameAndURL(), + infoset.getLocalizedReleaseNotesURL()); +} + +bool UpdateDialog::showDescription(css::uno::Reference< css::deployment::XPackage > const & aExtension) +{ + OSL_ASSERT(aExtension.is()); + css::beans::StringPair pubInfo = aExtension->getPublisherInfo(); + return showDescription(std::make_pair(pubInfo.First, pubInfo.Second), + OUSTR("")); +} + +bool UpdateDialog::showDescription(std::pair< rtl::OUString, rtl::OUString > const & pairPublisher, + rtl::OUString const & sReleaseNotes) +{ + rtl::OUString sPub = pairPublisher.first; + rtl::OUString sURL = pairPublisher.second; + + if ( sPub.getLength() == 0 && sURL.getLength() == 0 && sReleaseNotes.getLength() == 0 ) + // nothing to show + return false; + + bool bPublisher = false; + if ( sPub.getLength() > 0 ) + { + m_PublisherLabel.Show(); + m_PublisherLink.Show(); + m_PublisherLink.SetDescription( sPub ); + m_PublisherLink.SetURL( sURL ); + bPublisher = true; + } + + if ( sReleaseNotes.getLength() > 0 ) + { + if ( !bPublisher ) + { + m_ReleaseNotesLabel.SetPosPixel( m_PublisherLabel.GetPosPixel() ); + m_ReleaseNotesLink.SetPosPixel( m_PublisherLink.GetPosPixel() ); + } + m_ReleaseNotesLabel.Show(); + m_ReleaseNotesLink.Show(); + m_ReleaseNotesLink.SetURL( sReleaseNotes ); + } + return true; +} + +bool UpdateDialog::showDescription( const String& rDescription, bool bWithPublisher ) +{ + if ( rDescription.Len() == 0 ) + // nothing to show + return false; + + if ( bWithPublisher ) + { + bool bOneLineMissing = !m_ReleaseNotesLabel.IsVisible() || !m_PublisherLabel.IsVisible(); + Point aNewPos = m_aFirstLinePos; + aNewPos.Y() += m_nFirstLineDelta; + if ( bOneLineMissing ) + aNewPos.Y() -= m_nOneLineMissing; + Size aNewSize = m_aFirstLineSize; + aNewSize.Height() -= m_nFirstLineDelta; + if ( bOneLineMissing ) + aNewSize.Height() += m_nOneLineMissing; + m_descriptions.SetPosSizePixel( aNewPos, aNewSize ); + } + m_descriptions.Show(); + m_descriptions.SetDescription( rDescription ); + return true; +} + +bool UpdateDialog::isReadOnly( const css::uno::Reference< css::deployment::XPackage > &xPackage ) const +{ + if ( m_xExtensionManager.is() && xPackage.is() ) + { + return m_xExtensionManager->isReadOnlyRepository( xPackage->getRepositoryName() ); + } + else + return true; +} + +IMPL_LINK(UpdateDialog, selectionHandler, void *, EMPTYARG) +{ + rtl::OUStringBuffer b; + bool bInserted = false; + UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >( + m_updates.GetEntryData(m_updates.GetSelectEntryPos())); + clearDescription(); + + if (p != NULL) + { + //When the index is greater or equal than the amount of enabled updates then the "Show all" + //button is probably checked. Then we show first all enabled and then the disabled + //updates. + USHORT pos = m_updates.GetSelectEntryPos(); + const std::vector< dp_gui::UpdateData >::size_type sizeEnabled = + m_enabledUpdates.size(); + const std::vector< UpdateDialog::DisabledUpdate >::size_type sizeDisabled = + m_disabledUpdates.size(); + if (pos < sizeEnabled) + { + if (m_enabledUpdates[pos].aUpdateSource.is()) + bInserted = showDescription(m_enabledUpdates[pos].aUpdateSource); + else + bInserted = showDescription(m_enabledUpdates[pos].aUpdateInfo); + } + else if (pos >= sizeEnabled + && pos < (sizeEnabled + sizeDisabled)) + bInserted = showDescription(m_disabledUpdates[pos - sizeEnabled].aUpdateInfo); + + switch (p->kind) + { + case ENABLED_UPDATE: + { + b.append(m_noDescription); + break; + } + case DISABLED_UPDATE: + { + UpdateDialog::DisabledUpdate & data = m_disabledUpdates[ + p->index.disabledUpdate]; + if (data.unsatisfiedDependencies.getLength() != 0) + { + // create error string for version mismatch + ::rtl::OUString sVersion( RTL_CONSTASCII_USTRINGPARAM("%VERSION") ); + sal_Int32 nPos = m_noDependencyCurVer.indexOf( sVersion ); + if ( nPos >= 0 ) + { + ::rtl::OUString sCurVersion( RTL_CONSTASCII_USTRINGPARAM( "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":Version:OOOPackageVersion}")); + ::rtl::Bootstrap::expandMacros(sCurVersion); + m_noDependencyCurVer = m_noDependencyCurVer.replaceAt( nPos, sVersion.getLength(), sCurVersion ); + } + + b.append(m_noInstall); + b.append(LF); + b.append(m_noDependency); + for (sal_Int32 i = 0; + i < data.unsatisfiedDependencies.getLength(); ++i) + { + b.append(LF); + b.appendAscii(RTL_CONSTASCII_STRINGPARAM(" ")); + // U+2003 EM SPACE would be better than two spaces, + // but some fonts do not contain it + b.append( + confineToParagraph( + data.unsatisfiedDependencies[i])); + } + b.append(LF); + b.appendAscii(RTL_CONSTASCII_STRINGPARAM(" ")); + b.append(m_noDependencyCurVer); + } + break; + } + case GENERAL_ERROR: + { + rtl::OUString & msg = m_generalErrors[p->index.generalError]; + b.append(m_failure); + b.append(LF); + b.append(msg.getLength() == 0 ? m_unknownError : msg); + break; + } + case SPECIFIC_ERROR: + { + UpdateDialog::SpecificError & data = m_specificErrors[ + p->index.specificError]; + b.append(m_failure); + b.append(LF); + b.append( + data.message.getLength() == 0 + ? m_unknownError : data.message); + break; + } + default: + OSL_ASSERT(false); + break; + } + } + + showDescription( b.makeStringAndClear(), bInserted ); + return 0; +} + +IMPL_LINK(UpdateDialog, allHandler, void *, EMPTYARG) { + if (m_all.IsChecked()) { + m_update.Enable(); + m_updates.Enable(); + m_description.Enable(); + m_descriptions.Enable(); + std::vector< UpdateDialog::DisabledUpdate >::size_type n1 = 0; + for (std::vector< UpdateDialog::DisabledUpdate >::iterator i( + m_disabledUpdates.begin()); + i != m_disabledUpdates.end(); ++i) + { + insertItem( + i->name, LISTBOX_APPEND, + UpdateDialog::Index::newDisabledUpdate(n1++), + SvLBoxButtonKind_disabledCheckbox); + } + std::vector< rtl::OUString >::size_type n2 = 0; + for (std::vector< rtl::OUString >::iterator i(m_generalErrors.begin()); + i != m_generalErrors.end(); ++i) + { + insertItem( + m_error, LISTBOX_APPEND, + UpdateDialog::Index::newGeneralError(n2++), + SvLBoxButtonKind_staticImage); + } + std::vector< UpdateDialog::SpecificError >::size_type n3 = 0; + for (std::vector< UpdateDialog::SpecificError >::iterator i( + m_specificErrors.begin()); + i != m_specificErrors.end(); ++i) + { + insertItem( + i->name, LISTBOX_APPEND, + UpdateDialog::Index::newSpecificError(n3++), + SvLBoxButtonKind_staticImage); + } + } else { + for (USHORT i = 0; i < m_updates.getItemCount();) { + UpdateDialog::Index const * p = + static_cast< UpdateDialog::Index const * >( + m_updates.GetEntryData(i)); + if (p->kind != ENABLED_UPDATE) { + m_updates.RemoveEntry(i); + //TODO #i72487#: UpdateDialog::Index potentially leaks as + // SvxCheckListBox::RemoveEntry's exception behavior is + // unspecified + delete p; + } else { + ++i; + } + } + + if (m_updates.getItemCount() == 0) + { + clearDescription(); + m_update.Disable(); + m_updates.Disable(); + if (m_checking.IsVisible()) + m_description.Disable(); + else + showDescription(m_noInstallable,false); + } + } + return 0; +} + +IMPL_LINK(UpdateDialog, okHandler, void *, EMPTYARG) +{ + //If users are going to update a shared extension then we need + //to warn them + typedef ::std::vector<UpdateData>::const_iterator CIT; + for (CIT i = m_enabledUpdates.begin(); i < m_enabledUpdates.end(); i++) + { + OSL_ASSERT(i->aInstalledPackage.is()); + //If the user has no write access to the shared folder then the update + //for a shared extension is disable, that is it cannot be in m_enabledUpdates +// OSL_ASSERT(isReadOnly(i->aInstalledPackage) == sal_False); + } + + + for (USHORT i = 0; i < m_updates.getItemCount(); ++i) { + UpdateDialog::Index const * p = + static_cast< UpdateDialog::Index const * >( + m_updates.GetEntryData(i)); + if (p->kind == ENABLED_UPDATE && m_updates.IsChecked(i)) { + m_updateData.push_back(m_enabledUpdates[p->index.enabledUpdate]); + } + } + + EndDialog(RET_OK); + return 0; +} + +IMPL_LINK(UpdateDialog, cancelHandler, void *, EMPTYARG) { + m_thread->stop(); + EndDialog(RET_CANCEL); + return 0; +} + +IMPL_LINK( UpdateDialog, hyperlink_clicked, svt::FixedHyperlink*, pHyperlink ) +{ + ::rtl::OUString sURL; + if ( pHyperlink ) + sURL = ::rtl::OUString( pHyperlink->GetURL() ); + if ( sURL.getLength() == 0 ) + return 0; + + try + { + css::uno::Reference< css::system::XSystemShellExecute > xSystemShellExecute( + m_context->getServiceManager()->createInstanceWithContext( + OUSTR( "com.sun.star.system.SystemShellExecute" ), + m_context), css::uno::UNO_QUERY_THROW); + //throws css::lang::IllegalArgumentException, css::system::SystemShellExecuteException + xSystemShellExecute->execute( + sURL, ::rtl::OUString(), css::system::SystemShellExecuteFlags::DEFAULTS); + } + catch (css::uno::Exception& ) + { + } + + return 1; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_updatedialog.hxx b/desktop/source/deployment/gui/dp_gui_updatedialog.hxx new file mode 100644 index 000000000000..a9a8bcf71615 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_updatedialog.hxx @@ -0,0 +1,231 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_DEPLOYMENT_GUI_DP_GUI_UPDATEDIALOG_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_UPDATEDIALOG_HXX + +#include "sal/config.h" + +#include <memory> +#include <vector> +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "rtl/ref.hxx" +#include "rtl/ustring.hxx" +#include "svtools/svlbitm.hxx" +#include "svx/checklbx.hxx" +#include "tools/link.hxx" +#include "tools/solar.h" +#include "vcl/button.hxx" +#include "vcl/dialog.hxx" +#include "vcl/fixed.hxx" +#include <svtools/fixedhyper.hxx> + +#include "descedit.hxx" +#include "dp_gui_updatedata.hxx" + +/// @HTML + +class Image; +class KeyEvent; +class MouseEvent; +class ResId; +class Window; + +namespace com { namespace sun { namespace star { + namespace awt { class XThrobber; } + namespace deployment { class XExtensionManager; + class XPackage; } + namespace uno { class XComponentContext; } +} } } + +namespace dp_gui { +/** + The modal “Check for Updates” dialog. +*/ +class UpdateDialog: public ModalDialog { +public: + /** + Create an instance. + + <p>Exactly one of <code>selectedPackages</code> and + <code>packageManagers</code> must be non-null.</p> + + @param context + a non-null component context + + @param parent + the parent window, may be null + + @param vExtensionList + check for updates for the contained extensions. There must only be one extension with + a particular identifier. If one extension is installed in several repositories, then the + one with the highest version must be used, because it contains the latest known update + information. + */ + UpdateDialog( + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > const & context, + Window * parent, + const std::vector< com::sun::star::uno::Reference< + com::sun::star::deployment::XPackage > > & vExtensionList, + std::vector< dp_gui::UpdateData > * updateData); + + ~UpdateDialog(); + + virtual BOOL Close(); + + virtual short Execute(); + + void notifyMenubar( bool bPrepareOnly, bool bRecheckOnly ); + static void createNotifyJob( bool bPrepareOnly, + com::sun::star::uno::Sequence< com::sun::star::uno::Sequence< rtl::OUString > > &rItemList ); + +private: + UpdateDialog(UpdateDialog &); // not defined + void operator =(UpdateDialog &); // not defined + + struct DisabledUpdate; + struct SpecificError; + union IndexUnion; + friend union IndexUnion; + struct Index; + friend struct Index; + class Thread; + friend class Thread; + + class CheckListBox: public SvxCheckListBox { + public: + CheckListBox( + UpdateDialog & dialog, ResId const & resource, + Image const & normalStaticImage, + Image const & highContrastStaticImage); + + virtual ~CheckListBox(); + + USHORT getItemCount() const; + + private: + CheckListBox(UpdateDialog::CheckListBox &); // not defined + void operator =(UpdateDialog::CheckListBox &); // not defined + + virtual void MouseButtonDown(MouseEvent const & event); + + virtual void MouseButtonUp(MouseEvent const & event); + + virtual void KeyInput(KeyEvent const & event); + + UpdateDialog & m_dialog; + }; + + + friend class CheckListBox; + + void insertItem( + rtl::OUString const & name, USHORT position, + std::auto_ptr< UpdateDialog::Index const > index, + SvLBoxButtonKind kind); + + void addAdditional( + rtl::OUString const & name, USHORT position, + std::auto_ptr< UpdateDialog::Index const > index, + SvLBoxButtonKind kind); + + void addEnabledUpdate( + rtl::OUString const & name, dp_gui::UpdateData const & data); + + void addDisabledUpdate(UpdateDialog::DisabledUpdate const & data); + void addSpecificError(UpdateDialog::SpecificError const & data); + + void checkingDone(); + + void enableOk(); + + void initDescription(); + void clearDescription(); + bool showDescription(::com::sun::star::uno::Reference< + ::com::sun::star::deployment::XPackage > const & aExtension); + bool showDescription(std::pair< rtl::OUString, rtl::OUString > const & pairPublisher, + rtl::OUString const & sReleaseNotes); + bool showDescription( ::com::sun::star::uno::Reference< + ::com::sun::star::xml::dom::XNode > const & aUpdateInfo); + bool showDescription( const String& rDescription, bool bWithPublisher ); + bool isReadOnly( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ) const; + + DECL_LINK(selectionHandler, void *); + DECL_LINK(allHandler, void *); + DECL_LINK(okHandler, void *); + DECL_LINK(cancelHandler, void *); + DECL_LINK(hyperlink_clicked, svt::FixedHyperlink *); + + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + m_context; + FixedText m_checking; + com::sun::star::uno::Reference< com::sun::star::awt::XThrobber > m_throbber; + FixedText m_update; + UpdateDialog::CheckListBox m_updates; + CheckBox m_all; + FixedLine m_description; + FixedText m_PublisherLabel; + svt::FixedHyperlink m_PublisherLink; + FixedText m_ReleaseNotesLabel; + svt::FixedHyperlink m_ReleaseNotesLink; + dp_gui::DescriptionEdit m_descriptions; + FixedLine m_line; + HelpButton m_help; + PushButton m_ok; + CancelButton m_cancel; + rtl::OUString m_error; + rtl::OUString m_none; + rtl::OUString m_noInstallable; + rtl::OUString m_failure; + rtl::OUString m_unknownError; + rtl::OUString m_noDescription; + rtl::OUString m_noInstall; + rtl::OUString m_noDependency; + rtl::OUString m_noDependencyCurVer; + rtl::OUString m_browserbased; + rtl::OUString m_version; + std::vector< dp_gui::UpdateData > m_enabledUpdates; + std::vector< UpdateDialog::DisabledUpdate > m_disabledUpdates; + std::vector< rtl::OUString > m_generalErrors; + std::vector< UpdateDialog::SpecificError > m_specificErrors; + std::vector< dp_gui::UpdateData > & m_updateData; + rtl::Reference< UpdateDialog::Thread > m_thread; + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XExtensionManager > m_xExtensionManager; + + Point m_aFirstLinePos; + Size m_aFirstLineSize; + long m_nFirstLineDelta; + long m_nOneLineMissing; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_updatedialog.src b/desktop/source/deployment/gui/dp_gui_updatedialog.src new file mode 100644 index 000000000000..59539d55c1fc --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_updatedialog.src @@ -0,0 +1,265 @@ +/************************************************************************* + * + * 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 "svtools/controldims.hrc" + +#include "dp_gui.hrc" + +#define LOCAL_WIDTH (60 * RSC_BS_CHARWIDTH) +#define LABEL_WIDTH (1 * RSC_BS_CHARWIDTH) +#define LOCAL_LIST_HEIGHT1 (6 * RSC_BS_CHARHEIGHT) + 4 +#define LOCAL_LIST_HEIGHT2 (7 * RSC_BS_CHARHEIGHT) + 3 + +ModalDialog RID_DLG_UPDATE { + HelpID = HID_DEPLOYMENT_GUI_UPDATE; + Size = MAP_APPFONT( + (RSC_SP_DLG_INNERBORDER_LEFT + LOCAL_WIDTH + + RSC_SP_DLG_INNERBORDER_RIGHT), + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT2 + RSC_SP_FLGR_SPACE_Y + + RSC_CD_FIXEDLINE_HEIGHT + RSC_SP_FLGR_SPACE_Y + + RSC_CD_PUSHBUTTON_HEIGHT + RSC_SP_DLG_INNERBORDER_BOTTOM)); + Text[en-US] = "Extension Update"; + Moveable = TRUE; + Closeable = TRUE; + FixedText RID_DLG_UPDATE_CHECKING { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT + LOCAL_WIDTH * 2 / 3, + RSC_SP_DLG_INNERBORDER_TOP); + Size = MAP_APPFONT( + (LOCAL_WIDTH - LOCAL_WIDTH * 2 / 3 - RSC_SP_CTRL_DESC_X - + RSC_CD_FIXEDTEXT_HEIGHT), + RSC_CD_FIXEDTEXT_HEIGHT); + Text[en-US] = "Checking..."; + Right = TRUE; + NoLabel = TRUE; + }; + Control RID_DLG_UPDATE_THROBBER { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT + LOCAL_WIDTH - RSC_CD_FIXEDTEXT_HEIGHT, + RSC_SP_DLG_INNERBORDER_TOP); + Size = MAP_APPFONT(RSC_CD_FIXEDTEXT_HEIGHT, RSC_CD_FIXEDTEXT_HEIGHT); + }; + FixedText RID_DLG_UPDATE_UPDATE { + Disable = TRUE; + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, RSC_SP_DLG_INNERBORDER_TOP); + Size = MAP_APPFONT( + LOCAL_WIDTH * 2 / 3 - RSC_SP_CTRL_GROUP_X, RSC_CD_FIXEDTEXT_HEIGHT); + Text[en-US] = "~Available extension updates"; + }; + Control RID_DLG_UPDATE_UPDATES { + HelpId = HID_DEPLOYMENT_GUI_UPDATE_AVAILABLE_UPDATES; + Disable = TRUE; + Border = TRUE; + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y)); + Size = MAP_APPFONT(LOCAL_WIDTH, LOCAL_LIST_HEIGHT1); + TabStop = TRUE; + }; + CheckBox RID_DLG_UPDATE_ALL { + Disable = TRUE; + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y)); + Size = MAP_APPFONT(LOCAL_WIDTH, RSC_CD_CHECKBOX_HEIGHT); + Text[en-US] = "~Show all updates"; + }; + FixedLine RID_DLG_UPDATE_DESCRIPTION { + Disable = TRUE; + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y)); + Size = MAP_APPFONT(LOCAL_WIDTH, RSC_CD_FIXEDTEXT_HEIGHT); + Text[en-US] = "Description"; + }; + FixedText RID_DLG_UPDATE_PUBLISHER_LABEL + { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y)); + Size = MAP_APPFONT(LABEL_WIDTH, RSC_CD_FIXEDTEXT_HEIGHT); + Text[en-US] = "Publisher:"; + }; + FixedText RID_DLG_UPDATE_PUBLISHER_LINK + { + HelpId = HID_DEPLOYMENT_GUI_UPDATE_PUBLISHER; + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT + LABEL_WIDTH + RSC_SP_CTRL_DESC_X, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y)); + Size = MAP_APPFONT(LOCAL_WIDTH - LABEL_WIDTH - RSC_SP_CTRL_DESC_X, RSC_CD_FIXEDTEXT_HEIGHT); + }; + FixedText RID_DLG_UPDATE_RELEASENOTES_LABEL + { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_FIXEDTEXT_HEIGHT + RSC_SP_CTRL_DESC_Y)); + Size = MAP_APPFONT(LABEL_WIDTH, RSC_CD_FIXEDTEXT_HEIGHT); + Text[en-US] = "What is new:"; + }; + FixedText RID_DLG_UPDATE_RELEASENOTES_LINK + { + HelpId = HID_DEPLOYMENT_GUI_UPDATE_RELEASENOTES; + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT + LABEL_WIDTH + RSC_SP_CTRL_DESC_X, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_FIXEDTEXT_HEIGHT + RSC_SP_CTRL_DESC_Y)); + Size = MAP_APPFONT(LOCAL_WIDTH - LABEL_WIDTH - RSC_SP_CTRL_DESC_X, RSC_CD_FIXEDTEXT_HEIGHT); + Text[en-US] = "Release Notes"; + }; + MultiLineEdit RID_DLG_UPDATE_DESCRIPTIONS { + Disable = TRUE; + Border = TRUE; + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y)); + Size = MAP_APPFONT(LOCAL_WIDTH, LOCAL_LIST_HEIGHT2); + ReadOnly = TRUE; + VScroll = TRUE; + IgnoreTab = TRUE; + }; + FixedLine RID_DLG_UPDATE_LINE { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT2 + RSC_SP_FLGR_SPACE_Y)); + Size = MAP_APPFONT(LOCAL_WIDTH, RSC_CD_FIXEDLINE_HEIGHT); + }; + HelpButton RID_DLG_UPDATE_HELP { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT2 + RSC_SP_FLGR_SPACE_Y + + RSC_CD_FIXEDLINE_HEIGHT + RSC_SP_FLGR_SPACE_Y)); + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT); + }; + PushButton RID_DLG_UPDATE_OK { + Disable = TRUE; + Pos = MAP_APPFONT( + (RSC_SP_DLG_INNERBORDER_LEFT + LOCAL_WIDTH - RSC_CD_PUSHBUTTON_WIDTH - + RSC_SP_CTRL_GROUP_X - RSC_CD_PUSHBUTTON_WIDTH), + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT2 + RSC_SP_FLGR_SPACE_Y + + RSC_CD_FIXEDLINE_HEIGHT + RSC_SP_FLGR_SPACE_Y)); + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT); + Text[en-US] = "~Install"; + DefButton = TRUE; + }; + CancelButton RID_DLG_UPDATE_CANCEL { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT + LOCAL_WIDTH - RSC_CD_PUSHBUTTON_WIDTH, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT1 + RSC_SP_CTRL_GROUP_Y + + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_GROUP_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT2 + RSC_SP_FLGR_SPACE_Y + + RSC_CD_FIXEDLINE_HEIGHT + RSC_SP_FLGR_SPACE_Y)); + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT); + }; + + Image RID_DLG_UPDATE_NORMALALERT { + ImageBitmap = Bitmap { + File = "caution_12.png"; + }; + }; + Image RID_DLG_UPDATE_HIGHCONTRASTALERT { + ImageBitmap = Bitmap { + File = "caution_12_h.png"; + }; + }; + String RID_DLG_UPDATE_ERROR { + Text[en-US] = "Error"; + }; + String RID_DLG_UPDATE_NONE { + Text[en-US] = "No new updates are available."; + }; + String RID_DLG_UPDATE_NOINSTALLABLE { + Text[en-US] = "No installable updates are available. To see all updates, mark the check box 'Show all updates'."; + }; + String RID_DLG_UPDATE_FAILURE { + Text[en-US] = "An error occurred:"; + }; + String RID_DLG_UPDATE_UNKNOWNERROR { + Text[en-US] = "Unknown error."; + }; + String RID_DLG_UPDATE_NODESCRIPTION { + Text[en-US] = "No descriptions available for this extension."; + }; + String RID_DLG_UPDATE_NOINSTALL { + Text[en-US] = "The extension cannot be updated because:"; + }; + String RID_DLG_UPDATE_NODEPENDENCY { + Text[en-US] = "Required OpenOffice.org version doesn't match:"; + }; + String RID_DLG_UPDATE_NODEPENDENCY_CUR_VER { + Text[en-US] = "You have OpenOffice.org %VERSION"; + }; + String RID_DLG_UPDATE_BROWSERBASED { + Text[en-US] = "browser based update"; + }; + + String RID_DLG_UPDATE_VERSION { + Text[en-US] = "Version"; + }; +}; + +WarningBox RID_WARNINGBOX_UPDATE_SHARED_EXTENSION +{ + Buttons = WB_OK_CANCEL; + DefButton = WB_DEF_CANCEL; + Message[en-US] = "Make sure that no further users are working with the same " + "%PRODUCTNAME, when changing shared extensions in a multi user environment.\n" + "Click \'OK\' to update the extensions.\n" + "Click \'Cancel\' to stop updating the extensions."; +}; + diff --git a/desktop/source/deployment/gui/dp_gui_updateinstalldialog.cxx b/desktop/source/deployment/gui/dp_gui_updateinstalldialog.cxx new file mode 100644 index 000000000000..cfc42aa8d88c --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_updateinstalldialog.cxx @@ -0,0 +1,759 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_gui_updatedata.hxx" + +#include "sal/config.h" +#include "osl/file.hxx" +#include "osl/conditn.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "tools/resid.hxx" +#include "tools/resmgr.hxx" +#include "tools/solar.h" +#include "tools/string.hxx" +#include "vcl/dialog.hxx" +#include "vcl/msgbox.hxx" +#include "vcl/svapp.hxx" +#include "osl/mutex.hxx" +#include "vcl/dialog.hxx" +#include "cppuhelper/implbase3.hxx" + +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/beans/NamedValue.hpp" +#include "com/sun/star/xml/dom/XElement.hpp" +#include "com/sun/star/xml/dom/XNode.hpp" +#include "com/sun/star/xml/dom/XNodeList.hpp" +#include "com/sun/star/ucb/NameClash.hpp" +#include "com/sun/star/ucb/InteractiveAugmentedIOException.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/ucb/XProgressHandler.hpp" +#include "com/sun/star/deployment/XExtensionManager.hpp" +#include "com/sun/star/deployment/ExtensionManager.hpp" +#include "com/sun/star/deployment/XUpdateInformationProvider.hpp" +#include "com/sun/star/deployment/DependencyException.hpp" +#include "com/sun/star/deployment/LicenseException.hpp" +#include "com/sun/star/deployment/VersionException.hpp" +#include "com/sun/star/deployment/ui/LicenseDialog.hpp" +#include "com/sun/star/task/XInteractionHandler.hpp" +#include "com/sun/star/ui/dialogs/XExecutableDialog.hpp" +#include "com/sun/star/ui/dialogs/ExecutableDialogResults.hpp" +#include "com/sun/star/task/XInteractionAbort.hpp" +#include "com/sun/star/task/XInteractionApprove.hpp" + +#include "dp_descriptioninfoset.hxx" +#include "dp_gui.hrc" +#include "dp_gui_updateinstalldialog.hxx" +#include "dp_gui_shared.hxx" +#include "dp_gui_updatedata.hxx" +#include "dp_ucb.h" +#include "dp_misc.h" +#include "dp_version.hxx" +#include "dp_gui_thread.hxx" +#include "dp_gui_extensioncmdqueue.hxx" +#include "ucbhelper/content.hxx" +#include "osl/mutex.hxx" +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" +#include "com/sun/star/uno/Sequence.h" +#include "comphelper/anytostring.hxx" +#include "toolkit/helper/vclunohelper.hxx" + +#include <vector> + +class Window; + +namespace cssu = ::com::sun::star::uno; +namespace css = ::com::sun::star; + +using ::rtl::OUString; + + +namespace dp_gui { + +class UpdateInstallDialog::Thread: public dp_gui::Thread { + friend class UpdateCommandEnv; +public: + Thread(cssu::Reference< cssu::XComponentContext > ctx, + UpdateInstallDialog & dialog, std::vector< dp_gui::UpdateData > & aVecUpdateData); + + void stop(); + + + +private: + Thread(Thread &); // not defined + void operator =(Thread &); // not defined + + virtual ~Thread(); + + virtual void execute(); + void downloadExtensions(); + void download(::rtl::OUString const & aUrls, UpdateData & aUpdatData); + void installExtensions(); + void removeTempDownloads(); + + UpdateInstallDialog & m_dialog; + cssu::Reference< css::deployment::XUpdateInformationProvider > + m_updateInformation; + + // guarded by Application::GetSolarMutex(): + cssu::Reference< css::task::XAbortChannel > m_abort; + cssu::Reference< cssu::XComponentContext > m_xComponentContext; + std::vector< dp_gui::UpdateData > & m_aVecUpdateData; + ::rtl::Reference<UpdateCommandEnv> m_updateCmdEnv; + + //A folder which is created in the temp directory in which then the updates are downloaded + ::rtl::OUString m_sDownloadFolder; + + bool m_stop; + +}; + +class UpdateCommandEnv + : public ::cppu::WeakImplHelper3< css::ucb::XCommandEnvironment, + css::task::XInteractionHandler, + css::ucb::XProgressHandler > +{ + friend class UpdateInstallDialog::Thread; + + UpdateInstallDialog & m_updateDialog; + ::rtl::Reference<UpdateInstallDialog::Thread> m_installThread; + cssu::Reference< cssu::XComponentContext > m_xContext; + +public: + virtual ~UpdateCommandEnv(); + UpdateCommandEnv( cssu::Reference< cssu::XComponentContext > const & xCtx, + UpdateInstallDialog & updateDialog, + ::rtl::Reference<UpdateInstallDialog::Thread>const & thread); + + // XCommandEnvironment + virtual cssu::Reference<css::task::XInteractionHandler > SAL_CALL + getInteractionHandler() throw (cssu::RuntimeException); + virtual cssu::Reference<css::ucb::XProgressHandler > + SAL_CALL getProgressHandler() throw (cssu::RuntimeException); + + // XInteractionHandler + virtual void SAL_CALL handle( + cssu::Reference<css::task::XInteractionRequest > const & xRequest ) + throw (cssu::RuntimeException); + + // XProgressHandler + virtual void SAL_CALL push( cssu::Any const & Status ) + throw (cssu::RuntimeException); + virtual void SAL_CALL update( cssu::Any const & Status ) + throw (cssu::RuntimeException); + virtual void SAL_CALL pop() throw (cssu::RuntimeException); +}; + + +UpdateInstallDialog::Thread::Thread( + cssu::Reference< cssu::XComponentContext> xCtx, + UpdateInstallDialog & dialog, + std::vector< dp_gui::UpdateData > & aVecUpdateData): + m_dialog(dialog), + m_xComponentContext(xCtx), + m_aVecUpdateData(aVecUpdateData), + m_updateCmdEnv(new UpdateCommandEnv(xCtx, m_dialog, this)), + m_stop(false) +{} + +void UpdateInstallDialog::Thread::stop() { + cssu::Reference< css::task::XAbortChannel > abort; + { + SolarMutexGuard g; + abort = m_abort; + m_stop = true; + } + if (abort.is()) { + abort->sendAbort(); + } +} + +UpdateInstallDialog::Thread::~Thread() {} + +void UpdateInstallDialog::Thread::execute() +{ + try { + downloadExtensions(); + installExtensions(); + } + catch (...) + { + } + + //clean up the temp directories + try { + removeTempDownloads(); + } catch( ... ) { + } + + { + //make sure m_dialog is still alive + SolarMutexGuard g; + if (! m_stop) + m_dialog.updateDone(); + } + //UpdateCommandEnv keeps a reference to Thread and prevents destruction. Therefore remove it. + m_updateCmdEnv->m_installThread.clear(); +} + + +UpdateInstallDialog::UpdateInstallDialog( + Window * parent, + std::vector<dp_gui::UpdateData> & aVecUpdateData, + cssu::Reference< cssu::XComponentContext > const & xCtx): + ModalDialog( + parent, + DpGuiResId(RID_DLG_UPDATEINSTALL)), + + m_thread(new Thread(xCtx, *this, aVecUpdateData)), + m_xComponentContext(xCtx), + m_bError(false), + m_bNoEntry(true), + m_bActivated(false), + m_sInstalling(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_INSTALLING))), + m_sFinished(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_FINISHED))), + m_sNoErrors(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_NO_ERRORS))), + m_sErrorDownload(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_ERROR_DOWNLOAD))), + m_sErrorInstallation(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_ERROR_INSTALLATION))), + m_sErrorLicenseDeclined(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_ERROR_LIC_DECLINED))), + m_sNoInstall(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_EXTENSION_NOINSTALL))), + m_sThisErrorOccurred(String(DpGuiResId(RID_DLG_UPDATE_INSTALL_THIS_ERROR_OCCURRED))), + m_ft_action(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_DOWNLOADING)), + m_statusbar(this,DpGuiResId(RID_DLG_UPDATE_INSTALL_STATUSBAR)), + m_ft_extension_name(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_EXTENSION_NAME)), + m_ft_results(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_RESULTS)), + m_mle_info(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_INFO)), + m_line(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_LINE)), + m_help(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_HELP)), + m_ok(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_OK)), + m_cancel(this, DpGuiResId(RID_DLG_UPDATE_INSTALL_ABORT)) +{ + FreeResource(); + + m_xExtensionManager = css::deployment::ExtensionManager::get( xCtx ); + + m_cancel.SetClickHdl(LINK(this, UpdateInstallDialog, cancelHandler)); + m_mle_info.EnableCursor(FALSE); + if ( ! dp_misc::office_is_running()) + m_help.Disable(); +} + +UpdateInstallDialog::~UpdateInstallDialog() {} + +BOOL UpdateInstallDialog::Close() +{ + m_thread->stop(); + return ModalDialog::Close(); +} + +short UpdateInstallDialog::Execute() +{ + m_thread->launch(); + return ModalDialog::Execute(); +} + + +// make sure the solar mutex is locked before calling +void UpdateInstallDialog::updateDone() +{ + if (!m_bError) + m_mle_info.InsertText(m_sNoErrors); + m_ok.Enable(); + m_ok.GrabFocus(); + m_cancel.Disable(); +} +// make sure the solar mutex is locked before calling +//sets an error message in the text area +void UpdateInstallDialog::setError(INSTALL_ERROR err, ::rtl::OUString const & sExtension, + OUString const & exceptionMessage) +{ + String sError; + m_bError = true; + + switch (err) + { + case ERROR_DOWNLOAD: + sError = m_sErrorDownload; + break; + case ERROR_INSTALLATION: + sError = m_sErrorInstallation; + break; + case ERROR_LICENSE_DECLINED: + sError = m_sErrorLicenseDeclined; + break; + + default: + OSL_ASSERT(0); + } + + sError.SearchAndReplace(String(OUSTR("%NAME")), String(sExtension), 0); + //We want to have an empty line between the error messages. However, + //there shall be no empty line after the last entry. + if (m_bNoEntry) + m_bNoEntry = false; + else + m_mle_info.InsertText(OUSTR("\n")); + m_mle_info.InsertText(sError); + //Insert more information about the error + if (exceptionMessage.getLength()) + m_mle_info.InsertText(m_sThisErrorOccurred + exceptionMessage + OUSTR("\n")); + + m_mle_info.InsertText(m_sNoInstall); + m_mle_info.InsertText(OUSTR("\n")); +} + +void UpdateInstallDialog::setError(OUString const & exceptionMessage) +{ + m_bError = true; + m_mle_info.InsertText(exceptionMessage + OUSTR("\n")); +} + +IMPL_LINK(UpdateInstallDialog, cancelHandler, void *, EMPTYARG) +{ + m_thread->stop(); + EndDialog(RET_CANCEL); + return 0; +} + +//------------------------------------------------------------------------------------------------ + +void UpdateInstallDialog::Thread::downloadExtensions() +{ + try + { + //create the download directory in the temp folder + OUString sTempDir; + if (::osl::FileBase::getTempDirURL(sTempDir) != ::osl::FileBase::E_None) + throw cssu::Exception(OUSTR("Could not get URL for the temp directory. No extensions will be installed."), 0); + + //create a unique name for the directory + OUString tempEntry, destFolder; + if (::osl::File::createTempFile(&sTempDir, 0, &tempEntry ) != ::osl::File::E_None) + throw cssu::Exception(OUSTR("Could not create a temporary file in ") + sTempDir + + OUSTR(". No extensions will be installed"), 0 ); + + tempEntry = tempEntry.copy( tempEntry.lastIndexOf( '/' ) + 1 ); + + destFolder = dp_misc::makeURL( sTempDir, tempEntry ); + destFolder += OUSTR("_"); + m_sDownloadFolder = destFolder; + try + { + dp_misc::create_folder(0, destFolder, m_updateCmdEnv.get(), true ); + } catch (cssu::Exception & e) + { + throw cssu::Exception(e.Message + OUSTR(" No extensions will be installed."), 0); + } + + + sal_uInt16 count = 0; + typedef std::vector<UpdateData>::iterator It; + for (It i = m_aVecUpdateData.begin(); i != m_aVecUpdateData.end(); i++) + { + UpdateData & curData = *i; + + if (!curData.aUpdateInfo.is() || curData.aUpdateSource.is()) + continue; + //We assume that m_aVecUpdateData contains only information about extensions which + //can be downloaded directly. + OSL_ASSERT(curData.sWebsiteURL.getLength() == 0); + + //update the name of the extension which is to be downloaded + { + SolarMutexGuard g; + if (m_stop) { + return; + } + m_dialog.m_ft_extension_name.SetText(curData.aInstalledPackage->getDisplayName()); + sal_uInt16 prog = (sal::static_int_cast<sal_uInt16>(100) * ++count) / + sal::static_int_cast<sal_uInt16>(m_aVecUpdateData.size()); + m_dialog.m_statusbar.SetValue(prog); + } + dp_misc::DescriptionInfoset info(m_xComponentContext, curData.aUpdateInfo); + //remember occurring exceptions in case we need to print out error information + ::std::vector< ::std::pair<OUString, cssu::Exception> > vecExceptions; + cssu::Sequence<OUString> seqDownloadURLs = info.getUpdateDownloadUrls(); + OSL_ENSURE(seqDownloadURLs.getLength() > 0, "No download URL provided!"); + for (sal_Int32 j = 0; j < seqDownloadURLs.getLength(); j++) + { + try + { + OSL_ENSURE(seqDownloadURLs[j].getLength() > 0, "Download URL is empty!"); + download(seqDownloadURLs[j], curData); + if (curData.sLocalURL.getLength() > 0) + break; + } + catch ( cssu::Exception & e ) + { + vecExceptions.push_back( ::std::make_pair(seqDownloadURLs[j], e)); + //There can be several different errors, for example, the URL is wrong, webserver cannot be reached, + //name cannot be resolved. The UCB helper API does not specify different special exceptions for these + //cases. Therefore ignore and continue. + continue; + } + } + //update the progress and display download error + { + SolarMutexGuard g; + if (m_stop) { + return; + } + if (curData.sLocalURL.getLength() == 0) + { + //Construct a string of all messages contained in the exceptions plus the respective download URLs + ::rtl::OUStringBuffer buf(256); + typedef ::std::vector< ::std::pair<OUString, cssu::Exception > >::const_iterator CIT; + for (CIT j = vecExceptions.begin(); j != vecExceptions.end(); j++) + { + if (j != vecExceptions.begin()) + buf.appendAscii("\n"); + buf.append(OUSTR("Could not download ")); + buf.append(j->first); + buf.appendAscii(". "); + buf.append(j->second.Message); + } + m_dialog.setError(UpdateInstallDialog::ERROR_DOWNLOAD, curData.aInstalledPackage->getDisplayName(), + buf.makeStringAndClear()); + } + } + + } + } + catch (cssu::Exception & e) + { + SolarMutexGuard g; + if (m_stop) { + return; + } + m_dialog.setError(e.Message); + } +} +void UpdateInstallDialog::Thread::installExtensions() +{ + //Update the fix text in the dialog to "Installing extensions..." + { + SolarMutexGuard g; + if (m_stop) { + return; + } + m_dialog.m_ft_action.SetText(m_dialog.m_sInstalling); + m_dialog.m_statusbar.SetValue(0); + } + + sal_uInt16 count = 0; + typedef std::vector<UpdateData>::iterator It; + for (It i = m_aVecUpdateData.begin(); i != m_aVecUpdateData.end(); i++, count++) + { + //update the name of the extension which is to be installed + { + SolarMutexGuard g; + if (m_stop) { + return; + } + //we only show progress after an extension has been installed. + if (count > 0) { + m_dialog.m_statusbar.SetValue( + (sal::static_int_cast<sal_uInt16>(100) * count) / + sal::static_int_cast<sal_uInt16>(m_aVecUpdateData.size())); + } + m_dialog.m_ft_extension_name.SetText(i->aInstalledPackage->getDisplayName()); + } +// TimeValue v = {1, 0}; +// osl::Thread::wait(v); + bool bError = false; + bool bLicenseDeclined = false; + cssu::Reference<css::deployment::XPackage> xExtension; + UpdateData & curData = *i; + cssu::Exception exc; + try + { + cssu::Reference< css::task::XAbortChannel > xAbortChannel( + curData.aInstalledPackage->createAbortChannel() ); + { + SolarMutexGuard g; + if (m_stop) { + return; + } + m_abort = xAbortChannel; + } + if (!curData.aUpdateSource.is() && curData.sLocalURL.getLength()) + { + css::beans::NamedValue prop(OUSTR("EXTENSION_UPDATE"), css::uno::makeAny(OUSTR("1"))); + if (!curData.bIsShared) + xExtension = m_dialog.getExtensionManager()->addExtension( + curData.sLocalURL, css::uno::Sequence<css::beans::NamedValue>(&prop, 1), + OUSTR("user"), xAbortChannel, m_updateCmdEnv.get()); + else + xExtension = m_dialog.getExtensionManager()->addExtension( + curData.sLocalURL, css::uno::Sequence<css::beans::NamedValue>(&prop, 1), + OUSTR("shared"), xAbortChannel, m_updateCmdEnv.get()); + } + else if (curData.aUpdateSource.is()) + { + OSL_ASSERT(curData.aUpdateSource.is()); + //I am not sure if we should obtain the install properties and pass them into + //add extension. Currently it contains only "SUPPRESS_LICENSE". So it it could happen + //that a license is displayed when updating from the shared repository, although the + //shared extension was installed using "SUPPRESS_LICENSE". + css::beans::NamedValue prop(OUSTR("EXTENSION_UPDATE"), css::uno::makeAny(OUSTR("1"))); + if (!curData.bIsShared) + xExtension = m_dialog.getExtensionManager()->addExtension( + curData.aUpdateSource->getURL(), css::uno::Sequence<css::beans::NamedValue>(&prop, 1), + OUSTR("user"), xAbortChannel, m_updateCmdEnv.get()); + else + xExtension = m_dialog.getExtensionManager()->addExtension( + curData.aUpdateSource->getURL(), css::uno::Sequence<css::beans::NamedValue>(&prop, 1), + OUSTR("shared"), xAbortChannel, m_updateCmdEnv.get()); + } + } + catch (css::deployment::DeploymentException & de) + { + if (de.Cause.has<css::deployment::LicenseException>()) + { + bLicenseDeclined = true; + } + else + { + exc = de.Cause.get<cssu::Exception>(); + bError = true; + } + } + catch (cssu::Exception& e) + { + exc = e; + bError = true; + } + + if (bLicenseDeclined) + { + SolarMutexGuard g; + if (m_stop) { + return; + } + m_dialog.setError(UpdateInstallDialog::ERROR_LICENSE_DECLINED, + curData.aInstalledPackage->getDisplayName(), OUString()); + } + else if (!xExtension.is() || bError) + { + SolarMutexGuard g; + if (m_stop) { + return; + } + m_dialog.setError(UpdateInstallDialog::ERROR_INSTALLATION, + curData.aInstalledPackage->getDisplayName(), exc.Message); + } + } + { + SolarMutexGuard g; + if (m_stop) { + return; + } + m_dialog.m_statusbar.SetValue(100); + m_dialog.m_ft_extension_name.SetText(OUString()); + m_dialog.m_ft_action.SetText(m_dialog.m_sFinished); + } +} + +void UpdateInstallDialog::Thread::removeTempDownloads() +{ + if (m_sDownloadFolder.getLength()) + { + dp_misc::erase_path(m_sDownloadFolder, + cssu::Reference<css::ucb::XCommandEnvironment>(),false /* no throw: ignore errors */ ); + //remove also the temp file which we have used to create the unique name + OUString tempFile = m_sDownloadFolder.copy(0, m_sDownloadFolder.getLength() - 1); + dp_misc::erase_path(tempFile, cssu::Reference<css::ucb::XCommandEnvironment>(),false); + m_sDownloadFolder = OUString(); + } +} + + +void UpdateInstallDialog::Thread::download(OUString const & sDownloadURL, UpdateData & aUpdateData) +{ + { + SolarMutexGuard g; + if (m_stop) { + return; + } + } + + OSL_ASSERT(m_sDownloadFolder.getLength()); + OUString destFolder, tempEntry; + if (::osl::File::createTempFile( + &m_sDownloadFolder, + 0, &tempEntry ) != ::osl::File::E_None) + { + //ToDo feedback in window that download of this component failed + throw cssu::Exception(OUSTR("Could not create temporary file in folder ") + destFolder + OUSTR("."), 0); + } + tempEntry = tempEntry.copy( tempEntry.lastIndexOf( '/' ) + 1 ); + + destFolder = dp_misc::makeURL( m_sDownloadFolder, tempEntry ); + destFolder += OUSTR("_"); + + ::ucbhelper::Content destFolderContent; + dp_misc::create_folder( &destFolderContent, destFolder, m_updateCmdEnv.get() ); + + ::ucbhelper::Content sourceContent; + dp_misc::create_ucb_content( &sourceContent, sDownloadURL, m_updateCmdEnv.get() ); + + const OUString sTitle(sourceContent.getPropertyValue( + dp_misc::StrTitle::get() ).get<OUString>() ); + + if (destFolderContent.transferContent( + sourceContent, ::ucbhelper::InsertOperation_COPY, + sTitle, css::ucb::NameClash::OVERWRITE )) + { + //the user may have cancelled the dialog because downloading took to long + { + SolarMutexGuard g; + if (m_stop) { + return; + } + //all errors should be handeld by the command environment. + aUpdateData.sLocalURL = destFolder + OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ) + sTitle; + } + } +} + + +// ------------------------------------------------------------------------------------------------------- + +UpdateCommandEnv::UpdateCommandEnv( cssu::Reference< cssu::XComponentContext > const & xCtx, + UpdateInstallDialog & updateDialog, + ::rtl::Reference<UpdateInstallDialog::Thread>const & thread) + : m_updateDialog( updateDialog ), + m_installThread(thread), + m_xContext(xCtx) +{ +} + +UpdateCommandEnv::~UpdateCommandEnv() +{ +} + + +// XCommandEnvironment +//______________________________________________________________________________ +cssu::Reference<css::task::XInteractionHandler> UpdateCommandEnv::getInteractionHandler() +throw (cssu::RuntimeException) +{ + return this; +} + +//______________________________________________________________________________ +cssu::Reference<css::ucb::XProgressHandler> UpdateCommandEnv::getProgressHandler() +throw (cssu::RuntimeException) +{ + return this; +} + +// XInteractionHandler +void UpdateCommandEnv::handle( + cssu::Reference< css::task::XInteractionRequest> const & xRequest ) + throw (cssu::RuntimeException) +{ + cssu::Any request( xRequest->getRequest() ); + OSL_ASSERT( request.getValueTypeClass() == cssu::TypeClass_EXCEPTION ); + dp_misc::TRACE(OUSTR("[dp_gui_cmdenv.cxx] incoming request:\n") + + ::comphelper::anyToString(request) + OUSTR("\n\n")); + + css::deployment::VersionException verExc; + bool approve = false; + bool abort = false; + + if (request >>= verExc) + { //We must catch the version exception during the update, + //because otherwise the user would be confronted with the dialogs, asking + //them if they want to replace an already installed version of the same extension. + //During an update we assume that we always want to replace the old version with the + //new version. + approve = true; + } + + if (approve == false && abort == false) + { + //forward to interaction handler for main dialog. + handleInteractionRequest( m_xContext, xRequest ); + } + else + { + // select: + cssu::Sequence< cssu::Reference< css::task::XInteractionContinuation > > conts( + xRequest->getContinuations() ); + cssu::Reference< css::task::XInteractionContinuation > const * pConts = + conts.getConstArray(); + sal_Int32 len = conts.getLength(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + if (approve) { + cssu::Reference< css::task::XInteractionApprove > xInteractionApprove( + pConts[ pos ], cssu::UNO_QUERY ); + if (xInteractionApprove.is()) { + xInteractionApprove->select(); + // don't query again for ongoing continuations: + approve = false; + } + } + else if (abort) { + cssu::Reference< css::task::XInteractionAbort > xInteractionAbort( + pConts[ pos ], cssu::UNO_QUERY ); + if (xInteractionAbort.is()) { + xInteractionAbort->select(); + // don't query again for ongoing continuations: + abort = false; + } + } + } + } +} + +// XProgressHandler +void UpdateCommandEnv::push( cssu::Any const & /*Status*/ ) +throw (cssu::RuntimeException) +{ +} + + +void UpdateCommandEnv::update( cssu::Any const & /*Status */) +throw (cssu::RuntimeException) +{ +} + +void UpdateCommandEnv::pop() throw (cssu::RuntimeException) +{ +} + + +} //end namespace dp_gui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_updateinstalldialog.hxx b/desktop/source/deployment/gui/dp_gui_updateinstalldialog.hxx new file mode 100644 index 000000000000..a23488bfbf86 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_updateinstalldialog.hxx @@ -0,0 +1,145 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_DEPLOYMENT_GUI_DP_GUI_INSTALLDIALOG_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_DP_GUI_INSTALLDIALOG_HXX + +#include "sal/config.h" +#include "vcl/button.hxx" +#include "vcl/fixed.hxx" +#include "vcl/dialog.hxx" +#include "svtools/prgsbar.hxx" +#include "rtl/ref.hxx" +#include <vector> + +#include "dp_gui_autoscrolledit.hxx" +/// @HTML + +namespace com { namespace sun { namespace star { namespace deployment { + class XExtensionManager; +}}}} +namespace com { namespace sun { namespace star { namespace uno { + class XComponentContext; +}}}} +namespace com { namespace sun { namespace star { namespace xml { namespace dom { + class XNode; +}}}}} +namespace com { namespace sun { namespace star { namespace xml { namespace xpath { + class XXPathAPI; +}}}}} + +class Window; +namespace osl { + class Condition; +} + +namespace dp_gui { + + struct UpdateData; + class UpdateCommandEnv; + + +/** + The modal “Download and Installation” dialog. +*/ +class UpdateInstallDialog: public ModalDialog { +public: + /** + Create an instance. + + @param parent + the parent window, may be null + */ + UpdateInstallDialog(Window * parent, std::vector<UpdateData> & aVecUpdateData, + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & xCtx); + + ~UpdateInstallDialog(); + + BOOL Close(); + virtual short Execute(); + +private: + UpdateInstallDialog(UpdateInstallDialog &); // not defined + void operator =(UpdateInstallDialog &); // not defined + + class Thread; + friend class Thread; + friend class UpdateCommandEnv; + + DECL_LINK(cancelHandler, void *); + + //signals in the dialog that we have finished. + void updateDone(); + //Writes a particular error into the info listbox. + enum INSTALL_ERROR + { + ERROR_DOWNLOAD, + ERROR_INSTALLATION, + ERROR_LICENSE_DECLINED + }; + void setError(INSTALL_ERROR err, ::rtl::OUString const & sExtension, ::rtl::OUString const & exceptionMessage); + void setError(::rtl::OUString const & exceptionMessage); + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XExtensionManager > getExtensionManager() const + { return m_xExtensionManager; } + + rtl::Reference< Thread > m_thread; + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_xComponentContext; + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XExtensionManager > m_xExtensionManager; + //Signals that an error occurred during download and installation + bool m_bError; + bool m_bNoEntry; + bool m_bActivated; + + ::rtl::OUString m_sInstalling; + ::rtl::OUString m_sFinished; + ::rtl::OUString m_sNoErrors; + ::rtl::OUString m_sErrorDownload; + ::rtl::OUString m_sErrorInstallation; + ::rtl::OUString m_sErrorLicenseDeclined; + ::rtl::OUString m_sNoInstall; + ::rtl::OUString m_sThisErrorOccurred; + + FixedText m_ft_action; + ProgressBar m_statusbar; + FixedText m_ft_extension_name; + FixedText m_ft_results; + AutoScrollEdit m_mle_info; + FixedLine m_line; + HelpButton m_help; + OKButton m_ok; + CancelButton m_cancel; +}; + + + + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/dp_gui_updateinstalldialog.src b/desktop/source/deployment/gui/dp_gui_updateinstalldialog.src new file mode 100644 index 000000000000..7c4381775464 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_updateinstalldialog.src @@ -0,0 +1,203 @@ +/************************************************************************* + * + * 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 "svtools/controldims.hrc" + +#include "dp_gui.hrc" + + +#define LOCAL_WIDTH (60 * RSC_BS_CHARWIDTH) +#define LOCAL_LIST_HEIGHT (7 * RSC_BS_CHARHEIGHT) +#define LOCAL_BUTTON_WIDTH 80 + +ModalDialog RID_DLG_UPDATEINSTALL { + HelpId = HID_DEPLOYMENT_GUI_UPDATEINSTALL; + Size = MAP_APPFONT( + (RSC_SP_DLG_INNERBORDER_LEFT + LOCAL_WIDTH + + RSC_SP_DLG_INNERBORDER_RIGHT), + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_CHECKBOX_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_FLGR_SPACE_Y + LOCAL_LIST_HEIGHT + + RSC_SP_FLGR_SPACE_Y + RSC_CD_FIXEDLINE_HEIGHT + + RSC_SP_FLGR_SPACE_Y + RSC_CD_PUSHBUTTON_HEIGHT + + RSC_SP_DLG_INNERBORDER_BOTTOM)); + Text[en-US] = "Download and Installation"; + Moveable = TRUE; + Closeable = TRUE; + FixedText RID_DLG_UPDATE_INSTALL_DOWNLOADING { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, RSC_SP_DLG_INNERBORDER_TOP); + Size = MAP_APPFONT(LOCAL_WIDTH, RSC_CD_FIXEDTEXT_HEIGHT); + Text[en-US] = "Downloading extensions..."; + NoLabel = TRUE; + }; + + Window RID_DLG_UPDATE_INSTALL_STATUSBAR { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + (RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y)); + + Size = MAP_APPFONT(LOCAL_WIDTH, RSC_CD_CHECKBOX_HEIGHT); + Border = TRUE; + }; + + FixedText RID_DLG_UPDATE_INSTALL_EXTENSION_NAME { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_CHECKBOX_HEIGHT + RSC_SP_CTRL_DESC_Y); + Size = MAP_APPFONT(LOCAL_WIDTH, RSC_CD_FIXEDTEXT_HEIGHT); + Text[en-US] = ""; + NoLabel = TRUE; + }; + + FixedText RID_DLG_UPDATE_INSTALL_RESULTS { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_CHECKBOX_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_Y); + Size = MAP_APPFONT(LOCAL_WIDTH, RSC_CD_FIXEDTEXT_HEIGHT); + Text[en-US] = "Result"; + }; + + MultiLineEdit RID_DLG_UPDATE_INSTALL_INFO { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_CHECKBOX_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y); + + Size = MAP_APPFONT(LOCAL_WIDTH, LOCAL_LIST_HEIGHT); + Border = TRUE; + ReadOnly = TRUE; + VScroll = TRUE; + TabStop = FALSE; + }; + + FixedLine RID_DLG_UPDATE_INSTALL_LINE { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_CHECKBOX_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT + + RSC_SP_FLGR_SPACE_Y); + + Size = MAP_APPFONT(LOCAL_WIDTH, RSC_CD_FIXEDLINE_HEIGHT); + }; + + OKButton RID_DLG_UPDATE_INSTALL_OK { + Disable = TRUE; + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT + LOCAL_WIDTH - LOCAL_BUTTON_WIDTH - + RSC_SP_CTRL_GROUP_X - RSC_CD_PUSHBUTTON_WIDTH, + RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_CHECKBOX_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT + + RSC_SP_FLGR_SPACE_Y + RSC_CD_FIXEDLINE_HEIGHT + + RSC_SP_FLGR_SPACE_Y); + + + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT); + Text[en-US] = "OK"; + }; + + CancelButton RID_DLG_UPDATE_INSTALL_ABORT { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT + LOCAL_WIDTH - LOCAL_BUTTON_WIDTH, + RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_CHECKBOX_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT + + RSC_SP_FLGR_SPACE_Y + RSC_CD_FIXEDLINE_HEIGHT + + RSC_SP_FLGR_SPACE_Y); + + Size = MAP_APPFONT(LOCAL_BUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT); + Text[en-US] = "Cancel Update"; + DefButton = TRUE; + }; + + HelpButton RID_DLG_UPDATE_INSTALL_HELP { + Pos = MAP_APPFONT( + RSC_SP_DLG_INNERBORDER_LEFT, + RSC_SP_DLG_INNERBORDER_TOP + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_CHECKBOX_HEIGHT + + RSC_SP_CTRL_DESC_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_Y + RSC_CD_FIXEDTEXT_HEIGHT + + RSC_SP_CTRL_DESC_Y + LOCAL_LIST_HEIGHT + + RSC_SP_FLGR_SPACE_Y + RSC_CD_FIXEDLINE_HEIGHT + + RSC_SP_FLGR_SPACE_Y); + Size = MAP_APPFONT(RSC_CD_PUSHBUTTON_WIDTH, RSC_CD_PUSHBUTTON_HEIGHT); + }; + + + String RID_DLG_UPDATE_INSTALL_INSTALLING { + Text[en-US] = "Installing extensions..."; + }; + + String RID_DLG_UPDATE_INSTALL_FINISHED { + Text[en-US] = "Installation finished"; + }; + + String RID_DLG_UPDATE_INSTALL_NO_ERRORS { + Text[en-US] = "No errors."; + }; + + String RID_DLG_UPDATE_INSTALL_ERROR_DOWNLOAD { + Text[en-US] = "Error while downloading extension %NAME. "; + }; + + String RID_DLG_UPDATE_INSTALL_THIS_ERROR_OCCURRED { + Text[en-US] = "The error message is: "; + }; + + + String RID_DLG_UPDATE_INSTALL_ERROR_INSTALLATION { + Text[en-US] = "Error while installing extension %NAME. "; + }; + + String RID_DLG_UPDATE_INSTALL_ERROR_LIC_DECLINED { + Text[en-US] = "The license agreement for extension %NAME was refused. "; + }; + + String RID_DLG_UPDATE_INSTALL_EXTENSION_NOINSTALL{ + Text[en-US] = "The extension will not be installed."; + }; + +}; + diff --git a/desktop/source/deployment/gui/dp_gui_versionboxes.src b/desktop/source/deployment/gui/dp_gui_versionboxes.src new file mode 100644 index 000000000000..cc6edc0ad760 --- /dev/null +++ b/desktop/source/deployment/gui/dp_gui_versionboxes.src @@ -0,0 +1,76 @@ +/************************************************************************* + * + * 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 "dp_gui.hrc" + +WarningBox RID_WARNINGBOX_VERSION_LESS { + Buttons = WB_OK_CANCEL; + DefButton = WB_DEF_CANCEL; + Message[en-US] = "You are about to install version $NEW of the extension \'$NAME\'.\n" + "The newer version $DEPLOYED is already installed.\n" + "Click \'OK\' to replace the installed extension.\n" + "Click \'Cancel\' to stop the installation."; +}; + +String RID_STR_WARNINGBOX_VERSION_LESS_DIFFERENT_NAMES { + Text [en-US] = "You are about to install version $NEW of the extension \'$NAME\'.\n" + "The newer version $DEPLOYED, named \'$OLDNAME\', is already installed.\n" + "Click \'OK\' to replace the installed extension.\n" + "Click \'Cancel\' to stop the installation."; +}; + +WarningBox RID_WARNINGBOX_VERSION_EQUAL { + Buttons = WB_OK_CANCEL; + DefButton = WB_DEF_CANCEL; + Message[en-US] = "You are about to install version $NEW of the extension \'$NAME\'.\n" + "That version is already installed.\n" + "Click \'OK\' to replace the installed extension.\n" + "Click \'Cancel\' to stop the installation."; +}; + +String RID_STR_WARNINGBOX_VERSION_EQUAL_DIFFERENT_NAMES { + Text [en-US] = "You are about to install version $NEW of the extension \'$NAME\'.\n" + "That version, named \'$OLDNAME\', is already installed.\n" + "Click \'OK\' to replace the installed extension.\n" + "Click \'Cancel\' to stop the installation."; +}; + +WarningBox RID_WARNINGBOX_VERSION_GREATER { + Buttons = WB_OK_CANCEL; + DefButton = WB_DEF_OK; + Message[en-US] = "You are about to install version $NEW of the extension \'$NAME\'.\n" + "The older version $DEPLOYED is already installed.\n" + "Click \'OK\' to replace the installed extension.\n" + "Click \'Cancel\' to stop the installation."; +}; + +String RID_STR_WARNINGBOX_VERSION_GREATER_DIFFERENT_NAMES { + TEXT [en-US] = "You are about to install version $NEW of the extension \'$NAME\'.\n" + "The older version $DEPLOYED, named \'$OLDNAME\', is already installed.\n" + "Click \'OK\' to replace the installed extension.\n" + "Click \'Cancel\' to stop the installation."; +};
\ No newline at end of file diff --git a/desktop/source/deployment/gui/license_dialog.cxx b/desktop/source/deployment/gui/license_dialog.cxx new file mode 100644 index 000000000000..9fd55d293859 --- /dev/null +++ b/desktop/source/deployment/gui/license_dialog.cxx @@ -0,0 +1,332 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "cppuhelper/implbase2.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "unotools/configmgr.hxx" +#include "comphelper/servicedecl.hxx" +#include "comphelper/unwrapargs.hxx" +#include "i18npool/mslangid.hxx" +#include "vcl/svapp.hxx" +#include "vcl/msgbox.hxx" +#include "toolkit/helper/vclunohelper.hxx" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/task/XJobExecutor.hpp" +#include "svtools/svmedit.hxx" +#include "svl/lstner.hxx" +#include "svtools/xtextedt.hxx" +#include <vcl/scrbar.hxx> +#include "vcl/threadex.hxx" + + + +#include "boost/bind.hpp" +#include "dp_gui_shared.hxx" +#include "license_dialog.hxx" +#include "dp_gui.hrc" + +using namespace ::dp_misc; +namespace cssu = ::com::sun::star::uno; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +namespace dp_gui { + +class LicenseView : public MultiLineEdit, public SfxListener +{ + BOOL mbEndReached; + Link maEndReachedHdl; + Link maScrolledHdl; + +public: + LicenseView( Window* pParent, const ResId& rResId ); + ~LicenseView(); + + void ScrollDown( ScrollType eScroll ); + + BOOL IsEndReached() const; + BOOL EndReached() const { return mbEndReached; } + void SetEndReached( BOOL bEnd ) { mbEndReached = bEnd; } + + void SetEndReachedHdl( const Link& rHdl ) { maEndReachedHdl = rHdl; } + const Link& GetAutocompleteHdl() const { return maEndReachedHdl; } + + void SetScrolledHdl( const Link& rHdl ) { maScrolledHdl = rHdl; } + const Link& GetScrolledHdl() const { return maScrolledHdl; } + + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); + +protected: + using MultiLineEdit::Notify; +}; + +struct LicenseDialogImpl : public ModalDialog +{ + cssu::Reference<cssu::XComponentContext> m_xComponentContext; + FixedText m_ftHead; + FixedText m_ftBody1; + FixedText m_ftBody1Txt; + FixedText m_ftBody2; + FixedText m_ftBody2Txt; + FixedImage m_fiArrow1; + FixedImage m_fiArrow2; + LicenseView m_mlLicense; + PushButton m_pbDown; + FixedLine m_flBottom; + + OKButton m_acceptButton; + CancelButton m_declineButton; + + DECL_LINK(PageDownHdl, PushButton*); + DECL_LINK(ScrolledHdl, LicenseView*); + DECL_LINK(EndReachedHdl, LicenseView*); + + bool m_bLicenseRead; + + virtual ~LicenseDialogImpl(); + + LicenseDialogImpl( + Window * pParent, + css::uno::Reference< css::uno::XComponentContext > const & xContext, + const ::rtl::OUString & sExtensionName, + const ::rtl::OUString & sLicenseText); + + virtual void Activate(); + +}; + +LicenseView::LicenseView( Window* pParent, const ResId& rResId ) + : MultiLineEdit( pParent, rResId ) +{ + SetLeftMargin( 5 ); + mbEndReached = IsEndReached(); + StartListening( *GetTextEngine() ); +} + +LicenseView::~LicenseView() +{ + maEndReachedHdl = Link(); + maScrolledHdl = Link(); + EndListeningAll(); +} + +void LicenseView::ScrollDown( ScrollType eScroll ) +{ + ScrollBar* pScroll = GetVScrollBar(); + if ( pScroll ) + pScroll->DoScrollAction( eScroll ); +} + +BOOL LicenseView::IsEndReached() const +{ + BOOL bEndReached; + + ExtTextView* pView = GetTextView(); + ExtTextEngine* pEdit = GetTextEngine(); + ULONG nHeight = pEdit->GetTextHeight(); + Size aOutSize = pView->GetWindow()->GetOutputSizePixel(); + Point aBottom( 0, aOutSize.Height() ); + + if ( (ULONG) pView->GetDocPos( aBottom ).Y() >= nHeight - 1 ) + bEndReached = TRUE; + else + bEndReached = FALSE; + + return bEndReached; +} + +void LicenseView::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.IsA( TYPE(TextHint) ) ) + { + BOOL bLastVal = EndReached(); + ULONG nId = ((const TextHint&)rHint).GetId(); + + if ( nId == TEXT_HINT_PARAINSERTED ) + { + if ( bLastVal ) + mbEndReached = IsEndReached(); + } + else if ( nId == TEXT_HINT_VIEWSCROLLED ) + { + if ( ! mbEndReached ) + mbEndReached = IsEndReached(); + maScrolledHdl.Call( this ); + } + + if ( EndReached() && !bLastVal ) + { + maEndReachedHdl.Call( this ); + } + } +} + +//============================================================================================================== + +LicenseDialogImpl::LicenseDialogImpl( + Window * pParent, + cssu::Reference< cssu::XComponentContext > const & xContext, + const ::rtl::OUString & sExtensionName, + const ::rtl::OUString & sLicenseText): + ModalDialog(pParent, DpGuiResId(RID_DLG_LICENSE)) + ,m_xComponentContext(xContext) + ,m_ftHead(this, DpGuiResId(FT_LICENSE_HEADER)) + ,m_ftBody1(this, DpGuiResId(FT_LICENSE_BODY_1)) + ,m_ftBody1Txt(this, DpGuiResId(FT_LICENSE_BODY_1_TXT)) + ,m_ftBody2(this, DpGuiResId(FT_LICENSE_BODY_2)) + ,m_ftBody2Txt(this, DpGuiResId(FT_LICENSE_BODY_2_TXT)) + ,m_fiArrow1(this, DpGuiResId(FI_LICENSE_ARROW1)) + ,m_fiArrow2(this, DpGuiResId(FI_LICENSE_ARROW2)) + ,m_mlLicense(this, DpGuiResId(ML_LICENSE)) + ,m_pbDown(this, DpGuiResId(PB_LICENSE_DOWN)) + ,m_flBottom(this, DpGuiResId(FL_LICENSE)) + ,m_acceptButton(this, DpGuiResId(BTN_LICENSE_ACCEPT)) + ,m_declineButton(this, DpGuiResId(BTN_LICENSE_DECLINE)) + ,m_bLicenseRead(false) + +{ + + if (GetSettings().GetStyleSettings().GetHighContrastMode()) + { + // high contrast mode needs other images + m_fiArrow1.SetImage(Image(DpGuiResId(IMG_LICENCE_ARROW_HC))); + m_fiArrow2.SetImage(Image(DpGuiResId(IMG_LICENCE_ARROW_HC))); + } + + FreeResource(); + + m_acceptButton.SetUniqueId(UID_BTN_LICENSE_ACCEPT); + m_fiArrow1.Show(true); + m_fiArrow2.Show(false); + m_mlLicense.SetText(sLicenseText); + m_ftHead.SetText(m_ftHead.GetText() + OUString('\n') + sExtensionName); + + m_mlLicense.SetEndReachedHdl( LINK(this, LicenseDialogImpl, EndReachedHdl) ); + m_mlLicense.SetScrolledHdl( LINK(this, LicenseDialogImpl, ScrolledHdl) ); + m_pbDown.SetClickHdl( LINK(this, LicenseDialogImpl, PageDownHdl) ); + + // We want a automatic repeating page down button + WinBits aStyle = m_pbDown.GetStyle(); + aStyle |= WB_REPEAT; + m_pbDown.SetStyle( aStyle ); +} + +LicenseDialogImpl::~LicenseDialogImpl() +{ +} + +void LicenseDialogImpl::Activate() +{ + if (!m_bLicenseRead) + { + //Only enable the scroll down button if the license text does not fit into the window + if (m_mlLicense.IsEndReached()) + { + m_pbDown.Disable(); + m_acceptButton.Enable(); + m_acceptButton.GrabFocus(); + } + else + { + m_pbDown.Enable(); + m_pbDown.GrabFocus(); + m_acceptButton.Disable(); + } + } +} + +IMPL_LINK( LicenseDialogImpl, ScrolledHdl, LicenseView *, EMPTYARG ) +{ + + if (m_mlLicense.IsEndReached()) + m_pbDown.Disable(); + else + m_pbDown.Enable(); + + return 0; +} + +IMPL_LINK( LicenseDialogImpl, PageDownHdl, PushButton *, EMPTYARG ) +{ + m_mlLicense.ScrollDown( SCROLL_PAGEDOWN ); + return 0; +} + +IMPL_LINK( LicenseDialogImpl, EndReachedHdl, LicenseView *, EMPTYARG ) +{ + m_acceptButton.Enable(); + m_acceptButton.GrabFocus(); + m_fiArrow1.Show(false); + m_fiArrow2.Show(true); + m_bLicenseRead = true; + return 0; +} + +//================================================================================= + + + + +LicenseDialog::LicenseDialog( Sequence<Any> const& args, + Reference<XComponentContext> const& xComponentContext) + : m_xComponentContext(xComponentContext) +{ + comphelper::unwrapArgs( args, m_parent, m_sExtensionName, m_sLicenseText ); +} + +// XExecutableDialog +//______________________________________________________________________________ +void LicenseDialog::setTitle( OUString const & ) throw (RuntimeException) +{ + +} + +//______________________________________________________________________________ +sal_Int16 LicenseDialog::execute() throw (RuntimeException) +{ + return vcl::solarthread::syncExecute( + boost::bind( &LicenseDialog::solar_execute, this)); +} + +sal_Int16 LicenseDialog::solar_execute() +{ + std::auto_ptr<LicenseDialogImpl> dlg( + new LicenseDialogImpl( + VCLUnoHelper::GetWindow(m_parent), + m_xComponentContext, m_sExtensionName, m_sLicenseText)); + + return dlg->Execute(); +} + +} // namespace dp_gui + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/license_dialog.hxx b/desktop/source/deployment/gui/license_dialog.hxx new file mode 100644 index 000000000000..7e7a8592e66f --- /dev/null +++ b/desktop/source/deployment/gui/license_dialog.hxx @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_DEPLOYMENT_GUI_LICENSE_DIALOG_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_GUI_LICENSE_DIALOG_HXX + +#include "dp_gui.h" +#include "cppuhelper/implbase1.hxx" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/task/XJobExecutor.hpp" +#include "com/sun/star/ui/dialogs/XExecutableDialog.hpp" + +#include "boost/bind.hpp" + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +namespace dp_gui { + +class LicenseDialog + : public ::cppu::WeakImplHelper1<ui::dialogs::XExecutableDialog> +// task::XJobExecutor> +{ + Reference<XComponentContext> const m_xComponentContext; + Reference<awt::XWindow> /* const */ m_parent; + OUString m_sExtensionName; + OUString /* const */ m_sLicenseText; + OUString m_initialTitle; + + sal_Int16 solar_execute(); + +public: + LicenseDialog( Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ); + + // XExecutableDialog + virtual void SAL_CALL setTitle( OUString const & title ) + throw (RuntimeException); + virtual sal_Int16 SAL_CALL execute() throw (RuntimeException); + + //// XJobExecutor + //virtual void SAL_CALL trigger( OUString const & event ) + // throw (RuntimeException); +}; +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/gui/makefile.mk b/desktop/source/deployment/gui/makefile.mk new file mode 100644 index 000000000000..52092a077a4b --- /dev/null +++ b/desktop/source/deployment/gui/makefile.mk @@ -0,0 +1,109 @@ +#************************************************************************* +# +# 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 = deploymentgui +ENABLE_EXCEPTIONS = TRUE +#USE_DEFFILE = TRUE +NO_BSYMBOLIC = TRUE +USE_PCH := +ENABLE_PCH := +PRJINC:=..$/.. + +.IF "$(GUI)"=="OS2" +TARGET = deplgui +.ENDIF + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/source$/deployment$/inc$/dp_misc.mk +DLLPRE = + +SLOFILES = \ + $(SLO)$/dp_gui_service.obj \ + $(SLO)$/dp_gui_extlistbox.obj \ + $(SLO)$/dp_gui_dialog2.obj \ + $(SLO)$/dp_gui_theextmgr.obj \ + $(SLO)$/license_dialog.obj \ + $(SLO)$/dp_gui_dependencydialog.obj \ + $(SLO)$/dp_gui_thread.obj \ + $(SLO)$/dp_gui_updatedialog.obj \ + $(SLO)$/dp_gui_updateinstalldialog.obj \ + $(SLO)$/dp_gui_autoscrolledit.obj \ + $(SLO)$/dp_gui_system.obj \ + $(SLO)$/dp_gui_extensioncmdqueue.obj \ + $(SLO)$/descedit.obj + +SHL1TARGET = $(TARGET)$(DLLPOSTFIX).uno +SHL1VERSIONMAP = $(SOLARENV)/src/component.map + +SHL1STDLIBS = \ + $(SALLIB) \ + $(SALHELPERLIB) \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(UCBHELPERLIB) \ + $(COMPHELPERLIB) \ + $(UNOTOOLSLIB) \ + $(TOOLSLIB) \ + $(I18NISOLANGLIB) \ + $(TKLIB) \ + $(VCLLIB) \ + $(SVTOOLLIB) \ + $(SVLLIB) \ + $(SVXLIB) \ + $(SVXCORELIB) \ + $(SFXLIB) \ + $(DEPLOYMENTMISCLIB) \ + $(OLE32LIB) + +SHL1DEPN = +SHL1IMPLIB = i$(TARGET) +SHL1LIBS = $(SLB)$/$(TARGET).lib +SHL1DEF = $(MISC)$/$(SHL1TARGET).def + +DEF1NAME = $(SHL1TARGET) +#DEFLIB1NAME = $(TARGET) +#DEF1DEPN = + +SRS1NAME = $(TARGET) +SRC1FILES = \ + dp_gui_dialog.src \ + dp_gui_dialog2.src \ + dp_gui_backend.src \ + dp_gui_dependencydialog.src \ + dp_gui_updatedialog.src \ + dp_gui_versionboxes.src \ + dp_gui_updateinstalldialog.src + +RESLIB1NAME = $(TARGET) +RESLIB1SRSFILES = $(SRS)$/$(TARGET).srs +RESLIB1IMAGES= $(PRJ)$/res + +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/inc/db.hxx b/desktop/source/deployment/inc/db.hxx new file mode 100644 index 000000000000..4f144667a920 --- /dev/null +++ b/desktop/source/deployment/inc/db.hxx @@ -0,0 +1,175 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 BERKELEYDBPROXY_DB_HXX_ +#define BERKELEYDBPROXY_DB_HXX_ + +#ifdef SYSTEM_DB +#include <db.h> +#else +#include <berkeleydb/db.h> +#endif + +#include <rtl/string.hxx> +#include "dp_misc_api.hxx" + +extern "C" { + typedef void *(*db_malloc_fcn_type)(size_t); + typedef void *(*db_realloc_fcn_type)(void *, size_t); + typedef void (*db_free_fcn_type)(void *); +} + + +namespace berkeleydbproxy { + + class DbEnv; + class Dbc; + class Dbt; + + namespace db_internal + { + class Noncopyable + { + // not implemented + Noncopyable(const Noncopyable&); + void operator=(const Noncopyable&); + protected: + Noncopyable() {} + ~Noncopyable() {} + }; + } + + class DESKTOP_DEPLOYMENTMISC_DLLPUBLIC DbException + { + rtl::OString what_; + public: + explicit DbException(rtl::OString const & theWhat) + : what_(theWhat) + {} + + const char *what() const + { return what_.getStr(); } + int get_errno() const + { return 0; } + }; + + + class DESKTOP_DEPLOYMENTMISC_DLLPUBLIC DbEnv : db_internal::Noncopyable + { + friend class Db; + + private: + DB_ENV* m_pDBENV; + + public: + static char *strerror(int); + }; + + class DESKTOP_DEPLOYMENTMISC_DLLPUBLIC Db : db_internal::Noncopyable + { + private: + DB* m_pDBP; + + public: + Db(DbEnv* dbbenv,u_int32_t flags); + ~Db(); + + int close(u_int32_t flags); + + int open(DB_TXN *txnid, + const char *file, + const char *database, + DBTYPE type, + u_int32_t flags, + int mode); + + int sync(u_int32_t flags); + int del(Dbt *key, u_int32_t flags); + + int get(DB_TXN* txnid, Dbt *key, Dbt *data, u_int32_t flags); + int put(DB_TXN* txnid, Dbt *key, Dbt *data, u_int32_t flags); + + int cursor(DB_TXN *txnid, Dbc **cursorp, u_int32_t flags); + }; + + class DESKTOP_DEPLOYMENTMISC_DLLPUBLIC Dbc : db_internal::Noncopyable + { + friend class Db; + friend class Dbt; + + private: + DBC* m_pDBC; + + SAL_DLLPRIVATE explicit Dbc(DBC* pDBC); + SAL_DLLPRIVATE ~Dbc(); + + public: + int close(); + + int get(Dbt *key, Dbt *data, u_int32_t flags); + }; + + class DESKTOP_DEPLOYMENTMISC_DLLPUBLIC Dbt: private DBT + { + friend class Db; + friend class Dbc; + + public: + Dbt(void *data_arg, u_int32_t size_arg); + + Dbt(); + Dbt(const Dbt & other); + Dbt & operator=(const Dbt & other); + + ~Dbt(); + + void *get_data() const; + void set_data(void *value); + + u_int32_t get_size() const; + void set_size(u_int32_t value); + }; +} + +#endif + + + + + + + + + + + + + + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_dependencies.hxx b/desktop/source/deployment/inc/dp_dependencies.hxx new file mode 100644 index 000000000000..2e57c0627573 --- /dev/null +++ b/desktop/source/deployment/inc/dp_dependencies.hxx @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_DEPLOYMENT_INC_DP_DEPENDENCIES_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_INC_DP_DEPENDENCIES_HXX + +#include "sal/config.h" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "dp_misc_api.hxx" + +/// @HTML + +namespace com { namespace sun { namespace star { namespace xml { namespace dom { + class XElement; +} } } } } +namespace dp_misc { class DescriptionInfoset; } +namespace rtl { class OUString; } + +namespace dp_misc { + +/** + Dependency handling. +*/ +namespace Dependencies { + /** + Check for unsatisfied dependencies. + + @param infoset + the infoset containing the dependencies to check + + @return + a list of the unsatisfied dependencies from <code>infoset</code> (in no + specific order) + */ + DESKTOP_DEPLOYMENTMISC_DLLPUBLIC + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< + ::com::sun::star::xml::dom::XElement > > + check(::dp_misc::DescriptionInfoset const & infoset); + + /** + Obtain the (human-readable) error message of a failed dependency. + + @param dependency + a dependency represented as a non-null XML element + + @return + the name of the dependency; will never be empty, as a localized + “unknown” is substituted for an empty/missing name + */ + DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString getErrorText( + ::com::sun::star::uno::Reference< + ::com::sun::star::xml::dom::XElement > const & dependency); +} + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_descriptioninfoset.hxx b/desktop/source/deployment/inc/dp_descriptioninfoset.hxx new file mode 100644 index 000000000000..78b824c87ab5 --- /dev/null +++ b/desktop/source/deployment/inc/dp_descriptioninfoset.hxx @@ -0,0 +1,302 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_DEPLOYMENT_INC_DP_DESCRIPTIONINFOSET_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_INC_DP_DESCRIPTIONINFOSET_HXX + +#include "sal/config.h" + +#include "boost/optional.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "sal/types.h" +#include "dp_misc_api.hxx" + +/// @HTML + +namespace com { namespace sun { namespace star { + namespace lang { struct Locale; } + namespace uno { class XComponentContext; } + namespace xml { + namespace dom { + class XNode; + class XNodeList; + } + namespace xpath { class XXPathAPI; } + } +} } } +namespace rtl { class OUString; } + +namespace dp_misc { + +struct DESKTOP_DEPLOYMENTMISC_DLLPUBLIC SimpleLicenseAttributes +{ + ::rtl::OUString acceptBy; + //Attribute suppress-on-update. Default is false. + bool suppressOnUpdate; + //Attribute suppress-if-required. Default is false. + bool suppressIfRequired; +}; + + +/** + Access to the content of an XML <code>description</code> element. + + <p>This works for <code>description</code> elements in both the + <code>description.xml</code> file and online update information formats.</p> +*/ +class DESKTOP_DEPLOYMENTMISC_DLLPUBLIC DescriptionInfoset { +public: + /** + Create an instance. + + @param context + a non-null component context + + @param element + a <code>description</code> element; may be null (equivalent to an element + with no content) + */ + DescriptionInfoset( + ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > const & context, + ::com::sun::star::uno::Reference< + ::com::sun::star::xml::dom::XNode > const & element); + + ~DescriptionInfoset(); + + /** + Return the identifier. + + @return + the identifier, or an empty <code>optional</code> if none is specified + */ + ::boost::optional< ::rtl::OUString > getIdentifier() const; + + /** + Return the textual version representation. + + @return + textual version representation + */ + ::rtl::OUString getVersion() const; + + /** + Returns a list of supported platforms. + + If the extension does not specify a platform by leaving out the platform element + then we assume that the extension supports all platforms. In this case the returned + sequence will have one element, which is "all". + If the platform element is present but does not specify a platform then an empty + sequence is returned. Examples for invalid platform elements: + <pre> + <platform />, <platform value="" />, <platfrom value=","> + </pre> + + The value attribute can contain various platform tokens. They must be separated by + commas.Each token will be stripped from leading and trailing white space (trim()). + */ + ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedPlaforms() const; + + /** + Returns the localized publisher name and the corresponding URL. + + In case there is no publisher element then a pair of two empty strings is returned. + */ + ::std::pair< ::rtl::OUString, ::rtl::OUString > getLocalizedPublisherNameAndURL() const; + + /** + Returns the URL for the release notes corresponding to the office's locale. + + In case there is no release-notes element then an empty string is returned. + */ + ::rtl::OUString getLocalizedReleaseNotesURL() const; + + /** returns the relative path to the license file. + + In case there is no simple-license element then an empty string is returned. + */ + ::rtl::OUString getLocalizedLicenseURL() const; + + /** returns the attributes of the simple-license element + + As long as there is a simple-license element, the function will return + the structure. If it does not exist, then the optional object is uninitialized. + */ + ::boost::optional<SimpleLicenseAttributes> getSimpleLicenseAttributes() const; + + /** returns the localized display name of the extensions. + + In case there is no localized display-name then an empty string is returned. + */ + ::rtl::OUString getLocalizedDisplayName() const; + + /** + returns the download website URL from the update information. + + There can be multiple URLs where each is assigned to a particular locale. + The function returs the URL which locale matches best the one used in the office. + + The return value is an optional because it may be necessary to find out if there + was a value provided or not. This is necessary to flag the extension in the update dialog + properly as "browser based update". The return value will only then not be initialized + if there is no <code><update-website></code>. If the element exists, then it must + have at least one child element containing an URL. + + The <code><update-website></code> and <code><update-download></code> + elements are mutually exclusiv. + + @return + the download website URL, or an empty <code>optional</code> if none is + specified + */ + ::boost::optional< ::rtl::OUString > getLocalizedUpdateWebsiteURL() const; + + /** returns the relative URL to the description. + + The URL is relative to the root directory of the extensions. + */ + ::rtl::OUString getLocalizedDescriptionURL() const; + /** + Return the dependencies. + + @return + dependencies; will never be null + */ + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNodeList > + getDependencies() const; + + /** + Return the update information URLs. + + @return + update information URLs + */ + ::com::sun::star::uno::Sequence< ::rtl::OUString > + getUpdateInformationUrls() const; + + /** + Return the download URLs from the update information. + + Because the <code><update-download></code> and the <code><update-website></code> + elements are mutually exclusive one may need to determine exacty if the element + was provided. + + @return + download URLs + */ + ::com::sun::star::uno::Sequence< ::rtl::OUString > + getUpdateDownloadUrls() const; + + /** + Returns the URL for the icon image. + */ + ::rtl::OUString getIconURL( sal_Bool bHighContrast ) const; + + bool hasDescription() const; + +private: + SAL_DLLPRIVATE ::boost::optional< ::rtl::OUString > getOptionalValue( + ::rtl::OUString const & expression) const; + + SAL_DLLPRIVATE ::com::sun::star::uno::Sequence< ::rtl::OUString > getUrls( + ::rtl::OUString const & expression) const; + + /** Retrieves a child element which as lang attribute which matches the office locale. + + Only top-level children are taken into account. It is also assumed that they are all + of the same element type and have a lang attribute. The matching algoritm is according + to RFC 3066, with the exception that only one variant is allowed. + @param parent + the expression used to obtain the parent of the localized children. It can be null. + Then a null reference is returned. + */ + SAL_DLLPRIVATE ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > + getLocalizedChild( ::rtl::OUString const & sParent) const; + SAL_DLLPRIVATE ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode> + matchFullLocale(::com::sun::star::uno::Reference< + ::com::sun::star::xml::dom::XNode > const & xParent, ::rtl::OUString const & sLocale) const; + SAL_DLLPRIVATE ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode> + matchCountryAndLanguage(::com::sun::star::uno::Reference< + ::com::sun::star::xml::dom::XNode > const & xParent, + ::com::sun::star::lang::Locale const & officeLocale) const; + SAL_DLLPRIVATE ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode> + matchLanguage( + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > const & xParent, + ::com::sun::star::lang::Locale const & officeLocale) const; + + /** If there is no child element with a locale matching the office locale, then we use + the first child. In the case of the simple-license we also use the former default locale, which + was determined by the default-license-id (/description/registration/simple-license/@default-license-id) + and the license-id attributes (/description/registration/simple-license/license-text/@license-id). + However, since OOo 2.4 we use also the first child as default for the license + unless the two attributes are present. + */ + SAL_DLLPRIVATE ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode> + getChildWithDefaultLocale( + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > const & xParent) const; + /** + @param out_bParentExists + indicates if the element node specified in sXPathParent exists. + */ + SAL_DLLPRIVATE ::rtl::OUString getLocalizedHREFAttrFromChild( + ::rtl::OUString const & sXPathParent, bool * out_bParentExists) const; + + static SAL_DLLPRIVATE ::rtl::OUString + localeToString(::com::sun::star::lang::Locale const & locale); + + /** Gets the node value for a given expression. The expression is used in + m_xpath-selectSingleNode. The value of the returned node is return value + of this function. + */ + SAL_DLLPRIVATE ::rtl::OUString + getNodeValueFromExpression(::rtl::OUString const & expression) const; + + ::com::sun::star::uno::Reference< + ::com::sun::star::xml::dom::XNode > m_element; + ::com::sun::star::uno::Reference< + ::com::sun::star::xml::xpath::XXPathAPI > m_xpath; +}; + +inline bool DescriptionInfoset::hasDescription() const +{ + return m_element.is(); +} + +/** creates a DescriptionInfoset object. + + The argument sExtensionFolderURL is a file URL to extension folder containing + the description.xml. + */ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +DescriptionInfoset getDescriptionInfoset(::rtl::OUString const & sExtensionFolderURL); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_identifier.hxx b/desktop/source/deployment/inc/dp_identifier.hxx new file mode 100644 index 000000000000..f7b6b1f120fb --- /dev/null +++ b/desktop/source/deployment/inc/dp_identifier.hxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_DEPLOYMENT_INC_DP_IDENTIFIER_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_INC_DP_IDENTIFIER_HXX + +#include "sal/config.h" + +#include "boost/optional.hpp" +#include "com/sun/star/uno/Reference.hxx" + +#include "dp_misc_api.hxx" + +namespace com { namespace sun { namespace star { namespace deployment { + class XPackage; +} } } } +namespace rtl { class OUString; } + +namespace dp_misc { + +/** + Generates an identifier from an optional identifier. + + @param optional + an optional identifier + + @param fileName + a file name + + @return + the given optional identifier if present, otherwise a legacy identifier based + on the given file name +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString generateIdentifier( + ::boost::optional< ::rtl::OUString > const & optional, + ::rtl::OUString const & fileName); + +/** + Gets the identifier of a package. + + @param package + a non-null package + + @return + the explicit identifier of the given package if present, otherwise the + implicit legacy identifier of the given package + + @throws com::sun::star::uno::RuntimeException +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString getIdentifier( + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > + const & package); + +/** + Generates a legacy identifier based on a file name. + + @param fileName + a file name + + @return + a legacy identifier based on the given file name +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString generateLegacyIdentifier( + ::rtl::OUString const & fileName); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_interact.h b/desktop/source/deployment/inc/dp_interact.h new file mode 100644 index 000000000000..3aca761c2d1e --- /dev/null +++ b/desktop/source/deployment/inc/dp_interact.h @@ -0,0 +1,153 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_INTERACT_H +#define INCLUDED_DP_INTERACT_H + +#include "rtl/ref.hxx" +#include "cppuhelper/implbase1.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/task/XAbortChannel.hpp" +#include "dp_misc_api.hxx" + +namespace css = ::com::sun::star; + +namespace dp_misc +{ + +inline void progressUpdate( + ::rtl::OUString const & status, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) +{ + if (xCmdEnv.is()) { + css::uno::Reference<css::ucb::XProgressHandler> xProgressHandler( + xCmdEnv->getProgressHandler() ); + if (xProgressHandler.is()) { + xProgressHandler->update( css::uno::makeAny(status) ); + } + } +} + +//============================================================================== +class ProgressLevel +{ + css::uno::Reference<css::ucb::XProgressHandler> m_xProgressHandler; + +public: + inline ~ProgressLevel(); + inline ProgressLevel( + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + ::rtl::OUString const & status ); + + inline void update( ::rtl::OUString const & status ) const; + inline void update( css::uno::Any const & status ) const; +}; + +//______________________________________________________________________________ +inline ProgressLevel::ProgressLevel( + css::uno::Reference< css::ucb::XCommandEnvironment > const & xCmdEnv, + ::rtl::OUString const & status ) +{ + if (xCmdEnv.is()) + m_xProgressHandler = xCmdEnv->getProgressHandler(); + if (m_xProgressHandler.is()) + m_xProgressHandler->push( css::uno::makeAny(status) ); +} + +//______________________________________________________________________________ +inline ProgressLevel::~ProgressLevel() +{ + if (m_xProgressHandler.is()) + m_xProgressHandler->pop(); +} + +//______________________________________________________________________________ +inline void ProgressLevel::update( ::rtl::OUString const & status ) const +{ + if (m_xProgressHandler.is()) + m_xProgressHandler->update( css::uno::makeAny(status) ); +} + +//______________________________________________________________________________ +inline void ProgressLevel::update( css::uno::Any const & status ) const +{ + if (m_xProgressHandler.is()) + m_xProgressHandler->update( status ); +} + +//############################################################################## + +/** @return true if ia handler is present and any selection has been chosen + */ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool interactContinuation( + css::uno::Any const & request, + css::uno::Type const & continuation, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + bool * pcont, bool * pabort ); + +//############################################################################## + +//============================================================================== +class DESKTOP_DEPLOYMENTMISC_DLLPUBLIC AbortChannel : + public ::cppu::WeakImplHelper1<css::task::XAbortChannel> +{ + bool m_aborted; + css::uno::Reference<css::task::XAbortChannel> m_xNext; + +public: + inline AbortChannel() : m_aborted( false ) {} + inline static AbortChannel * get( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel ) + { return static_cast<AbortChannel *>(xAbortChannel.get()); } + + inline bool isAborted() const { return m_aborted; } + + // XAbortChannel + virtual void SAL_CALL sendAbort() throw (css::uno::RuntimeException); + + class SAL_DLLPRIVATE Chain + { + const ::rtl::Reference<AbortChannel> m_abortChannel; + public: + inline Chain( + ::rtl::Reference<AbortChannel> const & abortChannel, + css::uno::Reference<css::task::XAbortChannel> const & xNext ) + : m_abortChannel( abortChannel ) + { if (m_abortChannel.is()) m_abortChannel->m_xNext = xNext; } + inline ~Chain() + { if (m_abortChannel.is()) m_abortChannel->m_xNext.clear(); } + }; + friend class Chain; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_misc.h b/desktop/source/deployment/inc/dp_misc.h new file mode 100644 index 000000000000..bbf6d5274b39 --- /dev/null +++ b/desktop/source/deployment/inc/dp_misc.h @@ -0,0 +1,182 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_MISC_H +#define INCLUDED_DP_MISC_H + +#include "rtl/ustrbuf.hxx" +#include "rtl/instance.hxx" +#include "osl/mutex.hxx" +#include "osl/process.h" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/lang/XComponent.hpp" +#include "com/sun/star/lang/DisposedException.hpp" +#include "com/sun/star/deployment/XPackageRegistry.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/awt/XWindow.hpp" +#include "dp_misc_api.hxx" + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) +#define ARLEN(x) (sizeof (x) / sizeof *(x)) + +namespace dp_misc { + +const sal_Char CR = 0x0d; +const sal_Char LF = 0x0a; + +//============================================================================== +class MutexHolder +{ + mutable ::osl::Mutex m_mutex; +protected: + inline ::osl::Mutex & getMutex() const { return m_mutex; } +}; + +//============================================================================== +inline void try_dispose( ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> const & x ) +{ + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent> xComp( x, ::com::sun::star::uno::UNO_QUERY ); + if (xComp.is()) + xComp->dispose(); +} + +//############################################################################## + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::rtl::OUString expandUnoRcTerm( ::rtl::OUString const & term ); + +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::rtl::OUString makeRcTerm( ::rtl::OUString const & url ); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::rtl::OUString expandUnoRcUrl( ::rtl::OUString const & url ); + +//============================================================================== + +/** appends a relative path to a url. + + The relative path must already be correctly encoded for use in an URL. + If the URL starts with vnd.sun.star.expand then the relative path will + be again encoded for use in an "expand" URL. + */ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString makeURL( + ::rtl::OUString const & baseURL, ::rtl::OUString const & relPath ); + + +/** appends a relative path to a url. + + This is the same as makeURL, but the relative Path must me a segment + of an system path. + */ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString makeURLAppendSysPathSegment( + ::rtl::OUString const & baseURL, ::rtl::OUString const & relPath ); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString generateRandomPipeId(); + +class AbortChannel; +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> resolveUnoURL( + ::rtl::OUString const & connectString, + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext> const & xLocalContext, + AbortChannel * abortChannel = 0 ); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool office_is_running(); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +oslProcess raiseProcess( ::rtl::OUString const & appURL, + ::com::sun::star::uno::Sequence< ::rtl::OUString > const & args ); + +//============================================================================== + +/** writes the argument string to the console. + On Linux/Unix/etc. it converts the UTF16 string to an ANSI string using + osl_getThreadTextEncoding() as target encoding. On Windows it uses WriteFile + with the standard out stream. unopkg.com reads the data and prints them out using + WriteConsoleW. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +void writeConsole(::rtl::OUString const & sText); + +/** writes the argument string to the console. + On Linux/Unix/etc. the string is passed into fprintf without any conversion. + On Windows the string is converted to UTF16 assuming the argument is UTF8 + encoded. The UTF16 string is written to stdout with WriteFile. unopkg.com + reads the data and prints them out using WriteConsoleW. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +void writeConsole(::rtl::OString const & sText); + +/** writes the argument to the console using the error stream. + Otherwise the same as writeConsole. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +void writeConsoleError(::rtl::OUString const & sText); + + +/** writes the argument to the console using the error stream. + Otherwise the same as writeConsole. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +void writeConsoleError(::rtl::OString const & sText); + + +/** reads from the console. + On Linux/Unix/etc. it uses fgets to read char values and converts them to OUString + using osl_getThreadTextEncoding as target encoding. The returned string has a maximum + size of 1024 and does NOT include leading and trailing white space(applied OUString::trim()) +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::rtl::OUString readConsole(); + +/** print the text to the console in a debug build. + The argument is forwarded to writeConsole. The function does not add new line. + The code is only executed if OSL_DEBUG_LEVEL > 1 +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +void TRACE(::rtl::OUString const & sText); +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +void TRACE(::rtl::OString const & sText); + +/** registers or revokes shared or bundled extensions which have been + recently added or removed. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +void syncRepositories(::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment> const & xCmdEnv); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_misc.mk b/desktop/source/deployment/inc/dp_misc.mk new file mode 100644 index 000000000000..829a6bb96bbf --- /dev/null +++ b/desktop/source/deployment/inc/dp_misc.mk @@ -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. +# +#************************************************************************* + +# To be included after settings.mk + +# Although the deployment shared library is a UNO component, it also exports +# some C++ functionality: +.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 diff --git a/desktop/source/deployment/inc/dp_misc_api.hxx b/desktop/source/deployment/inc/dp_misc_api.hxx new file mode 100644 index 000000000000..bc2cee1df2b6 --- /dev/null +++ b/desktop/source/deployment/inc/dp_misc_api.hxx @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_DEPLOYMENT_INC_DP_MISC_API_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_INC_DP_MISC_API_HXX + +#include "sal/config.h" +#include "sal/types.h" + +#if defined DESKTOP_DEPLOYMENTMISC_DLLIMPLEMENTATION +#define DESKTOP_DEPLOYMENTMISC_DLLPUBLIC SAL_DLLPUBLIC_EXPORT +#else +#define DESKTOP_DEPLOYMENTMISC_DLLPUBLIC SAL_DLLPUBLIC_IMPORT +#endif + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_persmap.h b/desktop/source/deployment/inc/dp_persmap.h new file mode 100644 index 000000000000..b1597f3bb5d3 --- /dev/null +++ b/desktop/source/deployment/inc/dp_persmap.h @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_PERSMAP_H +#define INCLUDED_DP_PERSMAP_H + +#include "rtl/ustring.hxx" +#include "db.hxx" +#include <hash_map> + +using namespace berkeleydbproxy; + +namespace dp_misc +{ + +typedef ::std::hash_map< + ::rtl::OString, ::rtl::OString, ::rtl::OStringHash > t_string2string_map; + +//============================================================================== +class PersistentMap +{ + ::rtl::OUString m_sysPath; + mutable Db m_db; + void throw_rtexc( int err, char const * msg = 0 ) const; + +public: + ~PersistentMap(); + PersistentMap( ::rtl::OUString const & url, bool readOnly ); + /** in mem db */ + PersistentMap(); + + bool has( ::rtl::OString const & key ) const; + bool get( ::rtl::OString * value, ::rtl::OString const & key ) const; + t_string2string_map getEntries() const; + void put( ::rtl::OString const & key, ::rtl::OString const & value ); + bool erase( ::rtl::OString const & key, bool flush_immediately = true ); +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_platform.hxx b/desktop/source/deployment/inc/dp_platform.hxx new file mode 100644 index 000000000000..f9773efa1a45 --- /dev/null +++ b/desktop/source/deployment/inc/dp_platform.hxx @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_PLATFORM_HXX +#define INCLUDED_DP_PLATFORM_HXX + + +#include "dp_misc_api.hxx" + +#include "com/sun/star/uno/Sequence.hxx" +#include "rtl/ustring.hxx" + +namespace dp_misc +{ + + +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString const & getPlatformString(); + +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC + bool platform_fits( ::rtl::OUString const & platform_string ); + +/** determines if the current platform corresponds to one of the platform strings. + +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +bool hasValidPlatform( ::com::sun::star::uno::Sequence< ::rtl::OUString > const & platformStrings); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_resource.h b/desktop/source/deployment/inc/dp_resource.h new file mode 100644 index 000000000000..96fd0492072f --- /dev/null +++ b/desktop/source/deployment/inc/dp_resource.h @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_RESOURCE_H +#define INCLUDED_DP_RESOURCE_H + +#include "tools/resmgr.hxx" +#include "tools/string.hxx" +#include "tools/resid.hxx" +#include "com/sun/star/lang/Locale.hpp" +#include "dp_misc.h" +#include <memory> +#include "dp_misc_api.hxx" + +namespace dp_misc { + +//============================================================================== +ResId getResId( USHORT id ); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC String getResourceString( USHORT id ); + +template <typename Unique, USHORT id> +struct StaticResourceString : + public ::rtl::StaticWithInit<const ::rtl::OUString, Unique> { + const ::rtl::OUString operator () () { return getResourceString(id); } +}; + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::com::sun::star::lang::Locale toLocale( ::rtl::OUString const & slang ); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::com::sun::star::lang::Locale getOfficeLocale(); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::rtl::OUString getOfficeLocaleString(); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_ucb.h b/desktop/source/deployment/inc/dp_ucb.h new file mode 100644 index 000000000000..c2fcdcd7e09c --- /dev/null +++ b/desktop/source/deployment/inc/dp_ucb.h @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_UCB_H +#define INCLUDED_DP_UCB_H + +#include <list> +#include "rtl/byteseq.hxx" +#include "rtl/instance.hxx" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "dp_misc_api.hxx" + +namespace ucbhelper +{ +class Content; +} + +namespace css = ::com::sun::star; + +namespace dp_misc { + +struct DESKTOP_DEPLOYMENTMISC_DLLPUBLIC StrTitle : + public rtl::StaticWithInit<const rtl::OUString, StrTitle> +{ + const rtl::OUString operator () (); +}; + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool create_ucb_content( + ::ucbhelper::Content * ucb_content, + ::rtl::OUString const & url, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + bool throw_exc = true ); + +//============================================================================== +/** @return true if previously non-existing folder has been created + */ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool create_folder( + ::ucbhelper::Content * ucb_content, + ::rtl::OUString const & url, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + bool throw_exc = true ); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool erase_path( + ::rtl::OUString const & url, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + bool throw_exc = true ); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::rtl::ByteSequence readFile( ::ucbhelper::Content & ucb_content ); + +//============================================================================== +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +bool readLine( ::rtl::OUString * res, ::rtl::OUString const & startingWith, + ::ucbhelper::Content & ucb_content, rtl_TextEncoding textenc ); + +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +bool readProperties( ::std::list< ::std::pair< ::rtl::OUString, ::rtl::OUString> > & out_result, + ::ucbhelper::Content & ucb_content); + + + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_update.hxx b/desktop/source/deployment/inc/dp_update.hxx new file mode 100644 index 000000000000..6d0c79026367 --- /dev/null +++ b/desktop/source/deployment/inc/dp_update.hxx @@ -0,0 +1,150 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_UPDATE_HXX +#define INCLUDED_DP_UPDATE_HXX + + +#include "com/sun/star/deployment/XPackage.hpp" +#include "com/sun/star/deployment/XExtensionManager.hpp" +#include "com/sun/star/deployment/XUpdateInformationProvider.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/dom/XNode.hpp" + +#include "rtl/ustrbuf.hxx" +#include "dp_misc_api.hxx" + +#include <map> +#include <vector> + +namespace dp_misc { + +/** returns the default update URL (for the update information) which + is used when an extension does not provide its own URL. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::rtl::OUString getExtensionDefaultUpdateURL(); + +enum UPDATE_SOURCE +{ + UPDATE_SOURCE_NONE, + UPDATE_SOURCE_SHARED, + UPDATE_SOURCE_BUNDLED, + UPDATE_SOURCE_ONLINE +}; + +/* determine if an update is available which is installed in the + user repository. + + If the return value is UPDATE_SOURCE_NONE, then no update is + available, otherwise the return value determine from which the + repository the update is used. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +UPDATE_SOURCE isUpdateUserExtension( + bool bReadOnlyShared, + ::rtl::OUString const & userVersion, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion); + +/* determine if an update is available which is installed in the + shared repository. + + If the return value is UPDATE_SOURCE_NONE, then no update is + available, otherwise the return value determine from which the + repository the update is used. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +UPDATE_SOURCE isUpdateSharedExtension( + bool bReadOnlyShared, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion); + +/* determines the extension with the highest identifier and returns it + + */ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage> +getExtensionWithHighestVersion( + ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Reference< + ::com::sun::star::deployment::XPackage> > const & seqExtensionsWithSameId); + + +struct UpdateInfo +{ + UpdateInfo( ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage> const & ext); + ::com::sun::star::uno::Reference< + ::com::sun::star::deployment::XPackage> extension; +//version of the update + ::rtl::OUString version; + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > info; +}; + +typedef std::map< ::rtl::OUString, UpdateInfo > UpdateInfoMap; + +/* + @param extensionList + List of extension for which online update information are to be obtained. If NULL, then + for update information are obtained for all installed extension. There may be only one extension + with a particular identifier contained in the list. If one extension is installed + in several repositories, then the one with the highest version must be used, because it contains + the more recent URLs for getting the update information (if at all). + @param out_errors + the first member of the pair is the extension and the second the exception that was produced + when processing the extension. + + @return + A map of UpdateInfo instances. If the parameter extensionList was given, then the map contains + at only information for those extensions. + */ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +UpdateInfoMap getOnlineUpdateInfos( + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext> const &xContext, + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XExtensionManager> const & xExtMgr, + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XUpdateInformationProvider > const & updateInformation, + std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > > const * extensionList, + ::std::vector< ::std::pair< ::com::sun::star::uno::Reference< + ::com::sun::star::deployment::XPackage>, ::com::sun::star::uno::Any> > & out_errors); + +/* retunrs the highest version from the provided arguments. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::rtl::OUString getHighestVersion( + ::rtl::OUString const & userVersion, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_version.hxx b/desktop/source/deployment/inc/dp_version.hxx new file mode 100644 index 000000000000..c3491a7451de --- /dev/null +++ b/desktop/source/deployment/inc/dp_version.hxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_DEPLOYMENT_INC_DP_VERSION_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_INC_DP_VERSION_HXX + +#include "sal/config.h" +#include "com/sun/star/uno/Reference.hxx" +#include "dp_misc_api.hxx" + +namespace com { namespace sun { namespace star { namespace deployment { + class XPackage; +} } } } +namespace rtl { class OUString; } + +namespace dp_misc { + +enum Order { LESS, EQUAL, GREATER }; + +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC Order compareVersions( + ::rtl::OUString const & version1, ::rtl::OUString const & version2); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/inc/dp_xml.h b/desktop/source/deployment/inc/dp_xml.h new file mode 100644 index 000000000000..376df332fbf3 --- /dev/null +++ b/desktop/source/deployment/inc/dp_xml.h @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_XML_H +#define INCLUDED_DP_XML_H + +#include "rtl/ref.hxx" +#include "rtl/ustrbuf.hxx" +#include "cppuhelper/implbase1.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/input/XRoot.hpp" +#include "com/sun/star/xml/sax/XDocumentHandler.hpp" + + +namespace ucbhelper +{ +class Content; +} + +namespace css = ::com::sun::star; + +namespace dp_misc +{ + +//============================================================================== +void xml_parse( + css::uno::Reference< css::xml::sax::XDocumentHandler > const & xDocHandler, + ::ucbhelper::Content & ucb_content, + css::uno::Reference< css::uno::XComponentContext > const & xContext ); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/makefile.mk b/desktop/source/deployment/makefile.mk new file mode 100644 index 000000000000..6d83a5c1004b --- /dev/null +++ b/desktop/source/deployment/makefile.mk @@ -0,0 +1,112 @@ +#************************************************************************* +# +# 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 = deployment +ENABLE_EXCEPTIONS = TRUE +#USE_DEFFILE = TRUE +NO_BSYMBOLIC = TRUE + +.IF "$(GUI)"=="OS2" +TARGET = deploy +.ENDIF + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/source$/deployment$/inc$/dp_misc.mk + +.IF "$(SYSTEM_DB)" == "YES" +CFLAGS+=-DSYSTEM_DB -I$(DB_INCLUDES) +.ENDIF + +INCPRE += inc + +DLLPRE = + +SHL1TARGET = $(TARGET)$(DLLPOSTFIX).uno +SHL1VERSIONMAP = $(SOLARENV)/src/component.map + +SHL1LIBS = \ + $(SLB)$/deployment_manager.lib \ + $(SLB)$/deployment_registry.lib \ + $(SLB)$/deployment_registry_executable.lib \ + $(SLB)$/deployment_registry_component.lib \ + $(SLB)$/deployment_registry_configuration.lib \ + $(SLB)$/deployment_registry_package.lib \ + $(SLB)$/deployment_registry_script.lib \ + $(SLB)$/deployment_registry_sfwk.lib \ + $(SLB)$/deployment_registry_help.lib + +SHL1OBJS = \ + $(SLO)$/dp_log.obj \ + $(SLO)$/dp_persmap.obj \ + $(SLO)$/dp_services.obj \ + $(SLO)$/dp_xml.obj + +SHL1STDLIBS = \ + $(SALLIB) \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(UCBHELPERLIB) \ + $(COMPHELPERLIB) \ + $(TOOLSLIB) \ + $(XMLSCRIPTLIB) \ + $(SVLLIB) \ + $(UNOTOOLSLIB) \ + $(DEPLOYMENTMISCLIB) \ + $(HELPLINKERLIB) + +SHL1DEPN = +SHL1IMPLIB = i$(TARGET) +SHL1DEF = $(MISC)$/$(SHL1TARGET).def + +DEF1NAME = $(SHL1TARGET) + +SLOFILES = $(LIB1OBJFILES) + +RESLIB1NAME = $(TARGET) + +RESLIB1SRSFILES = \ + $(SRS)$/deployment_registry_configuration.srs \ + $(SRS)$/deployment_registry_component.srs \ + $(SRS)$/deployment_registry_script.srs \ + $(SRS)$/deployment_registry_sfwk.srs \ + $(SRS)$/deployment_registry_package.srs \ + $(SRS)$/deployment_registry_help.srs \ + $(SRS)$/deployment_registry.srs \ + $(SRS)$/deployment_manager.srs \ + $(SRS)$/deployment_unopkg.srs + +.IF "$(GUI)"=="OS2" +RESLIB1SRSFILES += $(SRS)$/deplmisc.srs +.ELSE +RESLIB1SRSFILES += $(SRS)$/deployment_misc.srs +.ENDIF + +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/manager/dp_activepackages.cxx b/desktop/source/deployment/manager/dp_activepackages.cxx new file mode 100644 index 000000000000..950e46174d22 --- /dev/null +++ b/desktop/source/deployment/manager/dp_activepackages.cxx @@ -0,0 +1,209 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "precompiled_desktop.hxx" + +#include "sal/config.h" + +#include <cstddef> +#include <utility> +#include <vector> + +#include "osl/diagnose.h" +#include "rtl/strbuf.hxx" +#include "rtl/string.hxx" +#include "rtl/textenc.h" +#include "rtl/uri.h" +#include "rtl/uri.hxx" +#include "rtl/ustring.hxx" +#include <hash_map> + +#include "dp_identifier.hxx" +#include "dp_persmap.h" + +#include "dp_activepackages.hxx" + +// Old format of database entry: +// key: UTF8(filename) +// value: UTF8(tempname ";" mediatype) +// New format of database entry: +// key: 0xFF UTF8(identifier) +// value: UTF8(tempname) 0xFF UTF8(filename) 0xFF UTF8(mediatype) + +namespace { + +static char const separator = static_cast< char >( + static_cast< unsigned char >(0xFF)); + +static char const legacyPrefix[] = "org.openoffice.legacy."; + +::rtl::OString oldKey(::rtl::OUString const & fileName) { + return ::rtl::OUStringToOString(fileName, RTL_TEXTENCODING_UTF8); +} + +::rtl::OString newKey(::rtl::OUString const & id) { + ::rtl::OStringBuffer b; + b.append(separator); + b.append(::rtl::OUStringToOString(id, RTL_TEXTENCODING_UTF8)); + return b.makeStringAndClear(); +} + +::dp_manager::ActivePackages::Data decodeOldData( + ::rtl::OUString const & fileName, ::rtl::OString const & value) +{ + ::dp_manager::ActivePackages::Data d; + sal_Int32 i = value.indexOf(';'); + OSL_ASSERT(i >= 0); + d.temporaryName = ::rtl::OUString(value.getStr(), i, RTL_TEXTENCODING_UTF8); + d.fileName = fileName; + d.mediaType = ::rtl::OUString( + value.getStr() + i + 1, value.getLength() - i - 1, + RTL_TEXTENCODING_UTF8); + return d; +} + +::dp_manager::ActivePackages::Data decodeNewData(::rtl::OString const & value) { + ::dp_manager::ActivePackages::Data d; + sal_Int32 i1 = value.indexOf(separator); + OSL_ASSERT(i1 >= 0); + d.temporaryName = ::rtl::OUString( + value.getStr(), i1, RTL_TEXTENCODING_UTF8); + sal_Int32 i2 = value.indexOf(separator, i1 + 1); + OSL_ASSERT(i2 >= 0); + d.fileName = ::rtl::OUString( + value.getStr() + i1 + 1, i2 - i1 - 1, RTL_TEXTENCODING_UTF8); + sal_Int32 i3 = value.indexOf(separator, i2 + 1); + + if (i3 < 0) + { + //Before ActivePackages::Data::version was added + d.mediaType = ::rtl::OUString( + value.getStr() + i2 + 1, value.getLength() - i2 - 1, + RTL_TEXTENCODING_UTF8); + } + else + { + sal_Int32 i4 = value.indexOf(separator, i3 + 1); + d.mediaType = ::rtl::OUString( + value.getStr() + i2 + 1, i3 - i2 -1, RTL_TEXTENCODING_UTF8); + d.version = ::rtl::OUString( + value.getStr() + i3 + 1, i4 - i3 - 1, + RTL_TEXTENCODING_UTF8); + d.failedPrerequisites = ::rtl::OUString( + value.getStr() + i4 + 1, value.getLength() - i4 - 1, + RTL_TEXTENCODING_UTF8); + } + return d; +} + +} + +namespace dp_manager { + +ActivePackages::ActivePackages() {} + +ActivePackages::ActivePackages(::rtl::OUString const & url, bool readOnly): + m_map(url, readOnly) {} + +ActivePackages::~ActivePackages() {} + +bool ActivePackages::has( + ::rtl::OUString const & id, ::rtl::OUString const & fileName) const +{ + return get(NULL, id, fileName); +} + +bool ActivePackages::get( + Data * data, ::rtl::OUString const & id, ::rtl::OUString const & fileName) + const +{ + ::rtl::OString v; + if (m_map.get(&v, newKey(id))) { + if (data != NULL) { + *data = decodeNewData(v); + } + return true; + } else if (m_map.get(&v, oldKey(fileName))) { + if (data != NULL) { + *data = decodeOldData(fileName, v); + } + return true; + } else { + return false; + } +} + +ActivePackages::Entries ActivePackages::getEntries() const { + Entries es; + ::dp_misc::t_string2string_map m(m_map.getEntries()); + for (::dp_misc::t_string2string_map::const_iterator i(m.begin()); + i != m.end(); ++i) + { + if (i->first.getLength() > 0 && i->first[0] == separator) { + es.push_back( + ::std::make_pair( + ::rtl::OUString( + i->first.getStr() + 1, i->first.getLength() - 1, + RTL_TEXTENCODING_UTF8), + decodeNewData(i->second))); + } else { + ::rtl::OUString fn( + ::rtl::OStringToOUString(i->first, RTL_TEXTENCODING_UTF8)); + es.push_back( + ::std::make_pair( + ::dp_misc::generateLegacyIdentifier(fn), + decodeOldData(fn, i->second))); + } + } + return es; +} + +void ActivePackages::put(::rtl::OUString const & id, Data const & data) { + ::rtl::OStringBuffer b; + b.append( + ::rtl::OUStringToOString(data.temporaryName, RTL_TEXTENCODING_UTF8)); + b.append(separator); + b.append(::rtl::OUStringToOString(data.fileName, RTL_TEXTENCODING_UTF8)); + b.append(separator); + b.append(::rtl::OUStringToOString(data.mediaType, RTL_TEXTENCODING_UTF8)); + b.append(separator); + b.append(::rtl::OUStringToOString(data.version, RTL_TEXTENCODING_UTF8)); + b.append(separator); + b.append(::rtl::OUStringToOString(data.failedPrerequisites, RTL_TEXTENCODING_UTF8)); + m_map.put(newKey(id), b.makeStringAndClear()); +} + +void ActivePackages::erase( + ::rtl::OUString const & id, ::rtl::OUString const & fileName) +{ + m_map.erase(newKey(id), true) || m_map.erase(oldKey(fileName), true); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_activepackages.hxx b/desktop/source/deployment/manager/dp_activepackages.hxx new file mode 100644 index 000000000000..569e4b7852d5 --- /dev/null +++ b/desktop/source/deployment/manager/dp_activepackages.hxx @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_DEPLOYMENT_MANAGER_DP_ACTIVEPACKAGES_HXX +#define INCLUDED_DESKTOP_SOURCE_DEPLOYMENT_MANAGER_DP_ACTIVEPACKAGES_HXX + +#include "sal/config.h" + +#include <utility> +#include <vector> + +#include "dp_persmap.h" + +namespace rtl { class OUString; } + +namespace dp_manager { + +class ActivePackages { +public: + struct Data { + Data(): failedPrerequisites(::rtl::OUString::valueOf((sal_Int32)0)) + {} + /* name of the temporary file (shared, user extension) or the name of + the folder of the bundled extension. + It does not contain the trailing '_' of the folder. + UTF-8 encoded + */ + ::rtl::OUString temporaryName; + /* The file name (shared, user) or the folder name (bundled) + If the key is the file name, then file name is not encoded. + If the key is the idendifier then the file name is UTF-8 encoded. + */ + ::rtl::OUString fileName; + ::rtl::OUString mediaType; + ::rtl::OUString version; + /* If this string contains the value according to + com::sun::star::deployment::Prerequisites or "0". That is, if + the value is > 0 then + the call to XPackage::checkPrerequisites failed. + In this case the extension must not be registered. + */ + ::rtl::OUString failedPrerequisites; + }; + + typedef ::std::vector< ::std::pair< ::rtl::OUString, Data > > Entries; + + ActivePackages(); + + ActivePackages(::rtl::OUString const & url, bool readOnly); + + ~ActivePackages(); + + bool has(::rtl::OUString const & id, ::rtl::OUString const & fileName) + const; + + bool get( + Data * data, ::rtl::OUString const & id, + ::rtl::OUString const & fileName) const; + + Entries getEntries() const; + + void put(::rtl::OUString const & id, Data const & value); + + void erase(::rtl::OUString const & id, ::rtl::OUString const & fileName); + +private: + ActivePackages(ActivePackages &); // not defined + void operator =(ActivePackages &); // not defined + + ::dp_misc::PersistentMap m_map; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_commandenvironments.cxx b/desktop/source/deployment/manager/dp_commandenvironments.cxx new file mode 100644 index 000000000000..ba32b3089805 --- /dev/null +++ b/desktop/source/deployment/manager/dp_commandenvironments.cxx @@ -0,0 +1,319 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "com/sun/star/deployment/VersionException.hpp" +#include "com/sun/star/deployment/LicenseException.hpp" +#include "com/sun/star/deployment/InstallException.hpp" +#include "com/sun/star/deployment/DependencyException.hpp" +#include "com/sun/star/deployment/PlatformException.hpp" +#include "com/sun/star/task/XInteractionApprove.hpp" +#include "com/sun/star/task/XInteractionAbort.hpp" +#include "com/sun/star/task/XInteractionHandler.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "dp_commandenvironments.hxx" + +namespace deployment = com::sun::star::deployment; +namespace lang = com::sun::star::lang; +namespace task = com::sun::star::task; +namespace ucb = com::sun::star::ucb; +namespace uno = com::sun::star::uno; +namespace css = com::sun::star; + +#define OUSTR(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) + +using ::com::sun::star::uno::Reference; +using ::rtl::OUString; + +namespace dp_manager { + +BaseCommandEnv::BaseCommandEnv() +{ +} + +BaseCommandEnv::BaseCommandEnv( + Reference< task::XInteractionHandler> const & handler) + : m_forwardHandler(handler) +{ +} + +BaseCommandEnv::~BaseCommandEnv() +{ +} +// XCommandEnvironment +//______________________________________________________________________________ +Reference<task::XInteractionHandler> BaseCommandEnv::getInteractionHandler() +throw (uno::RuntimeException) +{ + return this; +} + +//______________________________________________________________________________ +Reference<ucb::XProgressHandler> BaseCommandEnv::getProgressHandler() +throw (uno::RuntimeException) +{ + return this; +} + +void BaseCommandEnv::handle( + Reference< task::XInteractionRequest> const & /*xRequest*/ ) + throw (uno::RuntimeException) +{ +} + +void BaseCommandEnv::handle_(bool approve, bool abort, + Reference< task::XInteractionRequest> const & xRequest ) +{ + if (approve == false && abort == false) + { + //not handled so far -> forwarding + if (m_forwardHandler.is()) + m_forwardHandler->handle(xRequest); + else + return; //cannot handle + } + else + { + // select: + 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 (approve) { + Reference< task::XInteractionApprove > xInteractionApprove( + pConts[ pos ], uno::UNO_QUERY ); + if (xInteractionApprove.is()) { + xInteractionApprove->select(); + // don't query again for ongoing continuations: + approve = false; + } + } + else if (abort) { + Reference< task::XInteractionAbort > xInteractionAbort( + pConts[ pos ], uno::UNO_QUERY ); + if (xInteractionAbort.is()) { + xInteractionAbort->select(); + // don't query again for ongoing continuations: + abort = false; + } + } + } + } + +} + +// XProgressHandler +void BaseCommandEnv::push( uno::Any const & /*Status*/ ) +throw (uno::RuntimeException) +{ +} + +void BaseCommandEnv::update( uno::Any const & /*Status */) +throw (uno::RuntimeException) +{ +} + +void BaseCommandEnv::pop() throw (uno::RuntimeException) +{ +} +//============================================================================== + +TmpRepositoryCommandEnv::TmpRepositoryCommandEnv() +{ +} + +TmpRepositoryCommandEnv::TmpRepositoryCommandEnv( + css::uno::Reference< css::task::XInteractionHandler> const & handler): + BaseCommandEnv(handler) +{ +} +// XInteractionHandler +void TmpRepositoryCommandEnv::handle( + Reference< task::XInteractionRequest> const & xRequest ) + throw (uno::RuntimeException) +{ + uno::Any request( xRequest->getRequest() ); + OSL_ASSERT( request.getValueTypeClass() == uno::TypeClass_EXCEPTION ); + + deployment::VersionException verExc; + deployment::LicenseException licExc; + deployment::InstallException instExc; + + bool approve = false; + bool abort = false; + + if ((request >>= verExc) + || (request >>= licExc) + || (request >>= instExc)) + { + approve = true; + } + + handle_(approve, abort, xRequest); +} +//================================================================================ + +LicenseCommandEnv::LicenseCommandEnv( + css::uno::Reference< css::task::XInteractionHandler> const & handler, + bool bSuppressLicense, + OUString const & repository): + BaseCommandEnv(handler), m_repository(repository), + m_bSuppressLicense(bSuppressLicense) +{ +} +// XInteractionHandler +void LicenseCommandEnv::handle( + Reference< task::XInteractionRequest> const & xRequest ) + throw (uno::RuntimeException) +{ + uno::Any request( xRequest->getRequest() ); + OSL_ASSERT( request.getValueTypeClass() == uno::TypeClass_EXCEPTION ); + + deployment::LicenseException licExc; + + bool approve = false; + bool abort = false; + + if (request >>= licExc) + { + if (m_bSuppressLicense + || m_repository.equals(OUSTR("bundled")) + || licExc.AcceptBy.equals(OUSTR("admin"))) + { + //always approve in bundled case, because we do not support + //showing licenses anyway. + //The "admin" already accepted the license when installing the + // shared extension + approve = true; + } + } + + handle_(approve, abort, xRequest); +} + +//================================================================================ +//================================================================================ + +NoLicenseCommandEnv::NoLicenseCommandEnv( + css::uno::Reference< css::task::XInteractionHandler> const & handler): + BaseCommandEnv(handler) +{ +} +// XInteractionHandler +void NoLicenseCommandEnv::handle( + Reference< task::XInteractionRequest> const & xRequest ) + throw (uno::RuntimeException) +{ + uno::Any request( xRequest->getRequest() ); + OSL_ASSERT( request.getValueTypeClass() == uno::TypeClass_EXCEPTION ); + + deployment::LicenseException licExc; + + bool approve = false; + bool abort = false; + + if (request >>= licExc) + { + approve = true; + } + handle_(approve, abort, xRequest); +} + +// SilentCheckPrerequisitesCommandEnv::SilentCheckPrerequisitesCommandEnv( +// css::uno::Reference< css::task::XInteractionHandler> const & handler): +// BaseCommandEnv(handler) +// { +// } +SilentCheckPrerequisitesCommandEnv::SilentCheckPrerequisitesCommandEnv() +{ +} + +void SilentCheckPrerequisitesCommandEnv::handle( + Reference< task::XInteractionRequest> const & xRequest ) + throw (uno::RuntimeException) +{ + uno::Any request( xRequest->getRequest() ); + OSL_ASSERT( request.getValueTypeClass() == uno::TypeClass_EXCEPTION ); + + deployment::LicenseException licExc; + deployment::PlatformException platformExc; + deployment::DependencyException depExc; + bool approve = false; + bool abort = false; + + if (request >>= licExc) + { + approve = true; + handle_(approve, abort, xRequest); + } + else if ((request >>= platformExc) + || (request >>= depExc)) + { + m_Exception = request; + } + else + { + m_UnknownException = request; + } +} +// NoExceptionCommandEnv::NoExceptionCommandEnv( +// css::uno::Reference< css::task::XInteractionHandler> const & handler, +// css::uno::Type const & type): +// BaseCommandEnv(handler), +// m_type(type) +// { +// } +// // XInteractionHandler +// void NoExceptionCommandEnv::handle( +// Reference< task::XInteractionRequest> const & xRequest ) +// throw (uno::RuntimeException) +// { +// uno::Any request( xRequest->getRequest() ); +// OSL_ASSERT( request.getValueTypeClass() == uno::TypeClass_EXCEPTION ); + +// deployment::LicenseException licExc; + +// bool approve = false; +// bool abort = false; + +// if (request.getValueType() == m_type) +// { +// approve = true; +// } +// handle_(approve, abort, xRequest); +// } + +} // namespace dp_manager + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_commandenvironments.hxx b/desktop/source/deployment/manager/dp_commandenvironments.hxx new file mode 100644 index 000000000000..da64628792bd --- /dev/null +++ b/desktop/source/deployment/manager/dp_commandenvironments.hxx @@ -0,0 +1,177 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_COMMANDENVIRONMENTS_HXX +#define INCLUDED_DP_COMMANDENVIRONMENTS_HXX + +#include "cppuhelper/compbase3.hxx" +#include "ucbhelper/content.hxx" +#include "com/sun/star/uno/Type.hxx" + +namespace css = ::com::sun::star; + +namespace dp_manager { + +/** + This command environment is to be used when an extension is temporarily + stored in the "tmp" repository. It prevents all kind of user interaction. + */ +class BaseCommandEnv + : public ::cppu::WeakImplHelper3< css::ucb::XCommandEnvironment, + css::task::XInteractionHandler, + css::ucb::XProgressHandler > +{ +protected: + css::uno::Reference< css::uno::XComponentContext > m_xContext; + css::uno::Reference< css::task::XInteractionHandler> m_forwardHandler; + + void handle_(bool approve, bool abort, + css::uno::Reference< css::task::XInteractionRequest> const & xRequest ); +public: + virtual ~BaseCommandEnv(); + BaseCommandEnv(); + BaseCommandEnv( + css::uno::Reference< css::task::XInteractionHandler> const & handler); + + // XCommandEnvironment + virtual css::uno::Reference<css::task::XInteractionHandler > SAL_CALL + getInteractionHandler() throw (css::uno::RuntimeException); + virtual css::uno::Reference<css::ucb::XProgressHandler > + SAL_CALL getProgressHandler() throw (css::uno::RuntimeException); + + // XInteractionHandler + virtual void SAL_CALL handle( + css::uno::Reference<css::task::XInteractionRequest > const & xRequest ) + throw (css::uno::RuntimeException); + + // XProgressHandler + virtual void SAL_CALL push( css::uno::Any const & Status ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL update( css::uno::Any const & Status ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL pop() throw (css::uno::RuntimeException); +}; + +class TmpRepositoryCommandEnv : public BaseCommandEnv +{ +public: + TmpRepositoryCommandEnv(); + TmpRepositoryCommandEnv(css::uno::Reference< css::task::XInteractionHandler> const & handler); + +// XInteractionHandler + virtual void SAL_CALL handle( + css::uno::Reference<css::task::XInteractionRequest > const & xRequest ) + throw (css::uno::RuntimeException); + +}; + +/** this class is for use in XPackageManager::synchronize. + + It handles particular license cases. + */ +class LicenseCommandEnv : public BaseCommandEnv +{ +private: + ::rtl::OUString m_repository; + bool m_bSuppressLicense; +public: + LicenseCommandEnv(){}; + LicenseCommandEnv( + css::uno::Reference< css::task::XInteractionHandler> const & handler, + bool bSuppressLicense, + ::rtl::OUString const & repository); + +// XInteractionHandler + virtual void SAL_CALL handle( + css::uno::Reference<css::task::XInteractionRequest > const & xRequest ) + throw (css::uno::RuntimeException); + +}; + +/** this class is for use in XPackageManager::checkPrerequisites + + It always prohibits a license interaction + */ +class NoLicenseCommandEnv : public BaseCommandEnv +{ + +public: + NoLicenseCommandEnv(){}; + NoLicenseCommandEnv(css::uno::Reference< css::task::XInteractionHandler> const & handler); + +// XInteractionHandler + virtual void SAL_CALL handle( + css::uno::Reference<css::task::XInteractionRequest > const & xRequest ) + throw (css::uno::RuntimeException); + +}; + +/* For use in XExtensionManager::addExtension in the call to + XPackage::checkPrerequisites + It prevents all user interactions. The license is always accepted. + It remembers if there was a platform or a dependency exception in + the member m_bException. if there was any other exception then m_bUnknownException + is set. + + */ +class SilentCheckPrerequisitesCommandEnv : public BaseCommandEnv +{ +public: + SilentCheckPrerequisitesCommandEnv(); + // XInteractionHandler + virtual void SAL_CALL handle( + css::uno::Reference<css::task::XInteractionRequest > const & xRequest ) + throw (css::uno::RuntimeException); + + // Set to true if a PlatformException or a DependencyException were handled. + css::uno::Any m_Exception; + // Set to true if an unknown exception was handled. + css::uno::Any m_UnknownException; +}; + +// class NoExceptionCommandEnv : public BaseCommandEnv +// { +// css::uno::Type m_type; +// public: +// NoExceptionCommandEnv::NoExceptionCommandEnv(){}; +// NoExceptionCommandEnv::NoExceptionCommandEnv( +// css::uno::Reference< css::task::XInteractionHandler> const & handler, +// css::uno::Type const & type); + +// // XInteractionHandler +// virtual void SAL_CALL handle( +// css::uno::Reference<css::task::XInteractionRequest > const & xRequest ) +// throw (css::uno::RuntimeException); + +// }; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_extensionmanager.cxx b/desktop/source/deployment/manager/dp_extensionmanager.cxx new file mode 100644 index 000000000000..11b38cdc8892 --- /dev/null +++ b/desktop/source/deployment/manager/dp_extensionmanager.cxx @@ -0,0 +1,1517 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 <cppuhelper/implbase1.hxx> + +#include "comphelper/servicedecl.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "rtl/bootstrap.hxx" +#include "com/sun/star/deployment/ExtensionManager.hpp" +#include "com/sun/star/deployment/XExtensionManager.hpp" +#include "com/sun/star/deployment/thePackageManagerFactory.hpp" +#include "com/sun/star/deployment/XPackageManager.hpp" +#include "com/sun/star/deployment/XPackageManagerFactory.hpp" +#include "com/sun/star/deployment/XPackage.hpp" +#include "com/sun/star/deployment/InstallException.hpp" +#include "com/sun/star/deployment/VersionException.hpp" +#include "com/sun/star/deployment/LicenseException.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" +#include "com/sun/star/beans/Optional.hpp" +#include "com/sun/star/task/XInteractionApprove.hpp" +#include "com/sun/star/beans/Ambiguous.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/io/XInputStream.hpp" +#include "com/sun/star/util/XModifyBroadcaster.hpp" +#include "comphelper/sequence.hxx" +#include "xmlscript/xml_helper.hxx" +#include "osl/diagnose.h" +#include "dp_interact.h" +#include "dp_resource.h" +#include "dp_ucb.h" +#include "dp_identifier.hxx" +#include "dp_descriptioninfoset.hxx" +#include "dp_extensionmanager.hxx" +#include "dp_commandenvironments.hxx" +#include "dp_properties.hxx" +#include "boost/bind.hpp" + +#include <list> +#include <hash_map> +#include <algorithm> + +namespace deploy = com::sun::star::deployment; +namespace lang = com::sun::star::lang; +namespace registry = com::sun::star::registry; +namespace task = com::sun::star::task; +namespace ucb = com::sun::star::ucb; +namespace uno = com::sun::star::uno; +namespace beans = com::sun::star::beans; +namespace util = com::sun::star::util; +namespace css = com::sun::star; + +//#define OUSTR(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) + +using ::com::sun::star::uno::Reference; +using ::rtl::OUString; + +namespace { + +struct CompIdentifiers +{ + bool operator() (::std::vector<Reference<deploy::XPackage> > const & a, + ::std::vector<Reference<deploy::XPackage> > const & b) + { + + if (getName(a).compareTo(getName(b)) < 0) + return true; + return false; + } + + OUString getName(::std::vector<Reference<deploy::XPackage> > const & a); +}; + +OUString CompIdentifiers::getName(::std::vector<Reference<deploy::XPackage> > const & a) +{ + OSL_ASSERT(a.size() == 3); + //get the first non-null reference + Reference<deploy::XPackage> extension; + ::std::vector<Reference<deploy::XPackage> >::const_iterator it = a.begin(); + for (; it != a.end(); it++) + { + if (it->is()) + { + extension = *it; + break; + } + } + OSL_ASSERT(extension.is()); + return extension->getDisplayName(); +} + +void writeLastModified(OUString & url, Reference<ucb::XCommandEnvironment> const & xCmdEnv) +{ + //Write the lastmodified file + try { + ::rtl::Bootstrap::expandMacros(url); + ::ucbhelper::Content ucbStamp(url, xCmdEnv ); + dp_misc::erase_path( url, xCmdEnv ); + ::rtl::OString stamp("1" ); + Reference<css::io::XInputStream> xData( + ::xmlscript::createInputStream( + ::rtl::ByteSequence( + reinterpret_cast<sal_Int8 const *>(stamp.getStr()), + stamp.getLength() ) ) ); + ucbStamp.writeStream( xData, true /* replace existing */ ); + } + catch(...) + { + uno::Any exc(::cppu::getCaughtException()); + throw deploy::DeploymentException( + OUSTR("Failed to update") + url, 0, exc); + } +} + +class ExtensionRemoveGuard +{ + css::uno::Reference<css::deployment::XPackage> m_extension; + css::uno::Reference<css::deployment::XPackageManager> m_xPackageManager; + +public: + ExtensionRemoveGuard( + css::uno::Reference<css::deployment::XPackage> const & extension, + css::uno::Reference<css::deployment::XPackageManager> const & xPackageManager): + m_extension(extension), m_xPackageManager(xPackageManager) {} + ~ExtensionRemoveGuard(); + + void reset(css::uno::Reference<css::deployment::XPackage> const & extension) { + m_extension = extension; + } +}; + +ExtensionRemoveGuard::~ExtensionRemoveGuard() +{ + try { + if (m_xPackageManager.is() && m_extension.is()) + m_xPackageManager->removePackage( + dp_misc::getIdentifier(m_extension), ::rtl::OUString(), + css::uno::Reference<css::task::XAbortChannel>(), + css::uno::Reference<css::ucb::XCommandEnvironment>()); + } catch (...) { + OSL_ASSERT(0); + } +} + +} //end namespace + +namespace dp_manager { + +//------------------------------------------------------------------------------ + +//ToDo: bundled extension +ExtensionManager::ExtensionManager( Reference< uno::XComponentContext > const& xContext) : + ::cppu::WeakComponentImplHelper1< css::deployment::XExtensionManager >(getMutex()), + m_xContext( xContext ) +{ + Reference<deploy::XPackageManagerFactory> xPackageManagerFactory( + deploy::thePackageManagerFactory::get(m_xContext)); + m_userRepository = xPackageManagerFactory->getPackageManager(OUSTR("user")); + m_sharedRepository = xPackageManagerFactory->getPackageManager(OUSTR("shared")); + m_bundledRepository = xPackageManagerFactory->getPackageManager(OUSTR("bundled")); + m_tmpRepository = xPackageManagerFactory->getPackageManager(OUSTR("tmp")); + + m_repositoryNames.push_back(OUSTR("user")); + m_repositoryNames.push_back(OUSTR("shared")); + m_repositoryNames.push_back(OUSTR("bundled")); +} + +//------------------------------------------------------------------------------ + +ExtensionManager::~ExtensionManager() +{ +} + +Reference<task::XAbortChannel> ExtensionManager::createAbortChannel() + throw (uno::RuntimeException) +{ + return new dp_misc::AbortChannel; +} + +css::uno::Reference<css::deployment::XPackageManager> +ExtensionManager::getPackageManager(::rtl::OUString const & repository) + throw (css::lang::IllegalArgumentException) +{ + Reference<deploy::XPackageManager> xPackageManager; + if (repository.equals(OUSTR("user"))) + xPackageManager = m_userRepository; + else if (repository.equals(OUSTR("shared"))) + xPackageManager = m_sharedRepository; + else if (repository.equals(OUSTR("bundled"))) + xPackageManager = m_bundledRepository; + else + throw lang::IllegalArgumentException( + OUSTR("No valid repository name provided."), + static_cast<cppu::OWeakObject*>(this), 0); + return xPackageManager; +} + +/* + Enters the XPackage objects into a map. They must be all from the + same repository. The value type of the map is a vector, where each vector + represents an extension with a particular identifier. The first member + is represents the user extension, the second the shared extension and the + third the bundled extension. + */ +void ExtensionManager::addExtensionsToMap( + id2extensions & mapExt, + uno::Sequence<Reference<deploy::XPackage> > const & seqExt, + OUString const & repository) +{ + //Determine the index in the vector where these extensions are to be + //added. + ::std::list<OUString>::const_iterator citNames = + m_repositoryNames.begin(); + int index = 0; + for (;citNames != m_repositoryNames.end(); citNames++, index++) + { + if (citNames->equals(repository)) + break; + } + + for (int i = 0; i < seqExt.getLength(); i++) + { + Reference<deploy::XPackage> const & xExtension = seqExt[i]; + OUString id = dp_misc::getIdentifier(xExtension); + id2extensions::iterator ivec = mapExt.find(id); + if (ivec == mapExt.end()) + { + ::std::vector<Reference<deploy::XPackage> > vec(3); + vec[index] = xExtension; + mapExt[id] = vec; + } + else + { + ivec->second[index] = xExtension; + } + } +} + +/* + returns a list containing extensions with the same identifier from + all repositories (user, shared, bundled) If one repository does not + have this extension, then the list contains an empty Referenc. The list + is ordered according to the priority of the repostories: + 1. user + 2. shared + 3. bundled + + The number of elements is always three, unless the number of repository + changes. + */ +::std::list<Reference<deploy::XPackage> > + ExtensionManager::getExtensionsWithSameId( + OUString const & identifier, OUString const & fileName, + Reference< ucb::XCommandEnvironment> const & /*xCmdEnv*/) + +{ + ::std::list<Reference<deploy::XPackage> > extensionList; + try + { //will throw an exception if the extension does not exist + extensionList.push_back(m_userRepository->getDeployedPackage( + identifier, fileName, Reference<ucb::XCommandEnvironment>())); + } catch(lang::IllegalArgumentException &) + { + extensionList.push_back(Reference<deploy::XPackage>()); + } + try + { + extensionList.push_back(m_sharedRepository->getDeployedPackage( + identifier, fileName, Reference<ucb::XCommandEnvironment>())); + } catch (lang::IllegalArgumentException &) + { + extensionList.push_back(Reference<deploy::XPackage>()); + } + try + { + extensionList.push_back(m_bundledRepository->getDeployedPackage( + identifier, fileName, Reference<ucb::XCommandEnvironment>())); + } catch (lang::IllegalArgumentException &) + { + extensionList.push_back(Reference<deploy::XPackage>()); + } + OSL_ASSERT(extensionList.size() == 3); + return extensionList; +} + +uno::Sequence<Reference<deploy::XPackage> > +ExtensionManager::getExtensionsWithSameIdentifier( + OUString const & identifier, + OUString const & fileName, + Reference< ucb::XCommandEnvironment> const & xCmdEnv ) + throw ( + deploy::DeploymentException, + ucb::CommandFailedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + try + { + ::std::list<Reference<deploy::XPackage> > listExtensions = + getExtensionsWithSameId( + identifier, fileName, xCmdEnv); + sal_Bool bHasExtension = false; + + //throw an IllegalArgumentException if there is no extension at all. + typedef ::std::list<Reference<deploy::XPackage> >::const_iterator CIT; + for (CIT i = listExtensions.begin(); i != listExtensions.end(); i++) + bHasExtension |= i->is(); + if (!bHasExtension) + throw lang::IllegalArgumentException( + OUSTR("Could not find extension: ") + identifier + OUSTR(", ") + fileName, + static_cast<cppu::OWeakObject*>(this), -1); + + return comphelper::containerToSequence< + Reference<deploy::XPackage>, + ::std::list<Reference<deploy::XPackage> > + > (listExtensions); + } + catch (deploy::DeploymentException & ) + { + throw; + } + catch ( ucb::CommandFailedException & ) + { + throw; + } + catch (lang::IllegalArgumentException &) + { + throw; + } + catch (...) + { + uno::Any exc = ::cppu::getCaughtException(); + throw deploy::DeploymentException( + OUSTR("Extension Manager: exception during getExtensionsWithSameIdentifier"), + static_cast<OWeakObject*>(this), exc); + } +} + +bool ExtensionManager::isUserDisabled( + OUString const & identifier, OUString const & fileName) +{ + ::std::list<Reference<deploy::XPackage> > listExtensions; + + try { + listExtensions = getExtensionsWithSameId(identifier, fileName); + } catch (lang::IllegalArgumentException & ) { + } + OSL_ASSERT(listExtensions.size() == 3); + + return isUserDisabled( ::comphelper::containerToSequence< + Reference<deploy::XPackage>, + ::std::list<Reference<deploy::XPackage> > + > (listExtensions)); +} + +bool ExtensionManager::isUserDisabled( + uno::Sequence<Reference<deploy::XPackage> > const & seqExtSameId) +{ + OSL_ASSERT(seqExtSameId.getLength() == 3); + Reference<deploy::XPackage> const & userExtension = seqExtSameId[0]; + if (userExtension.is()) + { + beans::Optional<beans::Ambiguous<sal_Bool> > reg = + userExtension->isRegistered(Reference<task::XAbortChannel>(), + Reference<ucb::XCommandEnvironment>()); + //If the value is ambiguous is than we assume that the extension + //is enabled, but something went wrong during enabling. We do not + //automatically disable user extensions. + if (reg.IsPresent && + ! reg.Value.IsAmbiguous && ! reg.Value.Value) + return true; + } + return false; +} + +/* + This method determines the active extension (XPackage.registerPackage) with a + particular identifier. + + The parameter bUserDisabled determines if the user extension is disabled. + + When the user repository contains an extension with the given identifier and + it is not disabled by the user, then it is always registered. Otherwise an + extension is only registered when there is no registered extension in one of + the repositories with a higher priority. That is, if the extension is from + the shared repository and an active extension with the same identifer is in + the user repository, then the extension is not registered. Similarly a + bundled extension is not registered if there is an active extension with the + same identifier in the shared or user repository. +*/ +void ExtensionManager::activateExtension( + OUString const & identifier, OUString const & fileName, + bool bUserDisabled, + bool bStartup, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + ::std::list<Reference<deploy::XPackage> > listExtensions; + try { + listExtensions = getExtensionsWithSameId(identifier, fileName); + } catch (lang::IllegalArgumentException &) { + } + OSL_ASSERT(listExtensions.size() == 3); + + activateExtension( + ::comphelper::containerToSequence< + Reference<deploy::XPackage>, + ::std::list<Reference<deploy::XPackage> > + > (listExtensions), + bUserDisabled, bStartup, xAbortChannel, xCmdEnv); + + fireModified(); +} + +void ExtensionManager::activateExtension( + uno::Sequence<Reference<deploy::XPackage> > const & seqExt, + bool bUserDisabled, + bool bStartup, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + bool bActive = false; + sal_Int32 len = seqExt.getLength(); + for (sal_Int32 i = 0; i < len; i++) + { + Reference<deploy::XPackage> const & aExt = seqExt[i]; + if (aExt.is()) + { + //get the registration value of the current iteration + beans::Optional<beans::Ambiguous<sal_Bool> > optReg = + aExt->isRegistered(xAbortChannel, xCmdEnv); + //If nothing can be registered then break + if (!optReg.IsPresent) + break; + + //Check if this is a disabled user extension, + if (i == 0 && bUserDisabled) + { + aExt->revokePackage(xAbortChannel, xCmdEnv); + continue; + } + + //If we have already determined an active extension then we must + //make sure to unregister all extensions with the same id in + //repositories with a lower priority + if (bActive) + { + aExt->revokePackage(xAbortChannel, xCmdEnv); + } + else + { + //This is the first extension in the ordered list, which becomes + //the active extension + bActive = true; + //Register if not already done. + //reregister if the value is ambiguous, which indicates that + //something went wrong during last registration. + aExt->registerPackage(bStartup, xAbortChannel, xCmdEnv); + } + } + } +} + +Reference<deploy::XPackage> ExtensionManager::backupExtension( + OUString const & identifier, OUString const & fileName, + Reference<deploy::XPackageManager> const & xPackageManager, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + Reference<deploy::XPackage> xBackup; + Reference<ucb::XCommandEnvironment> tmpCmdEnv( + new TmpRepositoryCommandEnv(xCmdEnv->getInteractionHandler())); + Reference<deploy::XPackage> xOldExtension; + xOldExtension = xPackageManager->getDeployedPackage( + identifier, fileName, tmpCmdEnv); + + if (xOldExtension.is()) + { + xBackup = m_tmpRepository->addPackage( + xOldExtension->getURL(), uno::Sequence<beans::NamedValue>(), + OUString(), Reference<task::XAbortChannel>(), tmpCmdEnv); + + OSL_ENSURE(xBackup.is(), "Failed to backup extension"); + } + return xBackup; +} + +//The supported package types are actually determined by the registry. However +//creating a registry +//(desktop/source/deployment/registry/dp_registry.cxx:PackageRegistryImpl) will +//create all the backends, so that the registry can obtain from them the package +//types. Creating the registry will also set up the registry folder containing +//all the subfolders for the respective backends. +//Because all repositories support the same backends, we can just delegate this +//call to one of the repositories. +uno::Sequence< Reference<deploy::XPackageTypeInfo> > +ExtensionManager::getSupportedPackageTypes() + throw (uno::RuntimeException) +{ + return m_userRepository->getSupportedPackageTypes(); +} +//Do some necessary checks and user interaction. This function does not +//aquire the extension manager mutex and that mutex must not be aquired +//when this function is called. doChecksForAddExtension does synchronous +//user interactions which may require aquiring the solar mutex. +//Returns true if the extension can be installed. +bool ExtensionManager::doChecksForAddExtension( + Reference<deploy::XPackageManager> const & xPackageMgr, + uno::Sequence<beans::NamedValue> const & properties, + css::uno::Reference<css::deployment::XPackage> const & xTmpExtension, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv, + Reference<deploy::XPackage> & out_existingExtension ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + try + { + Reference<deploy::XPackage> xOldExtension; + const OUString sIdentifier = dp_misc::getIdentifier(xTmpExtension); + const OUString sFileName = xTmpExtension->getName(); + const OUString sDisplayName = xTmpExtension->getDisplayName(); + const OUString sVersion = xTmpExtension->getVersion(); + + try + { + xOldExtension = xPackageMgr->getDeployedPackage( + sIdentifier, sFileName, xCmdEnv); + out_existingExtension = xOldExtension; + } + catch (lang::IllegalArgumentException &) + { + } + bool bCanInstall = false; + + //This part is not guarded against other threads removing, adding, disabling ... + //etc. the same extension. + //checkInstall is safe because it notifies the user if the extension is not yet + //installed in the same repository. Because addExtension has its own guard + //(m_addMutex), another thread cannot add the extension in the meantime. + //checkUpdate is called if the same extension exists in the same + //repository. The user is asked if they want to replace it. Another + //thread + //could already remove the extension. So asking the user was not + //necessary. No harm is done. The other thread may also ask the user + //if he wants to remove the extension. This depends on the + //XCommandEnvironment which it passes to removeExtension. + if (xOldExtension.is()) + { + //throws a CommandFailedException if the user cancels + //the action. + checkUpdate(sVersion, sDisplayName,xOldExtension, xCmdEnv); + } + else + { + //throws a CommandFailedException if the user cancels + //the action. + checkInstall(sDisplayName, xCmdEnv); + } + //Prevent showing the license if requested. + Reference<ucb::XCommandEnvironment> _xCmdEnv(xCmdEnv); + ExtensionProperties props(OUString(), properties, Reference<ucb::XCommandEnvironment>()); + + dp_misc::DescriptionInfoset info(dp_misc::getDescriptionInfoset(xTmpExtension->getURL())); + const ::boost::optional<dp_misc::SimpleLicenseAttributes> licenseAttributes = + info.getSimpleLicenseAttributes(); + + if (licenseAttributes && licenseAttributes->suppressIfRequired + && props.isSuppressedLicense()) + _xCmdEnv = Reference<ucb::XCommandEnvironment>( + new NoLicenseCommandEnv(xCmdEnv->getInteractionHandler())); + + bCanInstall = xTmpExtension->checkPrerequisites( + xAbortChannel, _xCmdEnv, xOldExtension.is() || props.isExtensionUpdate()) == 0 ? true : false; + + return bCanInstall; + } + catch (deploy::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (uno::Exception &) { + uno::Any excOccurred = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception in doChecksForAddExtension"), + static_cast<OWeakObject*>(this), excOccurred); + throw exc; + } catch (...) { + throw uno::RuntimeException( + OUSTR("Extension Manager: unexpected exception in doChecksForAddExtension"), + static_cast<OWeakObject*>(this)); + } +} + +// Only add to shared and user repository +Reference<deploy::XPackage> ExtensionManager::addExtension( + OUString const & url, uno::Sequence<beans::NamedValue> const & properties, + OUString const & repository, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + Reference<deploy::XPackage> xNewExtension; + //Determine the repository to use + Reference<deploy::XPackageManager> xPackageManager; + if (repository.equals(OUSTR("user"))) + xPackageManager = m_userRepository; + else if (repository.equals(OUSTR("shared"))) + xPackageManager = m_sharedRepository; + else + throw lang::IllegalArgumentException( + OUSTR("No valid repository name provided."), + static_cast<cppu::OWeakObject*>(this), 0); + //We must make sure that the xTmpExtension is not create twice, because this + //would remove the first one. + ::osl::MutexGuard addGuard(m_addMutex); + + Reference<deploy::XPackage> xTmpExtension = + getTempExtension(url, xAbortChannel, xCmdEnv); + //Make sure the extension is removed from the tmp repository in case + //of an exception + ExtensionRemoveGuard tmpExtensionRemoveGuard(xTmpExtension, m_tmpRepository); + const OUString sIdentifier = dp_misc::getIdentifier(xTmpExtension); + const OUString sFileName = xTmpExtension->getName(); + Reference<deploy::XPackage> xOldExtension; + Reference<deploy::XPackage> xExtensionBackup; + + uno::Any excOccurred2; + bool bUserDisabled = false; + bool bCanInstall = doChecksForAddExtension( + xPackageManager, + properties, + xTmpExtension, + xAbortChannel, + xCmdEnv, + xOldExtension ); + + { + // In this garded section (getMutex) we must not use the argument xCmdEnv + // because it may bring up dialogs (XInteractionHandler::handle) this + //may potententially deadlock. See issue + //http://qa.openoffice.org/issues/show_bug.cgi?id=114933 + //By not providing xCmdEnv the underlying APIs will throw an exception if + //the XInteractionRequest cannot be handled + ::osl::MutexGuard guard(getMutex()); + + if (bCanInstall) + { + try + { + bUserDisabled = isUserDisabled(sIdentifier, sFileName); + if (xOldExtension.is()) + { + try + { + xOldExtension->revokePackage( + xAbortChannel, Reference<ucb::XCommandEnvironment>()); + //save the old user extension in case the user aborts + //store the extension in the tmp repository, this will overwrite + //xTmpPackage (same identifier). Do not let the user abort or + //interact + //importing the old extension in the tmp repository will remove + //the xTmpExtension + //no command environment supplied, only this class shall interact + //with the user! + xExtensionBackup = m_tmpRepository->importExtension( + xOldExtension, Reference<task::XAbortChannel>(), + Reference<ucb::XCommandEnvironment>()); + tmpExtensionRemoveGuard.reset(xExtensionBackup); + //xTmpExtension will later be used to check the dependencies + //again. However, only xExtensionBackup will be later removed + //from the tmp repository + xTmpExtension = xExtensionBackup; + OSL_ASSERT(xTmpExtension.is()); + } + catch (lang::DisposedException &) + { + //Another thread might have removed the extension meanwhile + } + } + //check again dependencies but prevent user interaction, + //We can disregard the license, because the user must have already + //accepted it, whe we called checkPrerequisites the first time + SilentCheckPrerequisitesCommandEnv * pSilentCommandEnv = + new SilentCheckPrerequisitesCommandEnv(); + Reference<ucb::XCommandEnvironment> silentCommandEnv(pSilentCommandEnv); + + sal_Int32 failedPrereq = xTmpExtension->checkPrerequisites( + xAbortChannel, silentCommandEnv, true); + if (failedPrereq == 0) + { + xNewExtension = xPackageManager->addPackage( + url, properties, OUString(), xAbortChannel, + Reference<ucb::XCommandEnvironment>()); + //If we add a user extension and there is already one which was + //disabled by a user, then the newly installed one is enabled. If we + //add to another repository then the user extension remains + //disabled. + bool bUserDisabled2 = bUserDisabled; + if (repository.equals(OUSTR("user"))) + bUserDisabled2 = false; + + // pass the two values via variables to workaround gcc-4.3.4 specific bug (bnc#655912) + OUString sNewExtensionIdentifier = dp_misc::getIdentifier(xNewExtension); + OUString sNewExtensionFileName = xNewExtension->getName(); + + activateExtension( + sNewExtensionIdentifier, sNewExtensionFileName, + bUserDisabled2, false, xAbortChannel, + Reference<ucb::XCommandEnvironment>()); + } + else + { + if (pSilentCommandEnv->m_Exception.hasValue()) + ::cppu::throwException(pSilentCommandEnv->m_Exception); + else if ( pSilentCommandEnv->m_UnknownException.hasValue()) + ::cppu::throwException(pSilentCommandEnv->m_UnknownException); + else + throw deploy::DeploymentException ( + OUSTR("Extension Manager: exception during addExtension, ckeckPrerequisites failed"), + static_cast<OWeakObject*>(this), uno::Any()); + } + } + catch (deploy::DeploymentException& ) { + excOccurred2 = ::cppu::getCaughtException(); + } catch (ucb::CommandFailedException & ) { + excOccurred2 = ::cppu::getCaughtException(); + } catch (ucb::CommandAbortedException & ) { + excOccurred2 = ::cppu::getCaughtException(); + } catch (lang::IllegalArgumentException &) { + excOccurred2 = ::cppu::getCaughtException(); + } catch (uno::RuntimeException &) { + excOccurred2 = ::cppu::getCaughtException(); + } catch (...) { + excOccurred2 = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception during addExtension, url: ") + + url, static_cast<OWeakObject*>(this), excOccurred2); + excOccurred2 <<= exc; + } + } + + if (excOccurred2.hasValue()) + { + //It does not matter what exception is thrown. We try to + //recover the original status. + //If the user aborted installation then a ucb::CommandAbortedException + //is thrown. + //Use a private AbortChannel so the user cannot interrupt. + try + { + if (xExtensionBackup.is()) + { + Reference<deploy::XPackage> xRestored = + xPackageManager->importExtension( + xExtensionBackup, Reference<task::XAbortChannel>(), + Reference<ucb::XCommandEnvironment>()); + } + activateExtension( + sIdentifier, sFileName, bUserDisabled, false, + Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>()); + } + catch (...) + { + } + ::cppu::throwException(excOccurred2); + } + } // leaving the garded section (getMutex()) + + try + { + fireModified(); + + }catch (deploy::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (uno::Exception &) { + uno::Any excOccurred = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception in doChecksForAddExtension"), + static_cast<OWeakObject*>(this), excOccurred); + throw exc; + } catch (...) { + throw uno::RuntimeException( + OUSTR("Extension Manager: unexpected exception in doChecksForAddExtension"), + static_cast<OWeakObject*>(this)); + } + + return xNewExtension; +} + +void ExtensionManager::removeExtension( + OUString const & identifier, OUString const & fileName, + OUString const & repository, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + uno::Any excOccurred1; + Reference<deploy::XPackage> xExtensionBackup; + Reference<deploy::XPackageManager> xPackageManager; + bool bUserDisabled = false; + ::osl::MutexGuard guard(getMutex()); + try + { +//Determine the repository to use + if (repository.equals(OUSTR("user"))) + xPackageManager = m_userRepository; + else if (repository.equals(OUSTR("shared"))) + xPackageManager = m_sharedRepository; + else + throw lang::IllegalArgumentException( + OUSTR("No valid repository name provided."), + static_cast<cppu::OWeakObject*>(this), 0); + + bUserDisabled = isUserDisabled(identifier, fileName); + //Backup the extension, in case the user cancels the action + xExtensionBackup = backupExtension( + identifier, fileName, xPackageManager, xCmdEnv); + + //revoke the extension if it is active + Reference<deploy::XPackage> xOldExtension = + xPackageManager->getDeployedPackage( + identifier, fileName, xCmdEnv); + xOldExtension->revokePackage(xAbortChannel, xCmdEnv); + + xPackageManager->removePackage( + identifier, fileName, xAbortChannel, xCmdEnv); + activateExtension(identifier, fileName, bUserDisabled, false, + xAbortChannel, xCmdEnv); + fireModified(); + } + catch (deploy::DeploymentException& ) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (ucb::CommandFailedException & ) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (ucb::CommandAbortedException & ) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (lang::IllegalArgumentException &) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (uno::RuntimeException &) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (...) { + excOccurred1 = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception during removeEtension"), + static_cast<OWeakObject*>(this), excOccurred1); + excOccurred1 <<= exc; + } + + if (excOccurred1.hasValue()) + { + //User aborted installation, restore the previous situation. + //Use a private AbortChannel so the user cannot interrupt. + try + { + Reference<ucb::XCommandEnvironment> tmpCmdEnv( + new TmpRepositoryCommandEnv(xCmdEnv->getInteractionHandler())); + if (xExtensionBackup.is()) + { + Reference<deploy::XPackage> xRestored = + xPackageManager->importExtension( + xExtensionBackup, Reference<task::XAbortChannel>(), + tmpCmdEnv); + activateExtension( + identifier, fileName, bUserDisabled, false, + Reference<task::XAbortChannel>(), + tmpCmdEnv); + + m_tmpRepository->removePackage( + dp_misc::getIdentifier(xExtensionBackup), + xExtensionBackup->getName(), xAbortChannel, xCmdEnv); + fireModified(); + } + } + catch (...) + { + } + ::cppu::throwException(excOccurred1); + } + + if (xExtensionBackup.is()) + m_tmpRepository->removePackage( + dp_misc::getIdentifier(xExtensionBackup), + xExtensionBackup->getName(), xAbortChannel, xCmdEnv); +} + +// Only enable extensions from shared and user repository +void ExtensionManager::enableExtension( + Reference<deploy::XPackage> const & extension, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + ::osl::MutexGuard guard(getMutex()); + bool bUserDisabled = false; + uno::Any excOccurred; + try + { + if (!extension.is()) + return; + OUString repository = extension->getRepositoryName(); + if (!repository.equals(OUSTR("user"))) + throw lang::IllegalArgumentException( + OUSTR("No valid repository name provided."), + static_cast<cppu::OWeakObject*>(this), 0); + + bUserDisabled = isUserDisabled(dp_misc::getIdentifier(extension), + extension->getName()); + + activateExtension(dp_misc::getIdentifier(extension), + extension->getName(), false, false, + xAbortChannel, xCmdEnv); + } + catch (deploy::DeploymentException& ) { + excOccurred = ::cppu::getCaughtException(); + } catch (ucb::CommandFailedException & ) { + excOccurred = ::cppu::getCaughtException(); + } catch (ucb::CommandAbortedException & ) { + excOccurred = ::cppu::getCaughtException(); + } catch (lang::IllegalArgumentException &) { + excOccurred = ::cppu::getCaughtException(); + } catch (uno::RuntimeException &) { + excOccurred = ::cppu::getCaughtException(); + } catch (...) { + excOccurred = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception during enableExtension"), + static_cast<OWeakObject*>(this), excOccurred); + excOccurred <<= exc; + } + + if (excOccurred.hasValue()) + { + try + { + activateExtension(dp_misc::getIdentifier(extension), + extension->getName(), bUserDisabled, false, + xAbortChannel, xCmdEnv); + } + catch (...) + { + } + ::cppu::throwException(excOccurred); + } +} + +/** + */ +sal_Int32 ExtensionManager::checkPrerequisitesAndEnable( + Reference<deploy::XPackage> const & extension, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + try + { + if (!extension.is()) + return 0; + ::osl::MutexGuard guard(getMutex()); + sal_Int32 ret = 0; + Reference<deploy::XPackageManager> mgr = + getPackageManager(extension->getRepositoryName()); + ret = mgr->checkPrerequisites(extension, xAbortChannel, xCmdEnv); + if (ret) + { + //There are some unfulfilled prerequisites, try to revoke + extension->revokePackage(xAbortChannel, xCmdEnv); + } + const OUString id(dp_misc::getIdentifier(extension)); + activateExtension(id, extension->getName(), + isUserDisabled(id, extension->getName()), false, + xAbortChannel, xCmdEnv); + return ret; + } + catch (deploy::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (...) { + uno::Any excOccurred = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception during disableExtension"), + static_cast<OWeakObject*>(this), excOccurred); + throw exc; + } +} + +void ExtensionManager::disableExtension( + Reference<deploy::XPackage> const & extension, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + ::osl::MutexGuard guard(getMutex()); + uno::Any excOccurred; + bool bUserDisabled = false; + try + { + if (!extension.is()) + return; + const OUString repository( extension->getRepositoryName()); + if (!repository.equals(OUSTR("user"))) + throw lang::IllegalArgumentException( + OUSTR("No valid repository name provided."), + static_cast<cppu::OWeakObject*>(this), 0); + + const OUString id(dp_misc::getIdentifier(extension)); + bUserDisabled = isUserDisabled(id, extension->getName()); + + activateExtension(id, extension->getName(), true, false, + xAbortChannel, xCmdEnv); + } + catch (deploy::DeploymentException& ) { + excOccurred = ::cppu::getCaughtException(); + } catch (ucb::CommandFailedException & ) { + excOccurred = ::cppu::getCaughtException(); + } catch (ucb::CommandAbortedException & ) { + excOccurred = ::cppu::getCaughtException(); + } catch (lang::IllegalArgumentException &) { + excOccurred = ::cppu::getCaughtException(); + } catch (uno::RuntimeException &) { + excOccurred = ::cppu::getCaughtException(); + } catch (...) { + excOccurred = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception during disableExtension"), + static_cast<OWeakObject*>(this), excOccurred); + excOccurred <<= exc; + } + + if (excOccurred.hasValue()) + { + try + { + activateExtension(dp_misc::getIdentifier(extension), + extension->getName(), bUserDisabled, false, + xAbortChannel, xCmdEnv); + } + catch (...) + { + } + ::cppu::throwException(excOccurred); + } +} + +uno::Sequence< Reference<deploy::XPackage> > + ExtensionManager::getDeployedExtensions( + OUString const & repository, + Reference<task::XAbortChannel> const &xAbort, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + return getPackageManager(repository)->getDeployedPackages( + xAbort, xCmdEnv); +} + +Reference<deploy::XPackage> + ExtensionManager::getDeployedExtension( + OUString const & repository, + OUString const & identifier, + OUString const & filename, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + return getPackageManager(repository)->getDeployedPackage( + identifier, filename, xCmdEnv); +} + +uno::Sequence< uno::Sequence<Reference<deploy::XPackage> > > + ExtensionManager::getAllExtensions( + Reference<task::XAbortChannel> const & xAbort, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + try + { + id2extensions mapExt; + + uno::Sequence<Reference<deploy::XPackage> > userExt = + m_userRepository->getDeployedPackages(xAbort, xCmdEnv); + addExtensionsToMap(mapExt, userExt, OUSTR("user")); + uno::Sequence<Reference<deploy::XPackage> > sharedExt = + m_sharedRepository->getDeployedPackages(xAbort, xCmdEnv); + addExtensionsToMap(mapExt, sharedExt, OUSTR("shared")); + uno::Sequence<Reference<deploy::XPackage> > bundledExt = + m_bundledRepository->getDeployedPackages(xAbort, xCmdEnv); + addExtensionsToMap(mapExt, bundledExt, OUSTR("bundled")); + + //copy the values of the map to a vector for sorting + ::std::vector< ::std::vector<Reference<deploy::XPackage> > > + vecExtensions; + id2extensions::const_iterator mapIt = mapExt.begin(); + for (;mapIt != mapExt.end(); mapIt++) + vecExtensions.push_back(mapIt->second); + + //sort the element according to the identifier + ::std::sort(vecExtensions.begin(), vecExtensions.end(), CompIdentifiers()); + + ::std::vector< ::std::vector<Reference<deploy::XPackage> > >::const_iterator + citVecVec = vecExtensions.begin(); + sal_Int32 j = 0; + uno::Sequence< uno::Sequence<Reference<deploy::XPackage> > > seqSeq(vecExtensions.size()); + for (;citVecVec != vecExtensions.end(); citVecVec++, j++) + { + seqSeq[j] = comphelper::containerToSequence(*citVecVec); + } + return seqSeq; + + } catch (deploy::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (...) { + uno::Any exc = ::cppu::getCaughtException(); + throw deploy::DeploymentException( + OUSTR("Extension Manager: exception during enableExtension"), + static_cast<OWeakObject*>(this), exc); + } +} + +//only to be called from unopkg!!! +void ExtensionManager::reinstallDeployedExtensions( + OUString const & repository, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, ucb::CommandAbortedException, + lang::IllegalArgumentException, uno::RuntimeException) +{ + try + { + Reference<deploy::XPackageManager> + xPackageManager = getPackageManager(repository); + + ::osl::MutexGuard guard(getMutex()); + xPackageManager->reinstallDeployedPackages(xAbortChannel, xCmdEnv); + //We must sync here, otherwise we will get exceptions when extensions + //are removed. + dp_misc::syncRepositories(xCmdEnv); + const uno::Sequence< Reference<deploy::XPackage> > extensions( + xPackageManager->getDeployedPackages(xAbortChannel, xCmdEnv)); + + for ( sal_Int32 pos = 0; pos < extensions.getLength(); ++pos ) + { + try + { + const OUString id = dp_misc::getIdentifier(extensions[ pos ]); + const OUString fileName = extensions[ pos ]->getName(); + OSL_ASSERT(id.getLength()); + activateExtension(id, fileName, false, false, xAbortChannel, xCmdEnv ); + } + catch (lang::DisposedException &) + { + } + } + } catch (deploy::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (...) { + uno::Any exc = ::cppu::getCaughtException(); + throw deploy::DeploymentException( + OUSTR("Extension Manager: exception during enableExtension"), + static_cast<OWeakObject*>(this), exc); + } +} + +sal_Bool ExtensionManager::synchronize( + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + try + { + sal_Bool bModified = sal_False; + + ::osl::MutexGuard guard(getMutex()); + String sSynchronizingShared(StrSyncRepository::get()); + sSynchronizingShared.SearchAndReplaceAllAscii( "%NAME", OUSTR("shared")); + dp_misc::ProgressLevel progressShared(xCmdEnv, sSynchronizingShared); + bModified = m_sharedRepository->synchronize(xAbortChannel, xCmdEnv); + progressShared.update(OUSTR("\n\n")); + + String sSynchronizingBundled(StrSyncRepository::get()); + sSynchronizingBundled.SearchAndReplaceAllAscii( "%NAME", OUSTR("bundled")); + dp_misc::ProgressLevel progressBundled(xCmdEnv, sSynchronizingBundled); + bModified |= m_bundledRepository->synchronize(xAbortChannel, xCmdEnv); + progressBundled.update(OUSTR("\n\n")); + + //Always determine the active extension. This is necessary for the + //first-start optimization. The setup creates the registration data for the + //bundled extensions (brand_layer/share/prereg/bundled), which is copied to the user + //installation (user_installation/extension/bundled) when a user starts OOo + //for the first time after running setup. All bundled extensions are registered + //at that moment. However, extensions with the same identifier can be in the + //shared or user repository, in which case the respective bundled extensions must + //be revoked. + try + { + const uno::Sequence<uno::Sequence<Reference<deploy::XPackage> > > + seqSeqExt = getAllExtensions(xAbortChannel, xCmdEnv); + for (sal_Int32 i = 0; i < seqSeqExt.getLength(); i++) + { + uno::Sequence<Reference<deploy::XPackage> > const & seqExt = + seqSeqExt[i]; + activateExtension(seqExt, isUserDisabled(seqExt), true, + xAbortChannel, xCmdEnv); + } + } + catch (...) + { + //We catch the exception, so we can write the lastmodified file + //so we will no repeat this everytime OOo starts. + OSL_ENSURE(0, "Extensions Manager: synchronize"); + } + OUString lastSyncBundled(RTL_CONSTASCII_USTRINGPARAM( + "$BUNDLED_EXTENSIONS_USER/lastsynchronized")); + writeLastModified(lastSyncBundled, xCmdEnv); + OUString lastSyncShared(RTL_CONSTASCII_USTRINGPARAM( + "$SHARED_EXTENSIONS_USER/lastsynchronized")); + writeLastModified(lastSyncShared, xCmdEnv); + return bModified; + } catch (deploy::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (...) { + uno::Any exc = ::cppu::getCaughtException(); + throw deploy::DeploymentException( + OUSTR("Extension Manager: exception in synchronize"), + static_cast<OWeakObject*>(this), exc); + } +} + +// Notify the user when a new extension is to be installed. This is only the +// case when one uses the system integration to install an extension (double +// clicking on .oxt file etc.)). The function must only be called if there is no +// extension with the same identifier already deployed. Then the checkUpdate +// function will inform the user that the extension is about to be installed In +// case the user cancels the installation a CommandFailed exception is +// thrown. +void ExtensionManager::checkInstall( + OUString const & displayName, + Reference<ucb::XCommandEnvironment> const & cmdEnv) +{ + uno::Any request( + deploy::InstallException( + OUSTR("Extension ") + displayName + + OUSTR(" is about to be installed."), + static_cast<OWeakObject *>(this), displayName)); + bool approve = false, abort = false; + if (! dp_misc::interactContinuation( + request, task::XInteractionApprove::static_type(), + cmdEnv, &approve, &abort )) + { + OSL_ASSERT( !approve && !abort ); + throw deploy::DeploymentException( + dp_misc::getResourceString(RID_STR_ERROR_WHILE_ADDING) + displayName, + static_cast<OWeakObject *>(this), request ); + } + if (abort || !approve) + throw ucb::CommandFailedException( + dp_misc::getResourceString(RID_STR_ERROR_WHILE_ADDING) + displayName, + static_cast<OWeakObject *>(this), request ); +} + +/* The function will make the user interaction in case there is an extension +installed with the same id. This function may only be called if there is already +an extension. +*/ +void ExtensionManager::checkUpdate( + OUString const & newVersion, + OUString const & newDisplayName, + Reference<deploy::XPackage> const & oldExtension, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + // package already deployed, interact --force: + uno::Any request( + (deploy::VersionException( + dp_misc::getResourceString( + RID_STR_PACKAGE_ALREADY_ADDED ) + newDisplayName, + static_cast<OWeakObject *>(this), newVersion, newDisplayName, + oldExtension ) ) ); + bool replace = false, abort = false; + if (! dp_misc::interactContinuation( + request, task::XInteractionApprove::static_type(), + xCmdEnv, &replace, &abort )) { + OSL_ASSERT( !replace && !abort ); + throw deploy::DeploymentException( + dp_misc::getResourceString( + RID_STR_ERROR_WHILE_ADDING) + newDisplayName, + static_cast<OWeakObject *>(this), request ); + } + if (abort || !replace) + throw ucb::CommandFailedException( + dp_misc::getResourceString( + RID_STR_PACKAGE_ALREADY_ADDED) + newDisplayName, + static_cast<OWeakObject *>(this), request ); +} + +Reference<deploy::XPackage> ExtensionManager::getTempExtension( + OUString const & url, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & /*xCmdEnv*/) + +{ + Reference<ucb::XCommandEnvironment> tmpCmdEnvA(new TmpRepositoryCommandEnv()); + Reference<deploy::XPackage> xTmpPackage = m_tmpRepository->addPackage( + url, uno::Sequence<beans::NamedValue>(),OUString(), xAbortChannel, tmpCmdEnvA); + if (!xTmpPackage.is()) + { + throw deploy::DeploymentException( + OUSTR("Extension Manager: Failed to create temporary XPackage for url: ") + url, + static_cast<OWeakObject*>(this), uno::Any()); + + } + return xTmpPackage; +} + +uno::Sequence<Reference<deploy::XPackage> > SAL_CALL +ExtensionManager::getExtensionsWithUnacceptedLicenses( + OUString const & repository, + Reference<ucb::XCommandEnvironment> const & xCmdEnv) + throw (deploy::DeploymentException, + uno::RuntimeException) +{ + Reference<deploy::XPackageManager> + xPackageManager = getPackageManager(repository); + ::osl::MutexGuard guard(getMutex()); + return xPackageManager->getExtensionsWithUnacceptedLicenses(xCmdEnv); +} + +sal_Bool ExtensionManager::isReadOnlyRepository(::rtl::OUString const & repository) + throw (uno::RuntimeException) +{ + return getPackageManager(repository)->isReadOnly(); +} +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +namespace sdecl = comphelper::service_decl; +sdecl::class_<ExtensionManager> servicePIP; +extern sdecl::ServiceDecl const serviceDecl( + servicePIP, + // a private one: + "com.sun.star.comp.deployment.ExtensionManager", + "com.sun.star.comp.deployment.ExtensionManager"); + +//------------------------------------------------------------------------------ +bool singleton_entries( + uno::Reference< registry::XRegistryKey > const & xRegistryKey ) +{ + try { + uno::Reference< registry::XRegistryKey > xKey( + xRegistryKey->createKey( + serviceDecl.getImplementationName() + + // xxx todo: use future generated function to get singleton name + OUSTR("/UNO/SINGLETONS/" + "com.sun.star.deployment.ExtensionManager") ) ); + xKey->setStringValue( serviceDecl.getSupportedServiceNames()[0] ); + return true; + } + catch (registry::InvalidRegistryException & exc) { + (void) exc; // avoid warnings + OSL_ENSURE( 0, ::rtl::OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + return false; + } +} + +// XModifyBroadcaster +//______________________________________________________________________________ +void ExtensionManager::addModifyListener( + Reference<util::XModifyListener> const & xListener ) + throw (uno::RuntimeException) +{ + check(); + rBHelper.addListener( ::getCppuType( &xListener ), xListener ); +} + +//______________________________________________________________________________ +void ExtensionManager::removeModifyListener( + Reference<util::XModifyListener> const & xListener ) + throw (uno::RuntimeException) +{ + check(); + rBHelper.removeListener( ::getCppuType( &xListener ), xListener ); +} + +void ExtensionManager::check() +{ + ::osl::MutexGuard guard( getMutex() ); + if (rBHelper.bInDispose || rBHelper.bDisposed) { + throw lang::DisposedException( + OUSTR("ExtensionManager instance has already been disposed!"), + static_cast<OWeakObject *>(this) ); + } +} + +void ExtensionManager::fireModified() +{ + ::cppu::OInterfaceContainerHelper * pContainer = rBHelper.getContainer( + util::XModifyListener::static_type() ); + if (pContainer != 0) { + pContainer->forEach<util::XModifyListener>( + boost::bind(&util::XModifyListener::modified, _1, + lang::EventObject(static_cast<OWeakObject *>(this))) ); + } +} + +} // namespace dp_manager + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_extensionmanager.hxx b/desktop/source/deployment/manager/dp_extensionmanager.hxx new file mode 100644 index 000000000000..8677f960ef91 --- /dev/null +++ b/desktop/source/deployment/manager/dp_extensionmanager.hxx @@ -0,0 +1,314 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_EXTENSIONMANAGER_H +#define INCLUDED_DP_EXTENSIONMANAGER_H + +#include "dp_manager.hrc" +#include "dp_misc.h" +#include "dp_interact.h" +#include "dp_activepackages.hxx" +#include "rtl/ref.hxx" +#include "cppuhelper/compbase1.hxx" +#include "ucbhelper/content.hxx" +#include "com/sun/star/deployment/XPackageRegistry.hpp" +#include "com/sun/star/deployment/XPackageManager.hpp" +#include "osl/mutex.hxx" +#include <list> + +namespace css = ::com::sun::star; + +namespace dp_manager { + +typedef ::std::hash_map< + ::rtl::OUString, + ::std::vector<css::uno::Reference<css::deployment::XPackage> >, + ::rtl::OUStringHash > id2extensions; + +class ExtensionManager : private ::dp_misc::MutexHolder, + public ::cppu::WeakComponentImplHelper1< css::deployment::XExtensionManager > +{ +public: + ExtensionManager( css::uno::Reference< css::uno::XComponentContext >const& xContext); + virtual ~ExtensionManager(); + + static css::uno::Sequence< ::rtl::OUString > getServiceNames(); + static ::rtl::OUString getImplName(); + + void check(); + void fireModified(); + +public: + +// XModifyBroadcaster + virtual void SAL_CALL addModifyListener( + css::uno::Reference<css::util::XModifyListener> const & xListener ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL removeModifyListener( + css::uno::Reference<css::util::XModifyListener> const & xListener ) + throw (css::uno::RuntimeException); + +//XExtensionManager + virtual css::uno::Sequence< + css::uno::Reference<css::deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() + throw (css::uno::RuntimeException); + + virtual css::uno::Reference<css::task::XAbortChannel> SAL_CALL + createAbortChannel() throw (css::uno::RuntimeException); + + virtual css::uno::Reference<css::deployment::XPackage> SAL_CALL addExtension( + ::rtl::OUString const & url, + css::uno::Sequence<css::beans::NamedValue> const & properties, + ::rtl::OUString const & repository, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual void SAL_CALL removeExtension( + ::rtl::OUString const & identifier, + ::rtl::OUString const & filename, + ::rtl::OUString const & repository, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual void SAL_CALL enableExtension( + css::uno::Reference<css::deployment::XPackage> const & extension, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual void SAL_CALL disableExtension( + css::uno::Reference<css::deployment::XPackage> const & extension, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL checkPrerequisitesAndEnable( + css::uno::Reference<css::deployment::XPackage> const & extension, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual css::uno::Sequence< css::uno::Reference<css::deployment::XPackage> > + SAL_CALL getDeployedExtensions( + ::rtl::OUString const & repository, + css::uno::Reference<css::task::XAbortChannel> const &, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual css::uno::Reference< css::deployment::XPackage> + SAL_CALL getDeployedExtension( + ::rtl::OUString const & repository, + ::rtl::OUString const & identifier, + ::rtl::OUString const & filename, + css::uno::Reference< css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw ( + css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > + SAL_CALL getExtensionsWithSameIdentifier( + ::rtl::OUString const & identifier, + ::rtl::OUString const & filename, + css::uno::Reference< css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw ( + css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual css::uno::Sequence< css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > > + SAL_CALL getAllExtensions( + css::uno::Reference<css::task::XAbortChannel> const &, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual void SAL_CALL reinstallDeployedExtensions( + ::rtl::OUString const & repository, + css::uno::Reference< css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference< css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw ( + css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL synchronize( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > SAL_CALL + getExtensionsWithUnacceptedLicenses( + ::rtl::OUString const & repository, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv) + throw (css::deployment::DeploymentException, + css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isReadOnlyRepository(::rtl::OUString const & repository) + throw (css::uno::RuntimeException); + +private: + + struct StrSyncRepository : public ::dp_misc::StaticResourceString< + StrSyncRepository, RID_STR_SYNCHRONIZING_REPOSITORY> {}; + + struct ExtensionInfos + { + ::rtl::OUString identifier; + ::rtl::OUString fileName; + ::rtl::OUString displayName; + ::rtl::OUString version; + }; + + css::uno::Reference< css::uno::XComponentContext> m_xContext; + + css::uno::Reference<css::deployment::XPackageManager> m_userRepository; + css::uno::Reference<css::deployment::XPackageManager> m_sharedRepository; + css::uno::Reference<css::deployment::XPackageManager> m_bundledRepository; + css::uno::Reference<css::deployment::XPackageManager> m_tmpRepository; + + //only to be used within addExtension + ::osl::Mutex m_addMutex; + /* contains the names of all repositories (except tmp) in order of there + priority. That is, the first element is "user" follod by "shared" and + then "bundled" + */ + ::std::list< ::rtl::OUString > m_repositoryNames; + + bool isUserDisabled(::rtl::OUString const & identifier, + ::rtl::OUString const & filename); + + bool isUserDisabled( + css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > const & seqExtSameId); + + void activateExtension( + ::rtl::OUString const & identifier, + ::rtl::OUString const & fileName, + bool bUserDisabled, bool bStartup, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + void activateExtension( + css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > const & seqExt, + bool bUserDisabled, bool bStartup, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ); + + ::std::list<css::uno::Reference<css::deployment::XPackage> > + getExtensionsWithSameId(::rtl::OUString const & identifier, + ::rtl::OUString const & fileName, + css::uno::Reference< css::ucb::XCommandEnvironment> const & xCmdEnv = + css::uno::Reference< css::ucb::XCommandEnvironment>()); + + css::uno::Reference<css::deployment::XPackage> backupExtension( + ::rtl::OUString const & identifier, ::rtl::OUString const & fileName, + css::uno::Reference<css::deployment::XPackageManager> const & xPackageManager, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + void checkInstall( + ::rtl::OUString const & displayName, + css::uno::Reference<css::ucb::XCommandEnvironment> const & cmdEnv); + + void checkUpdate( + ::rtl::OUString const & newVersion, + ::rtl::OUString const & newDisplayName, + css::uno::Reference<css::deployment::XPackage> const & oldExtension, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + css::uno::Reference<css::deployment::XPackage> getTempExtension( + ::rtl::OUString const & url, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + void addExtensionsToMap( + id2extensions & mapExt, + css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > const & seqExt, + ::rtl::OUString const & repository); + + css::uno::Reference<css::deployment::XPackageManager> + getPackageManager(::rtl::OUString const & repository) + throw (css::lang::IllegalArgumentException); + + bool doChecksForAddExtension( + css::uno::Reference<css::deployment::XPackageManager> const & xPackageMgr, + css::uno::Sequence<css::beans::NamedValue> const & properties, + css::uno::Reference<css::deployment::XPackage> const & xTmpExtension, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + css::uno::Reference<css::deployment::XPackage> & out_existingExtension ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_informationprovider.cxx b/desktop/source/deployment/manager/dp_informationprovider.cxx new file mode 100644 index 000000000000..6aaf3739e223 --- /dev/null +++ b/desktop/source/deployment/manager/dp_informationprovider.cxx @@ -0,0 +1,395 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 <cppuhelper/implbase3.hxx> + +#include "comphelper/servicedecl.hxx" + +#include "com/sun/star/deployment/UpdateInformationProvider.hpp" +#include "com/sun/star/deployment/XPackage.hpp" +#include "com/sun/star/deployment/XPackageInformationProvider.hpp" +#include "com/sun/star/deployment/ExtensionManager.hpp" +#include "com/sun/star/deployment/XUpdateInformationProvider.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" +#include "com/sun/star/task/XAbortChannel.hpp" +#include "com/sun/star/ucb/CommandFailedException.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/dom/XElement.hpp" +#include "com/sun/star/xml/dom/XNode.hpp" + +#include "com/sun/star/uno/Reference.hxx" +#include "rtl/ustring.hxx" +#include "ucbhelper/content.hxx" + +#include "dp_dependencies.hxx" +#include "dp_descriptioninfoset.hxx" +#include "dp_identifier.hxx" +#include "dp_version.hxx" +#include "dp_misc.h" +#include "dp_update.hxx" + +namespace beans = com::sun::star::beans ; +namespace deployment = com::sun::star::deployment ; +namespace lang = com::sun::star::lang ; +namespace registry = com::sun::star::registry ; +namespace task = com::sun::star::task ; +namespace css_ucb = com::sun::star::ucb ; +namespace uno = com::sun::star::uno ; +namespace xml = com::sun::star::xml ; + +#define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) + +namespace dp_info { + +class PackageInformationProvider : + public ::cppu::WeakImplHelper3< deployment::XPackageInformationProvider, + css_ucb::XCommandEnvironment, + task::XInteractionHandler > +{ + public: + PackageInformationProvider( uno::Reference< uno::XComponentContext >const& xContext); + virtual ~PackageInformationProvider(); + + static uno::Sequence< rtl::OUString > getServiceNames(); + static rtl::OUString getImplName(); + + // XInteractionHandler + virtual void SAL_CALL handle( const uno::Reference< task::XInteractionRequest >& Request ) + throw( uno::RuntimeException ); + // XCommandEnvironment + virtual uno::Reference< task::XInteractionHandler > SAL_CALL getInteractionHandler() + throw ( uno::RuntimeException ) { return static_cast<task::XInteractionHandler*>(this); }; + + virtual uno::Reference< css_ucb::XProgressHandler > SAL_CALL getProgressHandler() + throw ( uno::RuntimeException ) { return uno::Reference< css_ucb::XProgressHandler >(); }; + + // XPackageInformationProvider + virtual rtl::OUString SAL_CALL getPackageLocation( const rtl::OUString& extensionId ) + throw ( uno::RuntimeException ); + virtual uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL isUpdateAvailable( const rtl::OUString& extensionId ) + throw ( uno::RuntimeException ); + virtual uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL getExtensionList() + throw ( uno::RuntimeException ); +//--------- +private: + + uno::Reference< uno::XComponentContext> mxContext; + + rtl::OUString getPackageLocation( const rtl::OUString& repository, + const rtl::OUString& _sExtensionId ); + + uno::Reference< deployment::XUpdateInformationProvider > mxUpdateInformation; +}; + +//------------------------------------------------------------------------------ + +PackageInformationProvider::PackageInformationProvider( uno::Reference< uno::XComponentContext > const& xContext) : + mxContext( xContext ), + mxUpdateInformation( deployment::UpdateInformationProvider::create( xContext ) ) +{ +} + +//------------------------------------------------------------------------------ + +PackageInformationProvider::~PackageInformationProvider() +{ +} + +//------------------------------------------------------------------------------ +void SAL_CALL PackageInformationProvider::handle( uno::Reference< task::XInteractionRequest > const & rRequest) + throw (uno::RuntimeException) +{ + uno::Sequence< uno::Reference< task::XInteractionContinuation > > xContinuations = rRequest->getContinuations(); + if ( xContinuations.getLength() == 1 ) + { + xContinuations[0]->select(); + } +} + +//------------------------------------------------------------------------------ +rtl::OUString PackageInformationProvider::getPackageLocation( + const rtl::OUString & repository, + const rtl::OUString& _rExtensionId ) +{ + rtl::OUString aLocationURL; + uno::Reference<deployment::XExtensionManager> xManager = + deployment::ExtensionManager::get(mxContext); + + if ( xManager.is() ) + { + const uno::Sequence< uno::Reference< deployment::XPackage > > packages( + xManager->getDeployedExtensions( + repository, + uno::Reference< task::XAbortChannel >(), + static_cast < XCommandEnvironment *> (this) ) ); + + for ( int pos = packages.getLength(); pos--; ) + { + try + { + const rtl::OUString aName = packages[ pos ]->getName(); + const beans::Optional< rtl::OUString > aID = packages[ pos ]->getIdentifier(); + if ( aID.IsPresent && aID.Value.compareTo( _rExtensionId ) == 0 ) + { + aLocationURL = packages[ pos ]->getURL(); + break; + } + } + catch ( uno::RuntimeException & ) {} + } + } + + return aLocationURL; +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +rtl::OUString SAL_CALL +PackageInformationProvider::getPackageLocation( const rtl::OUString& _sExtensionId ) + throw ( uno::RuntimeException ) +{ + rtl::OUString aLocationURL = getPackageLocation( UNISTRING("user"), _sExtensionId ); + + if ( aLocationURL.getLength() == 0 ) + { + aLocationURL = getPackageLocation( UNISTRING("shared"), _sExtensionId ); + } + if ( aLocationURL.getLength() == 0 ) + { + aLocationURL = getPackageLocation( UNISTRING("bundled"), _sExtensionId ); + } + if ( aLocationURL.getLength() ) + { + ::ucbhelper::Content aContent( aLocationURL, NULL ); + aLocationURL = aContent.getURL(); + } + return aLocationURL; +} + +//------------------------------------------------------------------------------ + +uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL +PackageInformationProvider::isUpdateAvailable( const rtl::OUString& _sExtensionId ) + throw ( uno::RuntimeException ) +{ + uno::Sequence< uno::Sequence< rtl::OUString > > aList; + + uno::Reference<deployment::XExtensionManager> extMgr = + deployment::ExtensionManager::get(mxContext); + + if (!extMgr.is()) + { + OSL_ASSERT(0); + return aList; + } + std::vector<std::pair<uno::Reference<deployment::XPackage>, uno::Any > > errors; + dp_misc::UpdateInfoMap updateInfoMap; + if (_sExtensionId.getLength()) + { + std::vector<uno::Reference<deployment::XPackage> > vecExtensions; + uno::Reference<deployment::XPackage> extension; + try + { + extension = dp_misc::getExtensionWithHighestVersion( + extMgr->getExtensionsWithSameIdentifier( + _sExtensionId, _sExtensionId, uno::Reference<css_ucb::XCommandEnvironment>())); + vecExtensions.push_back(extension); + } + catch (lang::IllegalArgumentException &) + { + OSL_ASSERT(0); + } + updateInfoMap = dp_misc::getOnlineUpdateInfos( + mxContext, extMgr, mxUpdateInformation, &vecExtensions, errors); + } + else + { + updateInfoMap = dp_misc::getOnlineUpdateInfos( + mxContext, extMgr, mxUpdateInformation, NULL, errors); + } + + int nCount = 0; + for (dp_misc::UpdateInfoMap::iterator i(updateInfoMap.begin()); i != updateInfoMap.end(); i++) + { + dp_misc::UpdateInfo const & info = i->second; + + rtl::OUString sOnlineVersion; + if (info.info.is()) + { + // check, if there are unsatisfied dependencies and ignore this online update + dp_misc::DescriptionInfoset infoset(mxContext, info.info); + uno::Sequence< uno::Reference< xml::dom::XElement > > + ds( dp_misc::Dependencies::check( infoset ) ); + if ( ! ds.getLength() ) + sOnlineVersion = info.version; + } + + rtl::OUString sVersionUser; + rtl::OUString sVersionShared; + rtl::OUString sVersionBundled; + uno::Sequence< uno::Reference< deployment::XPackage> > extensions; + try { + extensions = extMgr->getExtensionsWithSameIdentifier( + dp_misc::getIdentifier(info.extension), info.extension->getName(), + uno::Reference<css_ucb::XCommandEnvironment>()); + } catch (lang::IllegalArgumentException& ) { + OSL_ASSERT(0); + } + OSL_ASSERT(extensions.getLength() == 3); + if (extensions[0].is() ) + sVersionUser = extensions[0]->getVersion(); + if (extensions[1].is() ) + sVersionShared = extensions[1]->getVersion(); + if (extensions[2].is() ) + sVersionBundled = extensions[2]->getVersion(); + + bool bSharedReadOnly = extMgr->isReadOnlyRepository(OUSTR("shared")); + + dp_misc::UPDATE_SOURCE sourceUser = dp_misc::isUpdateUserExtension( + bSharedReadOnly, sVersionUser, sVersionShared, sVersionBundled, sOnlineVersion); + dp_misc::UPDATE_SOURCE sourceShared = dp_misc::isUpdateSharedExtension( + bSharedReadOnly, sVersionShared, sVersionBundled, sOnlineVersion); + + rtl::OUString updateVersionUser; + rtl::OUString updateVersionShared; + if (sourceUser != dp_misc::UPDATE_SOURCE_NONE) + updateVersionUser = dp_misc::getHighestVersion( + rtl::OUString(), sVersionShared, sVersionBundled, sOnlineVersion); + if (sourceShared != dp_misc::UPDATE_SOURCE_NONE) + updateVersionShared = dp_misc::getHighestVersion( + rtl::OUString(), rtl::OUString(), sVersionBundled, sOnlineVersion); + rtl::OUString updateVersion; + if (dp_misc::compareVersions(updateVersionUser, updateVersionShared) == dp_misc::GREATER) + updateVersion = updateVersionUser; + else + updateVersion = updateVersionShared; + if (updateVersion.getLength()) + { + + rtl::OUString aNewEntry[2]; + aNewEntry[0] = i->first; + aNewEntry[1] = updateVersion; + aList.realloc( ++nCount ); + aList[ nCount-1 ] = ::uno::Sequence< rtl::OUString >( aNewEntry, 2 ); + } + } + return aList; +} + +//------------------------------------------------------------------------------ +uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL PackageInformationProvider::getExtensionList() + throw ( uno::RuntimeException ) +{ + const uno::Reference<deployment::XExtensionManager> mgr = + deployment::ExtensionManager::get(mxContext); + + if (!mgr.is()) + return uno::Sequence< uno::Sequence< rtl::OUString > >(); + + const uno::Sequence< uno::Sequence< uno::Reference<deployment::XPackage > > > + allExt = mgr->getAllExtensions( + uno::Reference< task::XAbortChannel >(), + static_cast < XCommandEnvironment *> (this) ); + + uno::Sequence< uno::Sequence< rtl::OUString > > retList; + + sal_Int32 cAllIds = allExt.getLength(); + retList.realloc(cAllIds); + + for (sal_Int32 i = 0; i < cAllIds; i++) + { + //The inner sequence contains extensions with the same identifier from + //all the different repositories, that is user, share, bundled. + const uno::Sequence< uno::Reference< deployment::XPackage > > & + seqExtension = allExt[i]; + sal_Int32 cExt = seqExtension.getLength(); + OSL_ASSERT(cExt == 3); + for (sal_Int32 j = 0; j < cExt; j++) + { + //ToDo according to the old code the first found extenions is used + //even if another one with the same id has a better version. + uno::Reference< deployment::XPackage > const & xExtension( seqExtension[j] ); + if (xExtension.is()) + { + rtl::OUString aNewEntry[2]; + aNewEntry[0] = dp_misc::getIdentifier(xExtension); + aNewEntry[1] = xExtension->getVersion(); + retList[i] = ::uno::Sequence< rtl::OUString >( aNewEntry, 2 ); + break; + } + } + } + return retList; +} + + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +namespace sdecl = comphelper::service_decl; +sdecl::class_<PackageInformationProvider> servicePIP; +extern sdecl::ServiceDecl const serviceDecl( + servicePIP, + // a private one: + "com.sun.star.comp.deployment.PackageInformationProvider", + "com.sun.star.comp.deployment.PackageInformationProvider" ); + +//------------------------------------------------------------------------------ +bool singleton_entries( + uno::Reference< registry::XRegistryKey > const & xRegistryKey ) +{ + try { + uno::Reference< registry::XRegistryKey > xKey( + xRegistryKey->createKey( + serviceDecl.getImplementationName() + + // xxx todo: use future generated function to get singleton name + UNISTRING("/UNO/SINGLETONS/" + "com.sun.star.deployment.PackageInformationProvider") ) ); + xKey->setStringValue( serviceDecl.getSupportedServiceNames()[0] ); + return true; + } + catch (registry::InvalidRegistryException & exc) { + (void) exc; // avoid warnings + OSL_ENSURE( 0, ::rtl::OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + return false; + } +} + +} // namespace dp_info + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_manager.cxx b/desktop/source/deployment/manager/dp_manager.cxx new file mode 100644 index 000000000000..3b7432ae8057 --- /dev/null +++ b/desktop/source/deployment/manager/dp_manager.cxx @@ -0,0 +1,1675 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_ucb.h" +#include "dp_resource.h" +#include "dp_platform.hxx" +#include "dp_manager.h" +#include "dp_identifier.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/string.hxx" +#include "rtl/uri.hxx" +#include "rtl/bootstrap.hxx" +#include "osl/diagnose.h" +#include "osl/file.hxx" +#include "osl/security.hxx" +#include "cppuhelper/weakref.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/interfacecontainer.hxx" +#include "comphelper/servicedecl.hxx" +#include "comphelper/sequence.hxx" +#include "xmlscript/xml_helper.hxx" +#include "svl/inettype.hxx" +#include "com/sun/star/lang/DisposedException.hpp" +#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" +#include "com/sun/star/beans/UnknownPropertyException.hpp" +#include "com/sun/star/util/XUpdatable.hpp" +#include "com/sun/star/sdbc/XResultSet.hpp" +#include "com/sun/star/sdbc/XRow.hpp" +#include "com/sun/star/ucb/XContentAccess.hpp" +#include "com/sun/star/ucb/NameClash.hpp" +#include "com/sun/star/deployment/VersionException.hpp" +#include "com/sun/star/deployment/InstallException.hpp" +#include "com/sun/star/deployment/Prerequisites.hpp" +#include "com/sun/star/task/XInteractionApprove.hpp" +#include "com/sun/star/ucb/UnsupportedCommandException.hpp" +#include "boost/bind.hpp" +#include "tools/urlobj.hxx" + +#include "osl/file.hxx" +#include <vector> +#include <list> +#include "dp_descriptioninfoset.hxx" +#include "dp_commandenvironments.hxx" +#include "dp_properties.hxx" + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; + +namespace dp_log { +extern comphelper::service_decl::ServiceDecl const serviceDecl; +} + +namespace dp_registry { +Reference<deployment::XPackageRegistry> create( + OUString const & context, + OUString const & cachePath, bool readOnly, + Reference<XComponentContext> const & xComponentContext ); +} + +namespace dp_manager { + +struct MatchTempDir +{ + OUString m_str; + MatchTempDir( OUString const & str ) : m_str( str ) {} + bool operator () ( ActivePackages::Entries::value_type const & v ) const { + return v.second.temporaryName.equalsIgnoreAsciiCase( m_str ); + } +}; + + +namespace { +OUString getExtensionFolder(OUString const & parentFolder, + Reference<ucb::XCommandEnvironment> const & xCmdEnv) +{ + ::ucbhelper::Content tempFolder( + parentFolder, xCmdEnv ); + Reference<sdbc::XResultSet> xResultSet( + tempFolder.createCursor( + Sequence<OUString>( &StrTitle::get(), 1 ), + ::ucbhelper::INCLUDE_FOLDERS_ONLY ) ); + + OUString title; + while (xResultSet->next()) + { + title = Reference<sdbc::XRow>( + xResultSet, UNO_QUERY_THROW )->getString(1 /* Title */ ) ; + break; + } + return title; +} +} +//______________________________________________________________________________ +void PackageManagerImpl::initActivationLayer( + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + if (m_activePackages.getLength() == 0) + { + OSL_ASSERT( m_registryCache.getLength() == 0 ); + // documents temp activation: + m_activePackagesDB.reset( new ActivePackages ); + ::ucbhelper::Content ucbContent; + if (create_ucb_content( &ucbContent, m_context, xCmdEnv, + false /* no throw */ )) + { + // scan for all entries in m_packagesDir: + Reference<sdbc::XResultSet> xResultSet( + ucbContent.createCursor( + Sequence<OUString>( &StrTitle::get(), 1 ), + ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS ) ); + while (xResultSet->next()) + { + Reference<sdbc::XRow> xRow( xResultSet, UNO_QUERY_THROW ); + OUString title( xRow->getString( 1 /* Title */ ) ); + // xxx todo: remove workaround for tdoc + if (title.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( + "this_is_a_dummy_stream_just_there_" + "as_a_workaround_for_a_" + "temporary_limitation_of_the_" + "storage_api_implementation") )) + continue; + if (title.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( + "META-INF") ) ) + continue; + + ::ucbhelper::Content sourceContent( + Reference<XContentAccess>( + xResultSet, UNO_QUERY_THROW )->queryContent(), + xCmdEnv ); + + OUString mediaType( detectMediaType( sourceContent, + false /* no throw */) ); + if (mediaType.getLength() >0) + { + ActivePackages::Data dbData; + insertToActivationLayer( + Sequence<css::beans::NamedValue>(),mediaType, sourceContent, + title, &dbData ); + + insertToActivationLayerDB( title, dbData ); + //TODO #i73136#: insertToActivationLayerDB needs id not + // title, but the whole m_activePackages.getLength()==0 + // case (i.e., document-relative deployment) currently + // does not work, anyway. + } + } + } + } + else + { + // user|share: + OSL_ASSERT( m_activePackages.getLength() > 0 ); + m_activePackages_expanded = expandUnoRcUrl( m_activePackages ); + m_registrationData_expanded = expandUnoRcUrl(m_registrationData); + if (!m_readOnly) + create_folder( 0, m_activePackages_expanded, xCmdEnv, true); + + OUString dbName; + if (m_context.equals(OUSTR("user"))) + dbName = m_activePackages_expanded + OUSTR(".db"); + else + { + //Create the extension data base in the user installation + create_folder( 0, m_registrationData_expanded, xCmdEnv, true); + dbName = m_registrationData_expanded + OUSTR("/extensions.db"); + } + //The data base can always be written because it it always in the user installation + m_activePackagesDB.reset( + new ActivePackages( dbName, false ) ); + + if (! m_readOnly && ! m_context.equals(OUSTR("bundled"))) + { + // clean up activation layer, scan for zombie temp dirs: + ActivePackages::Entries id2temp( m_activePackagesDB->getEntries() ); + + ::ucbhelper::Content tempFolder( + m_activePackages_expanded, xCmdEnv ); + Reference<sdbc::XResultSet> xResultSet( + tempFolder.createCursor( + Sequence<OUString>( &StrTitle::get(), 1 ), + ::ucbhelper::INCLUDE_DOCUMENTS_ONLY ) ); + // get all temp directories: + ::std::vector<OUString> tempEntries; + ::std::vector<OUString> removedEntries; + while (xResultSet->next()) + { + OUString title( + Reference<sdbc::XRow>( + xResultSet, UNO_QUERY_THROW )->getString( + 1 /* Title */ ) ); + + const char extensionRemoved[] = "removed"; + if (title.endsWithAsciiL( + extensionRemoved, sizeof(extensionRemoved) - 1)) + { + //save the file name withouth the "removed" part + sal_Int32 index = title.lastIndexOfAsciiL( + extensionRemoved, sizeof(extensionRemoved) - 1); + OUString remFile = title.copy(0, index); + removedEntries.push_back(::rtl::Uri::encode( + remFile, rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + } + else + { + tempEntries.push_back( ::rtl::Uri::encode( + title, rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + } + } + + bool bShared = m_context.equals(OUSTR("shared")) ? true : false; + for ( ::std::size_t pos = 0; pos < tempEntries.size(); ++pos ) + { + OUString const & tempEntry = tempEntries[ pos ]; + const MatchTempDir match( tempEntry ); + if (::std::find_if( id2temp.begin(), id2temp.end(), match ) == + id2temp.end()) + { + const OUString url( + makeURL(m_activePackages_expanded, tempEntry ) ); + + //In case of shared extensions, new entries are regarded as + //added extensions if there is no xxx.tmpremoved file. + if (bShared) + { + if (::std::find(removedEntries.begin(), removedEntries.end(), tempEntry) == + removedEntries.end()) + { + continue; + } + else + { + //Make sure only the same user removes the extension, who + //previously unregistered it. This is avoid races if multiple instances + //of OOo are running which all have write access to the shared installation. + //For example, a user removes the extension, but keeps OOo + //running. Parts of the extension may still be loaded and used by OOo. + //Therefore the extension is only deleted the next time the extension manager is + //run after restarting OOo. While OOo is still running, another user starts OOo + //which would deleted the extension files. If the same user starts another + //instance of OOo then the lock file will prevent this. + OUString aUserName; + ::osl::Security aSecurity; + aSecurity.getUserName( aUserName ); + ucbhelper::Content remFileContent( + url + OUSTR("removed"), Reference<XCommandEnvironment>()); + ::rtl::ByteSequence data = dp_misc::readFile(remFileContent); + ::rtl::OString osData(reinterpret_cast<const sal_Char*>(data.getConstArray()), + data.getLength()); + OUString sData = ::rtl::OStringToOUString( + osData, RTL_TEXTENCODING_UTF8); + if (!sData.equals(aUserName)) + continue; + } + } + // temp entry not needed anymore: + erase_path( url + OUSTR("_"), + Reference<XCommandEnvironment>(), + false /* no throw: ignore errors */ ); + erase_path( url, Reference<XCommandEnvironment>(), + false /* no throw: ignore errors */ ); + //delete the xxx.tmpremoved file + erase_path(url + OUSTR("removed"), + Reference<XCommandEnvironment>(), false); + } + } + } + } +} + +//______________________________________________________________________________ +void PackageManagerImpl::initRegistryBackends() +{ + if (m_registryCache.getLength() > 0) + create_folder( 0, m_registryCache, + Reference<XCommandEnvironment>(), false); + m_xRegistry.set( ::dp_registry::create( + m_context, m_registryCache, false, + m_xComponentContext ) ); +} + +//______________________________________________________________________________ +Reference<deployment::XPackageManager> PackageManagerImpl::create( + Reference<XComponentContext> const & xComponentContext, + OUString const & context ) +{ + PackageManagerImpl * that = new PackageManagerImpl( + xComponentContext, context ); + Reference<deployment::XPackageManager> xPackageManager( that ); + + OUString packages, logFile, stampURL; + if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("user") )) { + that->m_activePackages = OUSTR( + "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/uno_packages"); + that->m_registrationData = OUSTR( + "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE"); + that->m_registryCache = OUSTR( + "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/registry"); + logFile = OUSTR( + "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/log.txt"); + //We use the extension .sys for the file because on Windows Vista a sys + //(as well as exe and dll) file + //will not be written in the VirtualStore. For example if the process has no + //admin right once cannot write to the %programfiles% folder. However, when + //virtualization is used, the file will be written into the VirtualStore and + //it appears as if one could write to %programfiles%. When we test for write + //access to the office/shared folder for shared extensions then this typically + //fails because a normal user typically cannot write to this folder. However, + //using virtualization it appears that he/she can. Then a shared extension can + //be installed but is only visible for the user (because the extension is in + //the virtual store). + stampURL = OUSTR( + "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/stamp.sys"); + } + else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("shared") )) { + that->m_activePackages = OUSTR( + "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE/uno_packages"); + that->m_registrationData = OUSTR( + "vnd.sun.star.expand:$SHARED_EXTENSIONS_USER"); + that->m_registryCache = OUSTR( + "vnd.sun.star.expand:$SHARED_EXTENSIONS_USER/registry"); + logFile = OUSTR( + "vnd.sun.star.expand:$SHARED_EXTENSIONS_USER/log.txt"); + stampURL = OUSTR( + "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE/stamp.sys"); + } + else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("bundled") )) { + that->m_activePackages = OUSTR( + "vnd.sun.star.expand:$BUNDLED_EXTENSIONS"); + that->m_registrationData = OUSTR( + "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_USER"); + that->m_registryCache = OUSTR( + "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_USER/registry"); + logFile = OUSTR( + "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_USER/log.txt"); + //No stamp file. We assume that bundled is always readonly. It must not be + //modified from ExtensionManager but only by the installer + } + else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("tmp") )) { + that->m_activePackages = OUSTR( + "vnd.sun.star.expand:$TMP_EXTENSIONS/extensions"); + that->m_registrationData = OUSTR( + "vnd.sun.star.expand:$TMP_EXTENSIONS"); + that->m_registryCache = OUSTR( + "vnd.sun.star.expand:$TMP_EXTENSIONS/registry"); + stampURL = OUSTR( + "vnd.sun.star.expand:$TMP_EXTENSIONS/stamp.sys"); + } + else if (! context.matchAsciiL( + RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.tdoc:/") )) { + throw lang::IllegalArgumentException( + OUSTR("invalid context given: ") + context, + Reference<XInterface>(), static_cast<sal_Int16>(-1) ); + } + + Reference<XCommandEnvironment> xCmdEnv; + + try { + //There is no stampURL for the bundled folder + if (stampURL.getLength() > 0) + { +#define CURRENT_STAMP "1" + try { + //The osl file API does not allow to find out if one can write + //into a folder. Therefore we try to write a file. Then we delete + //it, so that it does not hinder uninstallation of OOo + // probe writing: + ::ucbhelper::Content ucbStamp( stampURL, xCmdEnv ); + ::rtl::OString stamp( + RTL_CONSTASCII_STRINGPARAM(CURRENT_STAMP) ); + Reference<io::XInputStream> xData( + ::xmlscript::createInputStream( + ::rtl::ByteSequence( + reinterpret_cast<sal_Int8 const *>(stamp.getStr()), + stamp.getLength() ) ) ); + ucbStamp.writeStream( xData, true /* replace existing */ ); + that->m_readOnly = false; + erase_path( stampURL, xCmdEnv ); + } + catch (RuntimeException &) { + try { + erase_path( stampURL, xCmdEnv ); + } catch (...) + { + } + throw; + } + catch (Exception &) { + that->m_readOnly = true; + } + } + + if (!that->m_readOnly && logFile.getLength() > 0) + { + const Any any_logFile(logFile); + that->m_xLogFile.set( + that->m_xComponentContext->getServiceManager() + ->createInstanceWithArgumentsAndContext( + dp_log::serviceDecl.getSupportedServiceNames()[0], + Sequence<Any>( &any_logFile, 1 ), + that->m_xComponentContext ), + UNO_QUERY_THROW ); + xCmdEnv.set( new CmdEnvWrapperImpl( xCmdEnv, that->m_xLogFile ) ); + } + + that->initRegistryBackends(); + that->initActivationLayer( xCmdEnv ); + + return xPackageManager; + + } + catch (RuntimeException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[context=\"") ); + buf.append( context ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "\"] caught unexpected exception!") ); + throw lang::WrappedTargetRuntimeException( + buf.makeStringAndClear(), Reference<XInterface>(), exc ); + } +} + +//______________________________________________________________________________ +PackageManagerImpl::~PackageManagerImpl() +{ +} + +//______________________________________________________________________________ +void PackageManagerImpl::fireModified() +{ + ::cppu::OInterfaceContainerHelper * pContainer = rBHelper.getContainer( + util::XModifyListener::static_type() ); + if (pContainer != 0) { + pContainer->forEach<util::XModifyListener>( + boost::bind(&util::XModifyListener::modified, _1, + lang::EventObject(static_cast<OWeakObject *>(this))) ); + } +} + +//______________________________________________________________________________ +void PackageManagerImpl::disposing() +{ + try { +// // xxx todo: guarding? +// ::osl::MutexGuard guard( getMutex() ); + try_dispose( m_xLogFile ); + m_xLogFile.clear(); + try_dispose( m_xRegistry ); + m_xRegistry.clear(); + m_activePackagesDB.reset(0); + m_xComponentContext.clear(); + + t_pm_helper::disposing(); + + } + catch (RuntimeException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + throw lang::WrappedTargetRuntimeException( + OUSTR("caught unexpected exception while disposing..."), + static_cast<OWeakObject *>(this), exc ); + } +} + +// XComponent +//______________________________________________________________________________ +void PackageManagerImpl::dispose() throw (RuntimeException) +{ + check(); + WeakComponentImplHelperBase::dispose(); +} + +//______________________________________________________________________________ +void PackageManagerImpl::addEventListener( + Reference<lang::XEventListener> const & xListener ) throw (RuntimeException) +{ + check(); + WeakComponentImplHelperBase::addEventListener( xListener ); +} + +//______________________________________________________________________________ +void PackageManagerImpl::removeEventListener( + Reference<lang::XEventListener> const & xListener ) throw (RuntimeException) +{ + check(); + WeakComponentImplHelperBase::removeEventListener( xListener ); +} + +// XPackageManager +//______________________________________________________________________________ +OUString PackageManagerImpl::getContext() throw (RuntimeException) +{ + check(); + return m_context; +} + +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackageTypeInfo> > +PackageManagerImpl::getSupportedPackageTypes() throw (RuntimeException) +{ + OSL_ASSERT( m_xRegistry.is() ); + return m_xRegistry->getSupportedPackageTypes(); +} + +//______________________________________________________________________________ +Reference<task::XAbortChannel> PackageManagerImpl::createAbortChannel() + throw (RuntimeException) +{ + check(); + return new AbortChannel; +} + +// XModifyBroadcaster +//______________________________________________________________________________ +void PackageManagerImpl::addModifyListener( + Reference<util::XModifyListener> const & xListener ) + throw (RuntimeException) +{ + check(); + rBHelper.addListener( ::getCppuType( &xListener ), xListener ); +} + +//______________________________________________________________________________ +void PackageManagerImpl::removeModifyListener( + Reference<util::XModifyListener> const & xListener ) + throw (RuntimeException) +{ + check(); + rBHelper.removeListener( ::getCppuType( &xListener ), xListener ); +} + +//______________________________________________________________________________ +OUString PackageManagerImpl::detectMediaType( + ::ucbhelper::Content const & ucbContent_, bool throw_exc ) +{ + ::ucbhelper::Content ucbContent(ucbContent_); + OUString url( ucbContent.getURL() ); + OUString mediaType; + if (url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.tdoc:") ) || + url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.pkg:") )) + { + try { + ucbContent.getPropertyValue( OUSTR("MediaType") ) >>= mediaType; + } + catch (beans::UnknownPropertyException &) { + } + OSL_ENSURE( mediaType.getLength() > 0, "### no media-type?!" ); + } + if (mediaType.getLength() == 0) + { + try { + Reference<deployment::XPackage> xPackage( + m_xRegistry->bindPackage( + url, OUString(), false, OUString(), ucbContent.getCommandEnvironment() ) ); + const Reference<deployment::XPackageTypeInfo> xPackageType( + xPackage->getPackageType() ); + OSL_ASSERT( xPackageType.is() ); + if (xPackageType.is()) + mediaType = xPackageType->getMediaType(); + } + catch (lang::IllegalArgumentException & exc) { + if (throw_exc) + throw; + (void) exc; + OSL_ENSURE( 0, ::rtl::OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + } + return mediaType; +} + +//______________________________________________________________________________ +OUString PackageManagerImpl::insertToActivationLayer( + Sequence<beans::NamedValue> const & properties, + OUString const & mediaType, ::ucbhelper::Content const & sourceContent_, + OUString const & title, ActivePackages::Data * dbData ) +{ + ::ucbhelper::Content sourceContent(sourceContent_); + Reference<XCommandEnvironment> xCmdEnv( + sourceContent.getCommandEnvironment() ); + OUString destFolder, tempEntry; + if (::osl::File::createTempFile( + m_activePackages_expanded.getLength() == 0 + ? 0 : &m_activePackages_expanded, + 0, &tempEntry ) != ::osl::File::E_None) + throw RuntimeException( + OUSTR("::osl::File::createTempFile() failed!"), 0 ); + if (m_activePackages_expanded.getLength() == 0) { + destFolder = tempEntry; + } + else { + tempEntry = tempEntry.copy( tempEntry.lastIndexOf( '/' ) + 1 ); + // tweak user|share to macrofied url: + destFolder = makeURL( m_activePackages, tempEntry ); + } + destFolder += OUSTR("_"); + + // prepare activation folder: + ::ucbhelper::Content destFolderContent; + create_folder( &destFolderContent, destFolder, xCmdEnv ); + + // copy content into activation temp dir: + if (mediaType.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/vnd.sun.star.package-bundle") ) || + // xxx todo: more sophisticated parsing + mediaType.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/vnd.sun.star.legacy-package-bundle") )) + { + // inflate content: + ::rtl::OUStringBuffer buf; + if (!sourceContent.isFolder()) + { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.zip://") ); + buf.append( ::rtl::Uri::encode( sourceContent.getURL(), + rtl_UriCharClassRegName, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + } + else + { + //Folder. No need to unzip, just copy + buf.append(sourceContent.getURL()); + } + buf.append( static_cast<sal_Unicode>('/') ); + sourceContent = ::ucbhelper::Content( + buf.makeStringAndClear(), xCmdEnv ); + } + if (! destFolderContent.transferContent( + sourceContent, ::ucbhelper::InsertOperation_COPY, + title, NameClash::OVERWRITE )) + throw RuntimeException( OUSTR("UCB transferContent() failed!"), 0 ); + + + // write to DB: + //bundled extensions should only be added by the synchronizeAddedExtensions + //functions. Moreover, there is no "temporary folder" for bundled extensions. + OSL_ASSERT(!m_context.equals(OUSTR("bundled"))); + OUString sFolderUrl = makeURLAppendSysPathSegment(destFolderContent.getURL(), title); + DescriptionInfoset info = + dp_misc::getDescriptionInfoset(sFolderUrl); + dbData->temporaryName = tempEntry; + dbData->fileName = title; + dbData->mediaType = mediaType; + dbData->version = info.getVersion(); + + //No write the properties file next to the extension + ExtensionProperties props(sFolderUrl, properties, xCmdEnv); + props.write(); + return destFolder; +} + +//______________________________________________________________________________ +void PackageManagerImpl::insertToActivationLayerDB( + OUString const & id, ActivePackages::Data const & dbData ) +{ + //access to the database must be guarded. See removePackage + const ::osl::MutexGuard guard( getMutex() ); + m_activePackagesDB->put( id, dbData ); +} + +//______________________________________________________________________________ +/* The function returns true if there is an extension with the same id already + installed which needs to be uninstalled, before the new extension can be installed. +*/ +bool PackageManagerImpl::isInstalled( + Reference<deployment::XPackage> const & package) +{ + OUString id(dp_misc::getIdentifier(package)); + OUString fn(package->getName()); + bool bInstalled = false; + if (m_activePackagesDB->has( id, fn )) + { + bInstalled = true; + } + return bInstalled; +} + +// XPackageManager +//______________________________________________________________________________ +Reference<deployment::XPackage> PackageManagerImpl::importExtension( + Reference<deployment::XPackage> const & extension, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<XCommandEnvironment> const & xCmdEnv_ ) + throw (deployment::DeploymentException, CommandFailedException, + CommandAbortedException, lang::IllegalArgumentException, + RuntimeException) +{ + return addPackage(extension->getURL(), Sequence<beans::NamedValue>(), + OUString(), xAbortChannel, xCmdEnv_); +} + +/* The function adds an extension but does not register it!!! + It may not do any user interaction. This is done in XExtensionManager::addExtension +*/ +Reference<deployment::XPackage> PackageManagerImpl::addPackage( + OUString const & url, + css::uno::Sequence<css::beans::NamedValue> const & properties, + OUString const & mediaType_, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<XCommandEnvironment> const & xCmdEnv_ ) + throw (deployment::DeploymentException, CommandFailedException, + CommandAbortedException, lang::IllegalArgumentException, + RuntimeException) +{ + check(); + if (m_readOnly) + { + OUString message; + if (m_context == OUSTR("shared")) + message = OUSTR("You need write permissions to install a shared extension!"); + else + message = OUSTR("You need write permissions to install this extension!"); + throw deployment::DeploymentException( + message, static_cast<OWeakObject *>(this), Any() ); + } + Reference<XCommandEnvironment> xCmdEnv; + if (m_xLogFile.is()) + xCmdEnv.set( new CmdEnvWrapperImpl( xCmdEnv_, m_xLogFile ) ); + else + xCmdEnv.set( xCmdEnv_ ); + + try { + ::ucbhelper::Content sourceContent; + create_ucb_content( &sourceContent, url, xCmdEnv ); // throws exc + const OUString title(sourceContent.getPropertyValue( + StrTitle::get() ).get<OUString>() ); + const OUString title_enc( ::rtl::Uri::encode( + title, rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + OUString destFolder; + + OUString mediaType(mediaType_); + if (mediaType.getLength() == 0) + mediaType = detectMediaType( sourceContent ); + + Reference<deployment::XPackage> xPackage; + // copy file: + progressUpdate( + getResourceString(RID_STR_COPYING_PACKAGE) + title, xCmdEnv ); + if (m_activePackages.getLength() == 0) + { + ::ucbhelper::Content docFolderContent; + create_folder( &docFolderContent, m_context, xCmdEnv ); + // copy into document, first: + if (! docFolderContent.transferContent( + sourceContent, ::ucbhelper::InsertOperation_COPY, + OUString(), + NameClash::ASK /* xxx todo: ASK not needed? */)) + throw RuntimeException( + OUSTR("UCB transferContent() failed!"), 0 ); + // set media-type: + ::ucbhelper::Content docContent( + makeURL( m_context, title_enc ), xCmdEnv ); + //TODO #i73136#: using title instead of id can lead to + // clashes, but the whole m_activePackages.getLength()==0 + // case (i.e., document-relative deployment) currently does + // not work, anyway. + docContent.setPropertyValue( + OUSTR("MediaType"), Any(mediaType) ); + + // xxx todo: obsolete in the future + try { + docFolderContent.executeCommand( OUSTR("flush"), Any() ); + } + catch (UnsupportedCommandException &) { + } + } + ActivePackages::Data dbData; + destFolder = insertToActivationLayer( + properties, mediaType, sourceContent, title, &dbData ); + + + // bind activation package: + //Because every shared/user extension will be unpacked in a folder, + //which was created with a unique name we will always have two different + //XPackage objects, even if the second extension is the same. + //Therefore bindPackage does not need a guard here. + xPackage = m_xRegistry->bindPackage( + makeURL( destFolder, title_enc ), mediaType, false, OUString(), xCmdEnv ); + + OSL_ASSERT( xPackage.is() ); + if (xPackage.is()) + { + bool install = false; + try + { + OUString const id = dp_misc::getIdentifier( xPackage ); + + ::osl::MutexGuard g(m_addMutex); + if (isInstalled(xPackage)) + { + //Do not guard the complete function with the getMutex + removePackage(id, xPackage->getName(), xAbortChannel, + xCmdEnv); + } + install = true; + insertToActivationLayerDB(id, dbData); + } + catch (...) + { + deletePackageFromCache( xPackage, destFolder ); + throw; + } + if (!install) + { + deletePackageFromCache( xPackage, destFolder ); + } + //ToDo: We should notify only if the extension is registered + fireModified(); + } + return xPackage; + } + catch (RuntimeException &) { + throw; + } + catch (CommandFailedException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (CommandAbortedException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (deployment::DeploymentException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + logIntern( exc ); + throw deployment::DeploymentException( + getResourceString(RID_STR_ERROR_WHILE_ADDING) + url, + static_cast<OWeakObject *>(this), exc ); + } +} +void PackageManagerImpl::deletePackageFromCache( + Reference<deployment::XPackage> const & xPackage, + OUString const & destFolder) +{ + try_dispose( xPackage ); + + //we remove the package from the uno cache + //no service from the package may be loaded at this time!!! + erase_path( destFolder, Reference<XCommandEnvironment>(), + false /* no throw: ignore errors */ ); + //rm last character '_' + OUString url = destFolder.copy(0, destFolder.getLength() - 1); + erase_path( url, Reference<XCommandEnvironment>(), + false /* no throw: ignore errors */ ); + +} +//______________________________________________________________________________ +void PackageManagerImpl::removePackage( + OUString const & id, ::rtl::OUString const & fileName, + Reference<task::XAbortChannel> const & /*xAbortChannel*/, + Reference<XCommandEnvironment> const & xCmdEnv_ ) + throw (deployment::DeploymentException, CommandFailedException, + CommandAbortedException, lang::IllegalArgumentException, + RuntimeException) +{ + check(); + + Reference<XCommandEnvironment> xCmdEnv; + if (m_xLogFile.is()) + xCmdEnv.set( new CmdEnvWrapperImpl( xCmdEnv_, m_xLogFile ) ); + else + xCmdEnv.set( xCmdEnv_ ); + + try { + Reference<deployment::XPackage> xPackage; + { + const ::osl::MutexGuard guard(getMutex()); + //Check if this extension exist and throw an IllegalArgumentException + //if it does not + //If the files of the extension are already removed, or there is a + //different extension at the same place, for example after updating the + //extension, then the returned object is that which uses the database data. + xPackage = getDeployedPackage_(id, fileName, xCmdEnv ); + + + //Because the extension is only removed the next time the extension + //manager runs after restarting OOo, we need to indicate that a + //shared extension was "deleted". When a user starts OOo, then it + //will check if something changed in the shared repository. Based on + //the flag file it will then recognize, that the extension was + //deleted and can then update the extnesion database of the shared + //extensions in the user installation. + if ( xPackage.is() && !m_readOnly && !xPackage->isRemoved() && m_context.equals(OUSTR("shared"))) + { + ActivePackages::Data val; + m_activePackagesDB->get( & val, id, fileName); + OSL_ASSERT(val.temporaryName.getLength()); + OUString url(makeURL(m_activePackages_expanded, + val.temporaryName + OUSTR("removed"))); + ::ucbhelper::Content contentRemoved(url, xCmdEnv ); + OUString aUserName; + ::osl::Security aSecurity; + aSecurity.getUserName( aUserName ); + + ::rtl::OString stamp = ::rtl::OUStringToOString(aUserName, RTL_TEXTENCODING_UTF8); + Reference<css::io::XInputStream> xData( + ::xmlscript::createInputStream( + ::rtl::ByteSequence( + reinterpret_cast<sal_Int8 const *>(stamp.getStr()), + stamp.getLength() ) ) ); + contentRemoved.writeStream( xData, true /* replace existing */ ); + } + m_activePackagesDB->erase( id, fileName ); // to be removed upon next start + } + try_dispose( xPackage ); + + fireModified(); + } + catch (RuntimeException &) { + throw; + } + catch (lang::IllegalArgumentException &) { + throw; + } + catch (CommandFailedException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (CommandAbortedException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (deployment::DeploymentException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + logIntern( exc ); + throw deployment::DeploymentException( + getResourceString(RID_STR_ERROR_WHILE_REMOVING) + id, + static_cast<OWeakObject *>(this), exc ); + } +} + +//______________________________________________________________________________ +OUString PackageManagerImpl::getDeployPath( ActivePackages::Data const & data ) +{ + ::rtl::OUStringBuffer buf; + buf.append( data.temporaryName ); + //The bundled extensions are not contained in an additional folder + //with a unique name. data.temporaryName contains already the + //UTF8 encoded folder name. See PackageManagerImpl::synchronize + if (!m_context.equals(OUSTR("bundled"))) + { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("_/") ); + buf.append( ::rtl::Uri::encode( data.fileName, rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + } + return makeURL( m_activePackages, buf.makeStringAndClear() ); +} + +//______________________________________________________________________________ +Reference<deployment::XPackage> PackageManagerImpl::getDeployedPackage_( + OUString const & id, OUString const & fileName, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + ActivePackages::Data val; + if (m_activePackagesDB->get( &val, id, fileName )) + { + return getDeployedPackage_( id, val, xCmdEnv, false ); + } + throw lang::IllegalArgumentException( + getResourceString(RID_STR_NO_SUCH_PACKAGE) + id, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); +} + +//______________________________________________________________________________ +Reference<deployment::XPackage> PackageManagerImpl::getDeployedPackage_( + OUString const & id, ActivePackages::Data const & data, + Reference<XCommandEnvironment> const & xCmdEnv, bool ignoreAlienPlatforms ) +{ + if (ignoreAlienPlatforms) + { + String type, subType; + INetContentTypeParameterList params; + if (INetContentTypes::parse( data.mediaType, type, subType, ¶ms )) + { + INetContentTypeParameter const * param = params.find( + ByteString("platform") ); + if (param != 0 && !platform_fits( param->m_sValue )) + throw lang::IllegalArgumentException( + getResourceString(RID_STR_NO_SUCH_PACKAGE) + id, + static_cast<OWeakObject *>(this), + static_cast<sal_Int16>(-1) ); + } + } + Reference<deployment::XPackage> xExtension; + try + { + //Ignore extensions where XPackage::checkPrerequisites failed. + //They must not be usable for this user. + if (data.failedPrerequisites.equals(OUSTR("0"))) + { + xExtension = m_xRegistry->bindPackage( + getDeployPath( data ), data.mediaType, false, OUString(), xCmdEnv ); + } + } + catch (deployment::InvalidRemovedParameterException& e) + { + xExtension = e.Extension; + } + return xExtension; +} + +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackage> > +PackageManagerImpl::getDeployedPackages_( + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + ::std::vector< Reference<deployment::XPackage> > packages; + ActivePackages::Entries id2temp( m_activePackagesDB->getEntries() ); + ActivePackages::Entries::const_iterator iPos( id2temp.begin() ); + ActivePackages::Entries::const_iterator const iEnd( id2temp.end() ); + for ( ; iPos != iEnd; ++iPos ) + { + if (! iPos->second.failedPrerequisites.equals(OUSTR("0"))) + continue; + try { + packages.push_back( + getDeployedPackage_( + iPos->first, iPos->second, xCmdEnv, + true /* xxx todo: think of GUI: + ignore other platforms than the current one */ ) ); + } + catch (lang::IllegalArgumentException & exc) { + // ignore + (void) exc; // avoid warnings + OSL_ENSURE( 0, ::rtl::OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + catch (deployment::DeploymentException& exc) { + // ignore + (void) exc; // avoid warnings + OSL_ENSURE( 0, ::rtl::OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + } + return comphelper::containerToSequence(packages); +} + +//______________________________________________________________________________ +Reference<deployment::XPackage> PackageManagerImpl::getDeployedPackage( + OUString const & id, ::rtl::OUString const & fileName, + Reference<XCommandEnvironment> const & xCmdEnv_ ) + throw (deployment::DeploymentException, CommandFailedException, + lang::IllegalArgumentException, RuntimeException) +{ + check(); + Reference<XCommandEnvironment> xCmdEnv; + if (m_xLogFile.is()) + xCmdEnv.set( new CmdEnvWrapperImpl( xCmdEnv_, m_xLogFile ) ); + else + xCmdEnv.set( xCmdEnv_ ); + + try { + const ::osl::MutexGuard guard( getMutex() ); + return getDeployedPackage_( id, fileName, xCmdEnv ); + } + catch (RuntimeException &) { + throw; + } + catch (CommandFailedException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (lang::IllegalArgumentException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (deployment::DeploymentException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + logIntern( exc ); + throw deployment::DeploymentException( + // ought never occur... + OUSTR("error while accessing deployed package: ") + id, + static_cast<OWeakObject *>(this), exc ); + } +} + +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackage> > +PackageManagerImpl::getDeployedPackages( + Reference<task::XAbortChannel> const &, + Reference<XCommandEnvironment> const & xCmdEnv_ ) + throw (deployment::DeploymentException, CommandFailedException, + CommandAbortedException, lang::IllegalArgumentException, + RuntimeException) +{ + check(); + Reference<XCommandEnvironment> xCmdEnv; + if (m_xLogFile.is()) + xCmdEnv.set( new CmdEnvWrapperImpl( xCmdEnv_, m_xLogFile ) ); + else + xCmdEnv.set( xCmdEnv_ ); + + try { + const ::osl::MutexGuard guard( getMutex() ); + return getDeployedPackages_( xCmdEnv ); + } + catch (RuntimeException &) { + throw; + } + catch (CommandFailedException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (CommandAbortedException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (deployment::DeploymentException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + logIntern( exc ); + throw deployment::DeploymentException( + // ought never occur... + OUSTR("error while getting all deployed packages: ") + m_context, + static_cast<OWeakObject *>(this), exc ); + } +} + +//______________________________________________________________________________ + + +//ToDo: the function must not call registerPackage, do this in +//XExtensionManager.reinstallDeployedExtensions +void PackageManagerImpl::reinstallDeployedPackages( + Reference<task::XAbortChannel> const & /*xAbortChannel*/, + Reference<XCommandEnvironment> const & xCmdEnv_ ) + throw (deployment::DeploymentException, + CommandFailedException, CommandAbortedException, + lang::IllegalArgumentException, RuntimeException) +{ + check(); + if (office_is_running()) + throw RuntimeException( + OUSTR("You must close any running Office process before " + "reinstalling packages!"), static_cast<OWeakObject *>(this) ); + + Reference<XCommandEnvironment> xCmdEnv; + if (m_xLogFile.is()) + xCmdEnv.set( new CmdEnvWrapperImpl( xCmdEnv_, m_xLogFile ) ); + else + xCmdEnv.set( xCmdEnv_ ); + + try { + ProgressLevel progress( + xCmdEnv, OUSTR("Reinstalling all deployed packages...") ); + + try_dispose( m_xRegistry ); + m_xRegistry.clear(); + if (m_registryCache.getLength() > 0) + erase_path( m_registryCache, xCmdEnv ); + initRegistryBackends(); + Reference<util::XUpdatable> xUpdatable( m_xRegistry, UNO_QUERY ); + if (xUpdatable.is()) + xUpdatable->update(); + + //registering is done by the ExtensionManager service. + } + catch (RuntimeException &) { + throw; + } + catch (CommandFailedException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (CommandAbortedException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (deployment::DeploymentException & exc) { + logIntern( Any(exc) ); + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + logIntern( exc ); + throw deployment::DeploymentException( + OUSTR("Error while reinstalling all previously deployed " + "packages of context ") + m_context, + static_cast<OWeakObject *>(this), exc ); + } +} + + +::sal_Bool SAL_CALL PackageManagerImpl::isReadOnly( ) + throw (::com::sun::star::uno::RuntimeException) +{ + return m_readOnly; +} +bool PackageManagerImpl::synchronizeRemovedExtensions( + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<css::ucb::XCommandEnvironment> const & xCmdEnv) +{ + + //find all which are in the extension data base but which + //are removed already. + OSL_ASSERT(!m_context.equals(OUSTR("user"))); + bool bModified = false; + ActivePackages::Entries id2temp( m_activePackagesDB->getEntries() ); + + typedef ActivePackages::Entries::const_iterator ITActive; + bool bShared = m_context.equals(OUSTR("shared")); + + for (ITActive i = id2temp.begin(); i != id2temp.end(); i++) + { + try + { + //Get the URL to the extensions folder, first make the url for the + //shared repository including the temporary name + OUString url = makeURL(m_activePackages, i->second.temporaryName); + if (bShared) + url = makeURLAppendSysPathSegment( url + OUSTR("_"), i->second.fileName); + + bool bRemoved = false; + //Check if the URL to the extension is still the same + ::ucbhelper::Content contentExtension; + + if (!create_ucb_content( + &contentExtension, url, + Reference<XCommandEnvironment>(), false)) + { + bRemoved = true; + } + + //The folder is in the extension database, but it can still be deleted. + //look for the xxx.tmpremoved file + //There can also be the case that a different extension was installed + //in a "temp" folder with name that is already used. + if (!bRemoved && bShared) + { + ::ucbhelper::Content contentRemoved; + + if (create_ucb_content( + &contentRemoved, + m_activePackages_expanded + OUSTR("/") + + i->second.temporaryName + OUSTR("removed"), + Reference<XCommandEnvironment>(), false)) + { + bRemoved = true; + } + } + + if (!bRemoved) + { + //There may be another extensions at the same place + dp_misc::DescriptionInfoset infoset = + dp_misc::getDescriptionInfoset(url); + OSL_ENSURE(infoset.hasDescription(), + "Extension Manager: bundled and shared extensions " + "must have an identifer and a version"); + if (infoset.hasDescription() && + infoset.getIdentifier() && + (! i->first.equals(*(infoset.getIdentifier())) + || ! i->second.version.equals(infoset.getVersion()))) + { + bRemoved = true; + } + + } + if (bRemoved) + { + Reference<deployment::XPackage> xPackage = m_xRegistry->bindPackage( + url, i->second.mediaType, true, i->first, xCmdEnv ); + OSL_ASSERT(xPackage.is()); //Even if the files are removed, we must get the object. + xPackage->revokePackage(xAbortChannel, xCmdEnv); + removePackage(xPackage->getIdentifier().Value, xPackage->getName(), + xAbortChannel, xCmdEnv); + bModified |= true; + } + } + catch( uno::Exception & ) + { + OSL_ASSERT(0); + } + } + return bModified; +} + + +bool PackageManagerImpl::synchronizeAddedExtensions( + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<css::ucb::XCommandEnvironment> const & xCmdEnv) +{ + bool bModified = false; + ActivePackages::Entries id2temp( m_activePackagesDB->getEntries() ); + //check if the folder exist at all. The shared extension folder + //may not exist for a normal user. + if (!create_ucb_content( + NULL, m_activePackages_expanded, Reference<css::ucb::XCommandEnvironment>(), false)) + return bModified; + ::ucbhelper::Content tempFolder( + m_activePackages_expanded, xCmdEnv ); + + Reference<sdbc::XResultSet> xResultSet( + tempFolder.createCursor( + Sequence<OUString>( &StrTitle::get(), 1 ), + ::ucbhelper::INCLUDE_FOLDERS_ONLY ) ); + + while (xResultSet->next()) + { + try + { + OUString title( + Reference<sdbc::XRow>( + xResultSet, UNO_QUERY_THROW )->getString( + 1 /* Title */ ) ); + //The temporary folders of user and shared have an '_' at then end. + //But the name in ActivePackages.temporaryName is saved without. + OUString title2 = title; + bool bNotBundled = !m_context.equals(OUSTR("bundled")); + if (bNotBundled) + { + OSL_ASSERT(title2[title2.getLength() -1] == '_'); + title2 = title2.copy(0, title2.getLength() -1); + } + OUString titleEncoded = ::rtl::Uri::encode( + title2, rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8); + + //It it sufficient to check for the folder name, because when the administor + //installed the extension it was already checked if there is one with the + //same identifier. + const MatchTempDir match(titleEncoded); + if (::std::find_if( id2temp.begin(), id2temp.end(), match ) == + id2temp.end()) + { + + // The folder was not found in the data base, so it must be + // an added extension + OUString url(m_activePackages_expanded + OUSTR("/") + titleEncoded); + OUString sExtFolder; + if (bNotBundled) //that is, shared + { + //Check if the extension was not "deleted" already which is indicated + //by a xxx.tmpremoved file + ::ucbhelper::Content contentRemoved; + if (create_ucb_content(&contentRemoved, url + OUSTR("removed"), + Reference<XCommandEnvironment>(), false)) + continue; + sExtFolder = getExtensionFolder( + m_activePackages_expanded + + OUString(OUSTR("/")) + titleEncoded + OUSTR("_"), xCmdEnv); + url = makeURLAppendSysPathSegment(m_activePackages_expanded, title); + url = makeURLAppendSysPathSegment(url, sExtFolder); + } + Reference<deployment::XPackage> xPackage = m_xRegistry->bindPackage( + url, OUString(), false, OUString(), xCmdEnv ); + if (xPackage.is()) + { + //Prepare the database entry + ActivePackages::Data dbData; + + dbData.temporaryName = titleEncoded; + if (bNotBundled) + dbData.fileName = sExtFolder; + else + dbData.fileName = title; + dbData.mediaType = xPackage->getPackageType()->getMediaType(); + dbData.version = xPackage->getVersion(); + OSL_ENSURE(dbData.version.getLength() > 0, + "Extension Manager: bundled and shared extensions must have " + "an identifier and a version"); + + OUString id = dp_misc::getIdentifier( xPackage ); + + //We provide a special command environment that will prevent + //showing a license if simple-licens/@accept-by = "admin" + //It will also prevent showing the license for bundled extensions + //which is not supported. + OSL_ASSERT(!m_context.equals(OUSTR("user"))); + + // shall the license be suppressed? + DescriptionInfoset info = + dp_misc::getDescriptionInfoset(url); + ::boost::optional<dp_misc::SimpleLicenseAttributes> + attr = info.getSimpleLicenseAttributes(); + ExtensionProperties props(url,xCmdEnv); + bool bNoLicense = false; + if (attr && attr->suppressIfRequired && props.isSuppressedLicense()) + bNoLicense = true; + + Reference<ucb::XCommandEnvironment> licCmdEnv( + new LicenseCommandEnv(xCmdEnv->getInteractionHandler(), + bNoLicense, m_context)); + sal_Int32 failedPrereq = xPackage->checkPrerequisites( + xAbortChannel, licCmdEnv, false); + //Remember that this failed. For example, the user + //could have declined the license. Then the next time the + //extension folder is investigated we do not want to + //try to install the extension again. + dbData.failedPrerequisites = OUString::valueOf(failedPrereq); + insertToActivationLayerDB(id, dbData); + bModified |= true; + } + } + } + catch (uno::Exception &) + { + OSL_ASSERT(0); + } + } + return bModified; +} + +sal_Bool PackageManagerImpl::synchronize( + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<css::ucb::XCommandEnvironment> const & xCmdEnv) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::uno::RuntimeException) +{ + check(); + bool bModified = false; + if (m_context.equals(OUSTR("user"))) + return bModified; + bModified |= + synchronizeRemovedExtensions(xAbortChannel, xCmdEnv); + bModified |= synchronizeAddedExtensions(xAbortChannel, xCmdEnv); + + return bModified; +} + +Sequence< Reference<deployment::XPackage> > PackageManagerImpl::getExtensionsWithUnacceptedLicenses( + Reference<ucb::XCommandEnvironment> const & xCmdEnv) + throw (deployment::DeploymentException, RuntimeException) +{ + ::std::vector<Reference<deployment::XPackage> > vec; + + try + { + const ::osl::MutexGuard guard( getMutex() ); + // clean up activation layer, scan for zombie temp dirs: + ActivePackages::Entries id2temp( m_activePackagesDB->getEntries() ); + + ActivePackages::Entries::const_iterator i = id2temp.begin(); + bool bShared = m_context.equals(OUSTR("shared")); + + for (; i != id2temp.end(); i++ ) + { + //Get the database entry + ActivePackages::Data const & dbData = i->second; + sal_Int32 failedPrereq = dbData.failedPrerequisites.toInt32(); + //If the installation failed for other reason then the license then we + //ignore it. + if (failedPrereq ^= deployment::Prerequisites::LICENSE) + continue; + + //Prepare the URL to the extension + OUString url = makeURL(m_activePackages, i->second.temporaryName); + if (bShared) + url = makeURLAppendSysPathSegment( url + OUSTR("_"), i->second.fileName); + + Reference<deployment::XPackage> p = m_xRegistry->bindPackage( + url, OUString(), false, OUString(), xCmdEnv ); + + if (p.is()) + vec.push_back(p); + + } + return ::comphelper::containerToSequence(vec); + } + catch (deployment::DeploymentException &) + { + throw; + } + catch (RuntimeException&) + { + throw; + } + catch (...) + { + Any exc = ::cppu::getCaughtException(); + deployment::DeploymentException de( + OUSTR("PackageManagerImpl::getExtensionsWithUnacceptedLicenses"), + static_cast<OWeakObject*>(this), exc); + exc <<= de; + ::cppu::throwException(exc); + } + + return ::comphelper::containerToSequence(vec); +} + +sal_Int32 PackageManagerImpl::checkPrerequisites( + css::uno::Reference<css::deployment::XPackage> const & extension, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException) +{ + try + { + if (!extension.is()) + return 0; + if (!m_context.equals(extension->getRepositoryName())) + throw lang::IllegalArgumentException( + OUSTR("PackageManagerImpl::checkPrerequisites: extension is not" + " from this repository."), 0, 0); + + ActivePackages::Data dbData; + OUString id = dp_misc::getIdentifier(extension); + if (m_activePackagesDB->get( &dbData, id, OUString())) + { + //If the license was already displayed, then do not show it again + Reference<ucb::XCommandEnvironment> _xCmdEnv = xCmdEnv; + sal_Int32 prereq = dbData.failedPrerequisites.toInt32(); + if ( !(prereq & deployment::Prerequisites::LICENSE)) + _xCmdEnv = new NoLicenseCommandEnv(xCmdEnv->getInteractionHandler()); + + sal_Int32 failedPrereq = extension->checkPrerequisites( + xAbortChannel, _xCmdEnv, false); + dbData.failedPrerequisites = OUString::valueOf(failedPrereq); + insertToActivationLayerDB(id, dbData); + } + else + { + throw lang::IllegalArgumentException( + OUSTR("PackageManagerImpl::checkPrerequisites: unknown extension"), + 0, 0); + + } + return 0; + } + catch (deployment::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (...) { + uno::Any excOccurred = ::cppu::getCaughtException(); + deployment::DeploymentException exc( + OUSTR("PackageManagerImpl::checkPrerequisites: exception "), + static_cast<OWeakObject*>(this), excOccurred); + throw exc; + } +} + +//############################################################################## + +//______________________________________________________________________________ +PackageManagerImpl::CmdEnvWrapperImpl::~CmdEnvWrapperImpl() +{ +} + +//______________________________________________________________________________ +PackageManagerImpl::CmdEnvWrapperImpl::CmdEnvWrapperImpl( + Reference<XCommandEnvironment> const & xUserCmdEnv, + Reference<XProgressHandler> const & xLogFile ) + : m_xLogFile( xLogFile ) +{ + if (xUserCmdEnv.is()) { + m_xUserProgress.set( xUserCmdEnv->getProgressHandler() ); + m_xUserInteractionHandler.set( xUserCmdEnv->getInteractionHandler() ); + } +} + +// XCommandEnvironment +//______________________________________________________________________________ +Reference<task::XInteractionHandler> +PackageManagerImpl::CmdEnvWrapperImpl::getInteractionHandler() + throw (RuntimeException) +{ + return m_xUserInteractionHandler; +} + +//______________________________________________________________________________ +Reference<XProgressHandler> +PackageManagerImpl::CmdEnvWrapperImpl::getProgressHandler() + throw (RuntimeException) +{ + return this; +} + +// XProgressHandler +//______________________________________________________________________________ +void PackageManagerImpl::CmdEnvWrapperImpl::push( Any const & Status ) + throw (RuntimeException) +{ + if (m_xLogFile.is()) + m_xLogFile->push( Status ); + if (m_xUserProgress.is()) + m_xUserProgress->push( Status ); +} + +//______________________________________________________________________________ +void PackageManagerImpl::CmdEnvWrapperImpl::update( Any const & Status ) + throw (RuntimeException) +{ + if (m_xLogFile.is()) + m_xLogFile->update( Status ); + if (m_xUserProgress.is()) + m_xUserProgress->update( Status ); +} + +//______________________________________________________________________________ +void PackageManagerImpl::CmdEnvWrapperImpl::pop() throw (RuntimeException) +{ + if (m_xLogFile.is()) + m_xLogFile->pop(); + if (m_xUserProgress.is()) + m_xUserProgress->pop(); +} + +} // namespace dp_manager + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_manager.h b/desktop/source/deployment/manager/dp_manager.h new file mode 100644 index 000000000000..fa4a9078ac42 --- /dev/null +++ b/desktop/source/deployment/manager/dp_manager.h @@ -0,0 +1,296 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_MANAGER_H +#define INCLUDED_DP_MANAGER_H + +#include "dp_manager.hrc" +#include "dp_misc.h" +#include "dp_interact.h" +#include "dp_activepackages.hxx" +#include "rtl/ref.hxx" +#include "cppuhelper/compbase1.hxx" +#include "cppuhelper/implbase2.hxx" +#include "ucbhelper/content.hxx" +#include "com/sun/star/deployment/XPackageRegistry.hpp" +#include "com/sun/star/deployment/XPackageManager.hpp" +#include <memory> + + +namespace css = ::com::sun::star; + +namespace dp_manager { + +typedef ::cppu::WeakComponentImplHelper1< + css::deployment::XPackageManager > t_pm_helper; + +//============================================================================== +class PackageManagerImpl : private ::dp_misc::MutexHolder, public t_pm_helper +{ + css::uno::Reference<css::uno::XComponentContext> m_xComponentContext; + ::rtl::OUString m_context; + ::rtl::OUString m_registrationData; + ::rtl::OUString m_registrationData_expanded; + ::rtl::OUString m_registryCache; + bool m_readOnly; + + ::rtl::OUString m_activePackages; + ::rtl::OUString m_activePackages_expanded; + ::std::auto_ptr< ActivePackages > m_activePackagesDB; + //This mutex is only used for synchronization in addPackage + ::osl::Mutex m_addMutex; + css::uno::Reference<css::ucb::XProgressHandler> m_xLogFile; + inline void logIntern( css::uno::Any const & status ); + void fireModified(); + + css::uno::Reference<css::deployment::XPackageRegistry> m_xRegistry; + + void initRegistryBackends(); + void initActivationLayer( + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ); + ::rtl::OUString detectMediaType( + ::ucbhelper::Content const & ucbContent, bool throw_exc = true ); + ::rtl::OUString insertToActivationLayer( + css::uno::Sequence<css::beans::NamedValue> const & properties, + ::rtl::OUString const & mediaType, + ::ucbhelper::Content const & sourceContent, + ::rtl::OUString const & title, ActivePackages::Data * dbData ); + void insertToActivationLayerDB( + ::rtl::OUString const & id, ActivePackages::Data const & dbData ); + + void deletePackageFromCache( + css::uno::Reference<css::deployment::XPackage> const & xPackage, + ::rtl::OUString const & destFolder ); + + bool isInstalled( + css::uno::Reference<css::deployment::XPackage> const & package); + + bool synchronizeRemovedExtensions( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + bool synchronizeAddedExtensions( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + class CmdEnvWrapperImpl + : public ::cppu::WeakImplHelper2< css::ucb::XCommandEnvironment, + css::ucb::XProgressHandler > + { + css::uno::Reference<css::ucb::XProgressHandler> m_xLogFile; + css::uno::Reference<css::ucb::XProgressHandler> m_xUserProgress; + css::uno::Reference<css::task::XInteractionHandler> + m_xUserInteractionHandler; + + public: + virtual ~CmdEnvWrapperImpl(); + CmdEnvWrapperImpl( + css::uno::Reference<css::ucb::XCommandEnvironment> + const & xUserCmdEnv, + css::uno::Reference<css::ucb::XProgressHandler> const & xLogFile ); + + // XCommandEnvironment + virtual css::uno::Reference<css::task::XInteractionHandler> SAL_CALL + getInteractionHandler() throw (css::uno::RuntimeException); + virtual css::uno::Reference<css::ucb::XProgressHandler> SAL_CALL + getProgressHandler() throw (css::uno::RuntimeException); + + // XProgressHandler + virtual void SAL_CALL push( css::uno::Any const & Status ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL update( css::uno::Any const & Status ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL pop() throw (css::uno::RuntimeException); + }; + +protected: + inline void check(); + virtual void SAL_CALL disposing(); + + virtual ~PackageManagerImpl(); + inline PackageManagerImpl( + css::uno::Reference<css::uno::XComponentContext> + const & xComponentContext, ::rtl::OUString const & context ) + : t_pm_helper( getMutex() ), + m_xComponentContext( xComponentContext ), + m_context( context ), + m_readOnly( true ) + {} + +public: + static css::uno::Reference<css::deployment::XPackageManager> create( + css::uno::Reference<css::uno::XComponentContext> + const & xComponentContext, ::rtl::OUString const & context ); + + // XComponent + virtual void SAL_CALL dispose() throw (css::uno::RuntimeException); + virtual void SAL_CALL addEventListener( + css::uno::Reference<css::lang::XEventListener> const & xListener ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( + css::uno::Reference<css::lang::XEventListener> const & xListener ) + throw (css::uno::RuntimeException); + + // XModifyBroadcaster + virtual void SAL_CALL addModifyListener( + css::uno::Reference<css::util::XModifyListener> const & xListener ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL removeModifyListener( + css::uno::Reference<css::util::XModifyListener> const & xListener ) + throw (css::uno::RuntimeException); + + // XPackageManager + virtual ::rtl::OUString SAL_CALL getContext() + throw (css::uno::RuntimeException); + virtual css::uno::Sequence< + css::uno::Reference<css::deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() throw (css::uno::RuntimeException); + + virtual css::uno::Reference<css::task::XAbortChannel> SAL_CALL + createAbortChannel() throw (css::uno::RuntimeException); + + virtual css::uno::Reference<css::deployment::XPackage> SAL_CALL addPackage( + ::rtl::OUString const & url, + css::uno::Sequence<css::beans::NamedValue> const & properties, + ::rtl::OUString const & mediaType, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual css::uno::Reference<css::deployment::XPackage> SAL_CALL importExtension( + css::uno::Reference<css::deployment::XPackage> const & extension, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual void SAL_CALL removePackage( + ::rtl::OUString const & id, ::rtl::OUString const & fileName, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + ::rtl::OUString getDeployPath( ActivePackages::Data const & data ); + css::uno::Reference<css::deployment::XPackage> SAL_CALL getDeployedPackage_( + ::rtl::OUString const & id, ::rtl::OUString const & fileName, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ); + css::uno::Reference<css::deployment::XPackage> getDeployedPackage_( + ::rtl::OUString const & id, ActivePackages::Data const & data, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + bool ignoreAlienPlatforms = false ); + virtual css::uno::Reference<css::deployment::XPackage> SAL_CALL + getDeployedPackage( + ::rtl::OUString const & id, ::rtl::OUString const & fileName, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::lang::IllegalArgumentException, css::uno::RuntimeException); + + css::uno::Sequence< css::uno::Reference<css::deployment::XPackage> > + getDeployedPackages_( + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ); + virtual css::uno::Sequence< css::uno::Reference<css::deployment::XPackage> > + SAL_CALL getDeployedPackages( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual void SAL_CALL reinstallDeployedPackages( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual ::sal_Bool SAL_CALL isReadOnly( ) + throw (::com::sun::star::uno::RuntimeException); + + virtual ::sal_Bool SAL_CALL synchronize( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::uno::RuntimeException); + + virtual css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > SAL_CALL + getExtensionsWithUnacceptedLicenses( + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv) + throw (css::deployment::DeploymentException, + css::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL checkPrerequisites( + css::uno::Reference<css::deployment::XPackage> const & extension, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + }; + +//______________________________________________________________________________ +inline void PackageManagerImpl::check() +{ + ::osl::MutexGuard guard( getMutex() ); + if (rBHelper.bInDispose || rBHelper.bDisposed) + throw css::lang::DisposedException( + OUSTR("PackageManager instance has already been disposed!"), + static_cast< ::cppu::OWeakObject * >(this) ); +} + +//______________________________________________________________________________ +inline void PackageManagerImpl::logIntern( css::uno::Any const & status ) +{ + if (m_xLogFile.is()) + m_xLogFile->update( status ); +} + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_manager.hrc b/desktop/source/deployment/manager/dp_manager.hrc new file mode 100644 index 000000000000..3dd89f57cf37 --- /dev/null +++ b/desktop/source/deployment/manager/dp_manager.hrc @@ -0,0 +1,39 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_MANAGER_HRC +#define INCLUDED_DP_MANAGER_HRC + +#include "deployment.hrc" + +#define RID_STR_ERROR_WHILE_ADDING (RID_DEPLOYMENT_MANAGER_START+0) +#define RID_STR_ERROR_WHILE_REMOVING (RID_DEPLOYMENT_MANAGER_START+1) +#define RID_STR_PACKAGE_ALREADY_ADDED (RID_DEPLOYMENT_MANAGER_START+2) +#define RID_STR_COPYING_PACKAGE (RID_DEPLOYMENT_MANAGER_START+3) +#define RID_STR_NO_SUCH_PACKAGE (RID_DEPLOYMENT_MANAGER_START+4) +#define RID_STR_SYNCHRONIZING_REPOSITORY (RID_DEPLOYMENT_MANAGER_START+5) +#endif diff --git a/desktop/source/deployment/manager/dp_manager.src b/desktop/source/deployment/manager/dp_manager.src new file mode 100644 index 000000000000..7430a8cab046 --- /dev/null +++ b/desktop/source/deployment/manager/dp_manager.src @@ -0,0 +1,59 @@ +/************************************************************************* + * + * 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 "dp_manager.hrc" + + +String RID_STR_COPYING_PACKAGE +{ + Text [ en-US ] = "Copying: "; +}; + +String RID_STR_ERROR_WHILE_ADDING +{ + Text [ en-US ] = "Error while adding: "; +}; + +String RID_STR_ERROR_WHILE_REMOVING +{ + Text [ en-US ] = "Error while removing: "; +}; + +String RID_STR_PACKAGE_ALREADY_ADDED +{ + Text [ en-US ] = "Extension has already been added: "; +}; + +String RID_STR_NO_SUCH_PACKAGE +{ + Text [ en-US ] = "There is no such extension deployed: "; +}; + +String RID_STR_SYNCHRONIZING_REPOSITORY +{ + Text [ en-US ] = "Synchronizing repository for %NAME extensions"; +}; diff --git a/desktop/source/deployment/manager/dp_managerfac.cxx b/desktop/source/deployment/manager/dp_managerfac.cxx new file mode 100644 index 000000000000..ccbaadcb8ac3 --- /dev/null +++ b/desktop/source/deployment/manager/dp_managerfac.cxx @@ -0,0 +1,202 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_manager.h" +#include "dp_resource.h" +#include "cppuhelper/compbase1.hxx" +#include "comphelper/servicedecl.hxx" +#include "com/sun/star/deployment/thePackageManagerFactory.hpp" + + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +namespace dp_manager { +namespace factory { + +typedef ::cppu::WeakComponentImplHelper1< + deployment::XPackageManagerFactory > t_pmfac_helper; + +//============================================================================== +class PackageManagerFactoryImpl : private MutexHolder, public t_pmfac_helper +{ + Reference<XComponentContext> m_xComponentContext; + + Reference<deployment::XPackageManager> m_xUserMgr; + Reference<deployment::XPackageManager> m_xSharedMgr; + Reference<deployment::XPackageManager> m_xBundledMgr; + typedef ::std::hash_map< + OUString, WeakReference<deployment::XPackageManager>, + ::rtl::OUStringHash > t_string2weakref; + t_string2weakref m_managers; + +protected: + inline void check(); + virtual void SAL_CALL disposing(); + +public: + virtual ~PackageManagerFactoryImpl(); + PackageManagerFactoryImpl( + Reference<XComponentContext> const & xComponentContext ); + + // XPackageManagerFactory + virtual Reference<deployment::XPackageManager> SAL_CALL getPackageManager( + OUString const & context ) throw (RuntimeException); +}; + +//============================================================================== +namespace sdecl = comphelper::service_decl; +sdecl::class_<PackageManagerFactoryImpl> servicePMFI; +extern sdecl::ServiceDecl const serviceDecl( + servicePMFI, + // a private one: + "com.sun.star.comp.deployment.PackageManagerFactory", + "com.sun.star.comp.deployment.PackageManagerFactory" ); + +//============================================================================== +bool singleton_entries( + Reference<registry::XRegistryKey> const & xRegistryKey ) +{ + try { + Reference<registry::XRegistryKey> xKey( + xRegistryKey->createKey( + serviceDecl.getImplementationName() + + // xxx todo: use future generated function to get singleton name + OUSTR("/UNO/SINGLETONS/" + "com.sun.star.deployment.thePackageManagerFactory") ) ); + xKey->setStringValue( serviceDecl.getSupportedServiceNames()[0] ); + return true; + } + catch (registry::InvalidRegistryException & exc) { + (void) exc; // avoid warnings + OSL_ENSURE( 0, ::rtl::OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + return false; + } +} + +//______________________________________________________________________________ +PackageManagerFactoryImpl::PackageManagerFactoryImpl( + Reference<XComponentContext> const & xComponentContext ) + : t_pmfac_helper( getMutex() ), + m_xComponentContext( xComponentContext ) +{ +} + +//______________________________________________________________________________ +PackageManagerFactoryImpl::~PackageManagerFactoryImpl() +{ +} + +//______________________________________________________________________________ +inline void PackageManagerFactoryImpl::check() +{ + ::osl::MutexGuard guard( getMutex() ); + if (rBHelper.bInDispose || rBHelper.bDisposed) + { + throw lang::DisposedException( + OUSTR("PackageManagerFactory instance has already been disposed!"), + static_cast<OWeakObject *>(this) ); + } +} + +//______________________________________________________________________________ +void PackageManagerFactoryImpl::disposing() +{ + // dispose all managers: + ::osl::MutexGuard guard( getMutex() ); + t_string2weakref::const_iterator iPos( m_managers.begin() ); + t_string2weakref::const_iterator const iEnd( m_managers.end() ); + for ( ; iPos != iEnd; ++iPos ) + try_dispose( iPos->second ); + m_managers = t_string2weakref(); + // the below are already disposed: + m_xUserMgr.clear(); + m_xSharedMgr.clear(); + m_xBundledMgr.clear(); +} + +// XPackageManagerFactory +//______________________________________________________________________________ +Reference<deployment::XPackageManager> +PackageManagerFactoryImpl::getPackageManager( OUString const & context ) + throw (RuntimeException) +{ + Reference< deployment::XPackageManager > xRet; + ::osl::ResettableMutexGuard guard( getMutex() ); + check(); + t_string2weakref::const_iterator const iFind( m_managers.find( context ) ); + if (iFind != m_managers.end()) { + xRet = iFind->second; + if (xRet.is()) + return xRet; + } + + guard.clear(); + xRet.set( PackageManagerImpl::create( m_xComponentContext, context ) ); + guard.reset(); + ::std::pair< t_string2weakref::iterator, bool > insertion( + m_managers.insert( t_string2weakref::value_type( context, xRet ) ) ); + if (insertion.second) + { + OSL_ASSERT( insertion.first->second.get() == xRet ); + // hold user, shared mgrs for whole process: live deployment + if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("user") )) + m_xUserMgr = xRet; + else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("shared") )) + m_xSharedMgr = xRet; + else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("bundled") )) + m_xBundledMgr = xRet; + } + else + { + Reference< deployment::XPackageManager > xAlreadyIn( + insertion.first->second ); + if (xAlreadyIn.is()) + { + guard.clear(); + try_dispose( xRet ); + xRet = xAlreadyIn; + } + else + { + insertion.first->second = xRet; + } + } + return xRet; +} + +} // namespace factory +} // namespace dp_manager + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_properties.cxx b/desktop/source/deployment/manager/dp_properties.cxx new file mode 100644 index 000000000000..6477c5aad099 --- /dev/null +++ b/desktop/source/deployment/manager/dp_properties.cxx @@ -0,0 +1,171 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "xmlscript/xml_helper.hxx" +#include "ucbhelper/content.hxx" +#include <list> + +#include "dp_ucb.h" +#include "rtl/ustrbuf.hxx" +#include "dp_properties.hxx" + +namespace lang = com::sun::star::lang; +namespace task = com::sun::star::task; +namespace ucb = com::sun::star::ucb; +namespace uno = com::sun::star::uno; +namespace css = com::sun::star; + +#define OUSTR(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) + +using ::com::sun::star::uno::Reference; +using ::rtl::OUString; + +#define PROP_SUPPRESS_LICENSE "SUPPRESS_LICENSE" +#define PROP_EXTENSION_UPDATE "EXTENSION_UPDATE" + +namespace dp_manager { + +//Reading the file +ExtensionProperties::ExtensionProperties( + OUString const & urlExtension, + Reference<ucb::XCommandEnvironment> const & xCmdEnv) : + m_xCmdEnv(xCmdEnv) +{ + m_propFileUrl = urlExtension + OUSTR("properties"); + + ::std::list< ::std::pair< OUString, OUString> > props; + if (! dp_misc::create_ucb_content(NULL, m_propFileUrl, 0, false)) + return; + + ::ucbhelper::Content contentProps(m_propFileUrl, m_xCmdEnv); + dp_misc::readProperties(props, contentProps); + + typedef ::std::list< ::std::pair< OUString, OUString> >::const_iterator CI; + for (CI i = props.begin(); i != props.end(); i++) + { + if (i->first.equals(OUSTR(PROP_SUPPRESS_LICENSE))) + m_prop_suppress_license = i->second; + } +} + +//Writing the file +ExtensionProperties::ExtensionProperties( + OUString const & urlExtension, + uno::Sequence<css::beans::NamedValue> const & properties, + Reference<ucb::XCommandEnvironment> const & xCmdEnv) : + m_xCmdEnv(xCmdEnv) +{ + m_propFileUrl = urlExtension + OUSTR("properties"); + + for (sal_Int32 i = 0; i < properties.getLength(); i++) + { + css::beans::NamedValue const & v = properties[i]; + if (v.Name.equals(OUSTR(PROP_SUPPRESS_LICENSE))) + { + m_prop_suppress_license = getPropertyValue(v); + } + else if (v.Name.equals(OUSTR(PROP_EXTENSION_UPDATE))) + { + m_prop_extension_update = getPropertyValue(v); + } + else + { + throw lang::IllegalArgumentException( + OUSTR("Extension Manager: unknown property"), 0, -1); + } + } +} + +OUString ExtensionProperties::getPropertyValue(css::beans::NamedValue const & v) +{ + OUString value(OUSTR("0")); + if (v.Value >>= value) + { + if (value.equals(OUSTR("1"))) + value = OUSTR("1"); + } + else + { + throw lang::IllegalArgumentException( + OUSTR("Extension Manager: wrong property value"), 0, -1); + } + return value; +} +void ExtensionProperties::write() +{ + ::ucbhelper::Content contentProps(m_propFileUrl, m_xCmdEnv); + ::rtl::OUStringBuffer buf; + + if (m_prop_suppress_license) + { + buf.append(OUSTR(PROP_SUPPRESS_LICENSE)); + buf.append(OUSTR("=")); + buf.append(*m_prop_suppress_license); + } + + ::rtl::OString stamp = ::rtl::OUStringToOString( + buf.makeStringAndClear(), RTL_TEXTENCODING_UTF8); + Reference<css::io::XInputStream> xData( + ::xmlscript::createInputStream( + ::rtl::ByteSequence( + reinterpret_cast<sal_Int8 const *>(stamp.getStr()), + stamp.getLength() ) ) ); + contentProps.writeStream( xData, true /* replace existing */ ); +} + +bool ExtensionProperties::isSuppressedLicense() +{ + bool ret = false; + if (m_prop_suppress_license) + { + if (m_prop_suppress_license->equals(OUSTR("1"))) + ret = true; + } + return ret; +} + +bool ExtensionProperties::isExtensionUpdate() +{ + bool ret = false; + if (m_prop_extension_update) + { + if (m_prop_extension_update->equals(OUSTR("1"))) + ret = true; + } + return ret; +} + +} // namespace dp_manager + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/dp_properties.hxx b/desktop/source/deployment/manager/dp_properties.hxx new file mode 100644 index 000000000000..70f6d9f62f47 --- /dev/null +++ b/desktop/source/deployment/manager/dp_properties.hxx @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_PROPERTIES_HXX +#define INCLUDED_DP_PROPERTIES_HXX + + + +#include "com/sun/star/beans/NamedValue.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "boost/optional.hpp" + + +namespace css = ::com::sun::star; + +namespace dp_manager { + + + +/** + + */ +class ExtensionProperties +{ +protected: + ::rtl::OUString m_propFileUrl; + const css::uno::Reference<css::ucb::XCommandEnvironment> m_xCmdEnv; + ::boost::optional< ::rtl::OUString> m_prop_suppress_license; + ::boost::optional< ::rtl::OUString> m_prop_extension_update; + + ::rtl::OUString getPropertyValue(css::beans::NamedValue const & v); +public: + + virtual ~ExtensionProperties() {}; + ExtensionProperties(::rtl::OUString const & urlExtension, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + ExtensionProperties(::rtl::OUString const & urlExtension, + css::uno::Sequence<css::beans::NamedValue> const & properties, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + void write(); + + bool isSuppressedLicense(); + + bool isExtensionUpdate(); +}; +} + + + + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/manager/makefile.mk b/desktop/source/deployment/manager/makefile.mk new file mode 100644 index 000000000000..4dc6405e34bf --- /dev/null +++ b/desktop/source/deployment/manager/makefile.mk @@ -0,0 +1,55 @@ +#************************************************************************* +# +# 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 = deployment_manager +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE : settings.mk + +.IF "$(SYSTEM_DB)" == "YES" +CFLAGS+=-DSYSTEM_DB -I$(DB_INCLUDES) +.ENDIF + +SRS1NAME = $(TARGET) +SRC1FILES = \ + dp_manager.src + +SLOFILES = \ + $(SLO)$/dp_activepackages.obj \ + $(SLO)$/dp_manager.obj \ + $(SLO)$/dp_managerfac.obj \ + $(SLO)$/dp_informationprovider.obj \ + $(SLO)$/dp_extensionmanager.obj \ + $(SLO)$/dp_commandenvironments.obj \ + $(SLO)$/dp_properties.obj + +.INCLUDE : ..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/misc/db.cxx b/desktop/source/deployment/misc/db.cxx new file mode 100644 index 000000000000..ce403181ab50 --- /dev/null +++ b/desktop/source/deployment/misc/db.cxx @@ -0,0 +1,274 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 <db.hxx> + +#include <rtl/alloc.h> +#include <cstring> +#include <errno.h> + +namespace berkeleydbproxy { + +//---------------------------------------------------------------------------- + namespace db_internal + { + static void raise_error(int dberr, const char * where); + + static inline int check_error(int dberr, const char * where) + { + if (dberr) raise_error(dberr,where); + return dberr; + } + } + +//---------------------------------------------------------------------------- + +char *DbEnv::strerror(int error) { + return (db_strerror(error)); +} + +//---------------------------------------------------------------------------- + +Db::Db(DbEnv* pDbenv,u_int32_t flags) +: m_pDBP(0) +{ + db_internal::check_error( db_create(&m_pDBP,pDbenv ? pDbenv->m_pDBENV:0,flags),"Db::Db" ); +} + + +Db::~Db() +{ + if (m_pDBP) + { + // should not happen + // TODO: add assert + } + +} + + +int Db::close(u_int32_t flags) +{ + int error = m_pDBP->close(m_pDBP,flags); + m_pDBP = 0; + return db_internal::check_error(error,"Db::close"); +} + +int Db::open(DB_TXN *txnid, + const char *file, + const char *database, + DBTYPE type, + u_int32_t flags, + int mode) +{ + int err = m_pDBP->open(m_pDBP,txnid,file,database,type,flags,mode); + return db_internal::check_error( err,"Db::open" ); +} + + +int Db::get(DB_TXN *txnid, Dbt *key, Dbt *data, u_int32_t flags) +{ + int err = m_pDBP->get(m_pDBP,txnid,key,data,flags); + + // these are non-exceptional outcomes + if (err != DB_NOTFOUND && err != DB_KEYEMPTY) + db_internal::check_error( err,"Db::get" ); + + return err; +} + +int Db::put(DB_TXN* txnid, Dbt *key, Dbt *data, u_int32_t flags) +{ + int err = m_pDBP->put(m_pDBP,txnid,key,data,flags); + + if (err != DB_KEYEXIST) // this is a non-exceptional outcome + db_internal::check_error( err,"Db::put" ); + return err; +} + +int Db::cursor(DB_TXN *txnid, Dbc **cursorp, u_int32_t flags) +{ + DBC * dbc = 0; + int error = m_pDBP->cursor(m_pDBP,txnid,&dbc,flags); + + if (!db_internal::check_error(error,"Db::cursor")) + *cursorp = new Dbc(dbc); + + return error; +} + + +#define DB_INCOMPLETE (-30999)/* Sync didn't finish. */ + +int Db::sync(u_int32_t flags) +{ + int err; + DB *db = m_pDBP; + + if (!db) { + db_internal::check_error(EINVAL,"Db::sync"); + return (EINVAL); + } + if ((err = db->sync(db, flags)) != 0 && err != DB_INCOMPLETE) { + db_internal::check_error(err, "Db::sync"); + return (err); + } + return (err); +} + +int Db::del(Dbt *key, u_int32_t flags) +{ + DB *db = m_pDBP; + int err; + + if ((err = db->del(db, 0, key, flags)) != 0) { + // DB_NOTFOUND is a "normal" return, so should not be + // thrown as an error + // + if (err != DB_NOTFOUND) { + db_internal::check_error(err, "Db::del"); + return (err); + } + } + return (err); +} + +//---------------------------------------------------------------------------- + +Dbc::Dbc(DBC * dbc) +: m_pDBC(dbc) +{ +} + +Dbc::~Dbc() +{ +} + +int Dbc::close() +{ + int err = m_pDBC->c_close(m_pDBC); + delete this; + return db_internal::check_error( err,"Dbcursor::close" ); +} + +int Dbc::get(Dbt *key, Dbt *data, u_int32_t flags) +{ + int err = m_pDBC->c_get(m_pDBC,key,data,flags); + + // these are non-exceptional outcomes + if (err != DB_NOTFOUND && err != DB_KEYEMPTY) + db_internal::check_error( err, "Dbcursor::get" ); + + return err; +} + +//---------------------------------------------------------------------------- + +Dbt::Dbt() +{ + using namespace std; + DBT * thispod = this; + memset(thispod, 0, sizeof *thispod); +} + + +Dbt::Dbt(void *data_arg, u_int32_t size_arg) +{ + using namespace std; + DBT * thispod = this; + memset(thispod, 0, sizeof *thispod); + this->set_data(data_arg); + this->set_size(size_arg); +} + +Dbt::Dbt(const Dbt & other) +{ + using namespace std; + const DBT *otherpod = &other; + DBT *thispod = this; + memcpy(thispod, otherpod, sizeof *thispod); +} + +Dbt& Dbt::operator = (const Dbt & other) +{ + if (this != &other) + { + using namespace std; + const DBT *otherpod = &other; + DBT *thispod = this; + memcpy(thispod, otherpod, sizeof *thispod); + } + return *this; +} + +Dbt::~Dbt() +{ +} + +void * Dbt::get_data() const +{ + return this->data; +} + +void Dbt::set_data(void *value) +{ + this->data = value; +} + +u_int32_t Dbt::get_size() const +{ + return this->size; +} + +void Dbt::set_size(u_int32_t value) +{ + this->size = value; +} + +//---------------------------------------------------------------------------- +void db_internal::raise_error(int dberr, const char * where) +{ + if (!where) where = "<unknown>"; + + const char * dberrmsg = db_strerror(dberr); + if (!dberrmsg || !*dberrmsg) dberrmsg = "<unknown DB error>"; + + rtl::OString msg = where; + msg += ": "; + msg += dberrmsg; + + throw DbException(msg); +} + +//---------------------------------------------------------------------------- +} // namespace ecomp + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_dependencies.cxx b/desktop/source/deployment/misc/dp_dependencies.cxx new file mode 100644 index 000000000000..345e4c248b4c --- /dev/null +++ b/desktop/source/deployment/misc/dp_dependencies.cxx @@ -0,0 +1,174 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "sal/config.h" + +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/xml/dom/XElement.hpp" +#include "com/sun/star/xml/dom/XNode.hpp" +#include "com/sun/star/xml/dom/XNodeList.hpp" +#include "rtl/bootstrap.hxx" +#include "rtl/string.h" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "tools/string.hxx" + +#include "deployment.hrc" +#include "dp_resource.h" + +#include "dp_dependencies.hxx" +#include "dp_descriptioninfoset.hxx" +#include "dp_version.hxx" + +namespace { + +namespace css = ::com::sun::star; + +static char const xmlNamespace[] = + "http://openoffice.org/extensions/description/2006"; + +bool satisfiesMinimalVersion(::rtl::OUString const & version) { + ::rtl::OUString v( + RTL_CONSTASCII_USTRINGPARAM( + "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") + ":Version:OOOPackageVersion}")); + ::rtl::Bootstrap::expandMacros(v); + return ::dp_misc::compareVersions(v, version) != ::dp_misc::LESS; +} + +} + +namespace dp_misc { + +namespace Dependencies { + +css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > +check(::dp_misc::DescriptionInfoset const & infoset) { + css::uno::Reference< css::xml::dom::XNodeList > deps( + infoset.getDependencies()); + ::sal_Int32 n = deps->getLength(); + css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > + unsatisfied(n); + ::sal_Int32 unsat = 0; + for (::sal_Int32 i = 0; i < n; ++i) { + static char const minimalVersion[] = "OpenOffice.org-minimal-version"; + css::uno::Reference< css::xml::dom::XElement > e( + deps->item(i), css::uno::UNO_QUERY_THROW); + bool sat = false; + if (e->getNamespaceURI().equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM(xmlNamespace)) + && e->getTagName().equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM(minimalVersion))) + { + sat = satisfiesMinimalVersion( + e->getAttribute( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("value")))); + } else if (e->getNamespaceURI().equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM(xmlNamespace)) + && e->getTagName().equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "OpenOffice.org-maximal-version"))) + { + ::rtl::OUString v( + RTL_CONSTASCII_USTRINGPARAM( + "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") + ":Version:OOOBaseVersion}")); + ::rtl::Bootstrap::expandMacros(v); + sat = + ::dp_misc::compareVersions( + v, + e->getAttribute( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("value")))) + != ::dp_misc::GREATER; + } else if (e->hasAttributeNS( + ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM(xmlNamespace)), + ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM(minimalVersion)))) + { + sat = satisfiesMinimalVersion( + e->getAttributeNS( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(xmlNamespace)), + ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM(minimalVersion)))); + } + if (!sat) { + unsatisfied[unsat++] = e; + } + } + unsatisfied.realloc(unsat); + return unsatisfied; +} + +::rtl::OUString getErrorText( css::uno::Reference< css::xml::dom::XElement > const & dependency ) +{ + ::rtl::OUString sReason; + ::rtl::OUString sValue; + ::rtl::OUString sVersion(RTL_CONSTASCII_USTRINGPARAM("%VERSION")); + + if ( dependency->getNamespaceURI().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( xmlNamespace ) ) + && dependency->getTagName().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "OpenOffice.org-minimal-version" ) ) ) + { + sValue = dependency->getAttribute( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "value" ) ) ); + sReason = ::rtl::OUString( ::String(::dp_misc::getResId(RID_DEPLYOMENT_DEPENDENCIES_MIN)) ); + } + else if ( dependency->getNamespaceURI().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( xmlNamespace ) ) + && dependency->getTagName().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "OpenOffice.org-maximal-version" ) ) ) + { + sValue = dependency->getAttribute( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("value") ) ); + sReason = ::rtl::OUString( ::String(::dp_misc::getResId(RID_DEPLYOMENT_DEPENDENCIES_MAX)) ); + } + else if ( dependency->hasAttributeNS( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( xmlNamespace ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenOffice.org-minimal-version" )))) + { + sValue = dependency->getAttributeNS( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( xmlNamespace ) ), + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OpenOffice.org-minimal-version" ) ) ); + sReason = ::rtl::OUString( ::String(::dp_misc::getResId(RID_DEPLYOMENT_DEPENDENCIES_MIN)) ); + } + else + return ::rtl::OUString( ::String(::dp_misc::getResId(RID_DEPLYOMENT_DEPENDENCIES_UNKNOWN)) ); + + if ( sValue.getLength() == 0 ) + sValue = ::rtl::OUString( ::String(::dp_misc::getResId(RID_DEPLYOMENT_DEPENDENCIES_UNKNOWN)) ); + + sal_Int32 nPos = sReason.indexOf( sVersion ); + if ( nPos >= 0 ) + sReason = sReason.replaceAt( nPos, sVersion.getLength(), sValue ); + return sReason; +} + +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_descriptioninfoset.cxx b/desktop/source/deployment/misc/dp_descriptioninfoset.cxx new file mode 100644 index 000000000000..0efc0ae091a0 --- /dev/null +++ b/desktop/source/deployment/misc/dp_descriptioninfoset.cxx @@ -0,0 +1,867 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_descriptioninfoset.hxx" + +#include "dp_resource.h" +#include "sal/config.h" + +#include "comphelper/sequence.hxx" +#include "comphelper/makesequence.hxx" +#include "comphelper/processfactory.hxx" +#include "boost/optional.hpp" +#include "com/sun/star/beans/Optional.hpp" +#include "com/sun/star/lang/XMultiComponentFactory.hpp" +#include "com/sun/star/lang/Locale.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/xml/dom/DOMException.hpp" +#include "com/sun/star/xml/dom/XNode.hpp" +#include "com/sun/star/xml/dom/XNodeList.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "com/sun/star/ucb/InteractiveAugmentedIOException.hpp" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/weak.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "ucbhelper/content.hxx" + +namespace { + +namespace css = ::com::sun::star; +using css::uno::Reference; +using ::rtl::OUString; + +class EmptyNodeList: public ::cppu::WeakImplHelper1< css::xml::dom::XNodeList > +{ +public: + EmptyNodeList(); + + virtual ~EmptyNodeList(); + + virtual ::sal_Int32 SAL_CALL getLength() throw (css::uno::RuntimeException); + + virtual css::uno::Reference< css::xml::dom::XNode > SAL_CALL + item(::sal_Int32 index) throw (css::uno::RuntimeException); + +private: + EmptyNodeList(EmptyNodeList &); // not defined + void operator =(EmptyNodeList &); // not defined +}; + +EmptyNodeList::EmptyNodeList() {} + +EmptyNodeList::~EmptyNodeList() {} + +::sal_Int32 EmptyNodeList::getLength() throw (css::uno::RuntimeException) { + return 0; +} + +css::uno::Reference< css::xml::dom::XNode > EmptyNodeList::item(::sal_Int32) + throw (css::uno::RuntimeException) +{ + throw css::uno::RuntimeException( + ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "bad EmptyNodeList com.sun.star.xml.dom.XNodeList.item call")), + static_cast< ::cppu::OWeakObject * >(this)); +} + +::rtl::OUString getNodeValue( + css::uno::Reference< css::xml::dom::XNode > const & node) +{ + OSL_ASSERT(node.is()); + try { + return node->getNodeValue(); + } catch (css::xml::dom::DOMException & e) { + throw css::uno::RuntimeException( + (::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.xml.dom.DOMException: ")) + + e.Message), + css::uno::Reference< css::uno::XInterface >()); + } +} + +/**The class uses the UCB to access the description.xml file in an + extension. The UCB must have been initialized already. It also + requires that the extension has already be unzipped to a particular + location. + */ +class ExtensionDescription +{ +public: + /**throws an exception if the description.xml is not + available, cannot be read, does not contain the expected data, + or any other error occured. Therefore it shoult only be used with + new extensions. + + Throws com::sun::star::uno::RuntimeException, + com::sun::star::deployment::DeploymentException, + dp_registry::backend::bundle::NoDescriptionException. + */ + ExtensionDescription( + const css::uno::Reference<css::uno::XComponentContext>& xContext, + const ::rtl::OUString& installDir, + const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv); + + ~ExtensionDescription(); + + css::uno::Reference<css::xml::dom::XNode> getRootElement() const + { + return m_xRoot; + } + + ::rtl::OUString getExtensionRootUrl() const + { + return m_sExtensionRootUrl; + } + + +private: + css::uno::Reference<css::xml::dom::XNode> m_xRoot; + ::rtl::OUString m_sExtensionRootUrl; +}; + +class NoDescriptionException +{ +}; + +class FileDoesNotExistFilter + : public ::cppu::WeakImplHelper2< css::ucb::XCommandEnvironment, + css::task::XInteractionHandler > + +{ + //css::uno::Reference<css::task::XInteractionHandler> m_xHandler; + bool m_bExist; + css::uno::Reference< css::ucb::XCommandEnvironment > m_xCommandEnv; + +public: + virtual ~FileDoesNotExistFilter(); + FileDoesNotExistFilter( + const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv); + + bool exist(); + // XCommandEnvironment + virtual css::uno::Reference<css::task::XInteractionHandler > SAL_CALL + getInteractionHandler() throw (css::uno::RuntimeException); + virtual css::uno::Reference<css::ucb::XProgressHandler > + SAL_CALL getProgressHandler() throw (css::uno::RuntimeException); + + // XInteractionHandler + virtual void SAL_CALL handle( + css::uno::Reference<css::task::XInteractionRequest > const & xRequest ) + throw (css::uno::RuntimeException); +}; + +ExtensionDescription::ExtensionDescription( + const Reference<css::uno::XComponentContext>& xContext, + const OUString& installDir, + const Reference< css::ucb::XCommandEnvironment >& xCmdEnv) +{ + try { + m_sExtensionRootUrl = installDir; + //may throw ::com::sun::star::ucb::ContentCreationException + //If there is no description.xml then ucb will start an interaction which + //brings up a dialog.We want to prevent this. Therefore we wrap the xCmdEnv + //and filter the respective exception out. + OUString sDescriptionUri(installDir + OUSTR("/description.xml")); + Reference<css::ucb::XCommandEnvironment> xFilter = + static_cast<css::ucb::XCommandEnvironment*>( + new FileDoesNotExistFilter(xCmdEnv)); + ::ucbhelper::Content descContent(sDescriptionUri, xFilter); + + //throws an com::sun::star::uno::Exception if the file is not available + Reference<css::io::XInputStream> xIn; + try + { //throws com.sun.star.ucb.InteractiveAugmentedIOException + xIn = descContent.openStream(); + } + catch (css::uno::Exception& ) + { + if ( ! static_cast<FileDoesNotExistFilter*>(xFilter.get())->exist()) + throw NoDescriptionException(); + throw; + } + if (!xIn.is()) + { + throw css::uno::Exception( + OUSTR("Could not get XInputStream for description.xml of extension ") + + sDescriptionUri, 0); + } + + //get root node of description.xml + Reference<css::xml::dom::XDocumentBuilder> xDocBuilder( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.xml.dom.DocumentBuilder"), + xContext ), css::uno::UNO_QUERY); + if (!xDocBuilder.is()) + throw css::uno::Exception(OUSTR(" Could not create service com.sun.star.xml.dom.DocumentBuilder"), 0); + + if (xDocBuilder->isNamespaceAware() == sal_False) + { + throw css::uno::Exception( + OUSTR("Service com.sun.star.xml.dom.DocumentBuilder is not namespace aware."), 0); + } + + Reference<css::xml::dom::XDocument> xDoc = xDocBuilder->parse(xIn); + if (!xDoc.is()) + { + throw css::uno::Exception(sDescriptionUri + OUSTR(" contains data which cannot be parsed. "), 0); + } + + //check for proper root element and namespace + Reference<css::xml::dom::XElement> xRoot = xDoc->getDocumentElement(); + if (!xRoot.is()) + { + throw css::uno::Exception( + sDescriptionUri + OUSTR(" contains no root element."), 0); + } + + if ( ! xRoot->getTagName().equals(OUSTR("description"))) + { + throw css::uno::Exception( + sDescriptionUri + OUSTR(" does not contain the root element <description>."), 0); + } + + m_xRoot = Reference<css::xml::dom::XNode>( + xRoot, css::uno::UNO_QUERY_THROW); + OUString nsDescription = xRoot->getNamespaceURI(); + + //check if this namespace is supported + if ( ! nsDescription.equals(OUSTR("http://openoffice.org/extensions/description/2006"))) + { + throw css::uno::Exception(sDescriptionUri + OUSTR(" contains a root element with an unsupported namespace. "), 0); + } + } catch (css::uno::RuntimeException &) { + throw; + } catch (css::deployment::DeploymentException &) { + throw; + } catch (css::uno::Exception & e) { + css::uno::Any a(cppu::getCaughtException()); + throw css::deployment::DeploymentException( + e.Message, Reference< css::uno::XInterface >(), a); + } +} + +ExtensionDescription::~ExtensionDescription() +{ +} + +//====================================================================== +FileDoesNotExistFilter::FileDoesNotExistFilter( + const Reference< css::ucb::XCommandEnvironment >& xCmdEnv): + m_bExist(true), m_xCommandEnv(xCmdEnv) +{} + +FileDoesNotExistFilter::~FileDoesNotExistFilter() +{ +}; + +bool FileDoesNotExistFilter::exist() +{ + return m_bExist; +} + // XCommandEnvironment +Reference<css::task::XInteractionHandler > + FileDoesNotExistFilter::getInteractionHandler() throw (css::uno::RuntimeException) +{ + return static_cast<css::task::XInteractionHandler*>(this); +} + +Reference<css::ucb::XProgressHandler > + FileDoesNotExistFilter::getProgressHandler() throw (css::uno::RuntimeException) +{ + return m_xCommandEnv.is() + ? m_xCommandEnv->getProgressHandler() + : Reference<css::ucb::XProgressHandler>(); +} + +// XInteractionHandler +//If the interaction was caused by a non-existing file which is specified in the ctor +//of FileDoesNotExistFilter, then we do nothing +void FileDoesNotExistFilter::handle( + Reference<css::task::XInteractionRequest > const & xRequest ) + throw (css::uno::RuntimeException) +{ + css::uno::Any request( xRequest->getRequest() ); + + css::ucb::InteractiveAugmentedIOException ioexc; + if ((request>>= ioexc) && ioexc.Code == css::ucb::IOErrorCode_NOT_EXISTING ) + { + m_bExist = false; + return; + } + Reference<css::task::XInteractionHandler> xInteraction; + if (m_xCommandEnv.is()) { + xInteraction = m_xCommandEnv->getInteractionHandler(); + } + if (xInteraction.is()) { + xInteraction->handle(xRequest); + } +} + +} + +namespace dp_misc { + +DescriptionInfoset getDescriptionInfoset(OUString const & sExtensionFolderURL) +{ + Reference< css::xml::dom::XNode > root; + Reference<css::uno::XComponentContext> context = + comphelper_getProcessComponentContext(); + OSL_ASSERT(context.is()); + try { + root = + ExtensionDescription( + context, sExtensionFolderURL, + Reference< css::ucb::XCommandEnvironment >()). + getRootElement(); + } catch (NoDescriptionException &) { + } catch (css::deployment::DeploymentException & e) { + throw css::uno::RuntimeException( + (OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.deployment.DeploymentException: ")) + + e.Message), 0); + } + return DescriptionInfoset(context, root); +} + +DescriptionInfoset::DescriptionInfoset( + css::uno::Reference< css::uno::XComponentContext > const & context, + css::uno::Reference< css::xml::dom::XNode > const & element): + m_element(element) +{ + css::uno::Reference< css::lang::XMultiComponentFactory > manager( + context->getServiceManager(), css::uno::UNO_QUERY_THROW); + if (m_element.is()) { + m_xpath = css::uno::Reference< css::xml::xpath::XXPathAPI >( + manager->createInstanceWithContext( + ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.xml.xpath.XPathAPI")), + context), + css::uno::UNO_QUERY_THROW); + m_xpath->registerNS( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc")), + element->getNamespaceURI()); + m_xpath->registerNS( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("xlink")), + ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("http://www.w3.org/1999/xlink"))); + } +} + +DescriptionInfoset::~DescriptionInfoset() {} + +::boost::optional< ::rtl::OUString > DescriptionInfoset::getIdentifier() const { + return getOptionalValue( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:identifier/@value"))); +} + +::rtl::OUString DescriptionInfoset::getNodeValueFromExpression(::rtl::OUString const & expression) const +{ + css::uno::Reference< css::xml::dom::XNode > n; + if (m_element.is()) { + try { + n = m_xpath->selectSingleNode(m_element, expression); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + } + return n.is() ? getNodeValue(n) : ::rtl::OUString(); +} + + +::rtl::OUString DescriptionInfoset::getVersion() const +{ + return getNodeValueFromExpression( ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("desc:version/@value"))); +} + +css::uno::Sequence< ::rtl::OUString > DescriptionInfoset::getSupportedPlaforms() const +{ + //When there is no description.xml then we assume that we support all platforms + if (! m_element.is()) + { + return comphelper::makeSequence( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("all"))); + } + + //Check if the <platform> element was provided. If not the default is "all" platforms + css::uno::Reference< css::xml::dom::XNode > nodePlatform( + m_xpath->selectSingleNode(m_element, ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("desc:platform")))); + if (!nodePlatform.is()) + { + return comphelper::makeSequence( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("all"))); + } + + //There is a platform element. + const ::rtl::OUString value = getNodeValueFromExpression(::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("desc:platform/@value"))); + //parse the string, it can contained multiple strings separated by commas + ::std::vector< ::rtl::OUString> vec; + sal_Int32 nIndex = 0; + do + { + ::rtl::OUString aToken = value.getToken( 0, ',', nIndex ); + aToken = aToken.trim(); + if (aToken.getLength()) + vec.push_back(aToken); + + } + while (nIndex >= 0); + + return comphelper::containerToSequence(vec); +} + +css::uno::Reference< css::xml::dom::XNodeList > +DescriptionInfoset::getDependencies() const { + if (m_element.is()) { + try { + return m_xpath->selectNodeList(m_element, ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("desc:dependencies/*"))); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + } + return new EmptyNodeList; +} + +css::uno::Sequence< ::rtl::OUString > +DescriptionInfoset::getUpdateInformationUrls() const { + return getUrls( + ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "desc:update-information/desc:src/@xlink:href"))); +} + +css::uno::Sequence< ::rtl::OUString > +DescriptionInfoset::getUpdateDownloadUrls() const +{ + return getUrls( + ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "desc:update-download/desc:src/@xlink:href"))); +} + +::rtl::OUString DescriptionInfoset::getIconURL( sal_Bool bHighContrast ) const +{ + css::uno::Sequence< ::rtl::OUString > aStrList = getUrls( ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "desc:icon/desc:default/@xlink:href"))); + css::uno::Sequence< ::rtl::OUString > aStrListHC = getUrls( ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "desc:icon/desc:high-contrast/@xlink:href"))); + + if ( bHighContrast && aStrListHC.hasElements() && aStrListHC[0].getLength() ) + return aStrListHC[0]; + + if ( aStrList.hasElements() && aStrList[0].getLength() ) + return aStrList[0]; + + return ::rtl::OUString(); +} + +::boost::optional< ::rtl::OUString > DescriptionInfoset::getLocalizedUpdateWebsiteURL() + const +{ + bool bParentExists = false; + const ::rtl::OUString sURL (getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "/desc:description/desc:update-website")), &bParentExists )); + + if (sURL.getLength() > 0) + return ::boost::optional< ::rtl::OUString >(sURL); + else + return bParentExists ? ::boost::optional< ::rtl::OUString >(::rtl::OUString()) : + ::boost::optional< ::rtl::OUString >(); +} + +::boost::optional< ::rtl::OUString > DescriptionInfoset::getOptionalValue( + ::rtl::OUString const & expression) const +{ + css::uno::Reference< css::xml::dom::XNode > n; + if (m_element.is()) { + try { + n = m_xpath->selectSingleNode(m_element, expression); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + } + return n.is() + ? ::boost::optional< ::rtl::OUString >(getNodeValue(n)) + : ::boost::optional< ::rtl::OUString >(); +} + +css::uno::Sequence< ::rtl::OUString > DescriptionInfoset::getUrls( + ::rtl::OUString const & expression) const +{ + css::uno::Reference< css::xml::dom::XNodeList > ns; + if (m_element.is()) { + try { + ns = m_xpath->selectNodeList(m_element, expression); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + } + css::uno::Sequence< ::rtl::OUString > urls(ns.is() ? ns->getLength() : 0); + for (::sal_Int32 i = 0; i < urls.getLength(); ++i) { + urls[i] = getNodeValue(ns->item(i)); + } + return urls; +} + +::std::pair< ::rtl::OUString, ::rtl::OUString > DescriptionInfoset::getLocalizedPublisherNameAndURL() const +{ + css::uno::Reference< css::xml::dom::XNode > node = + getLocalizedChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:publisher"))); + + ::rtl::OUString sPublisherName; + ::rtl::OUString sURL; + if (node.is()) + { + const ::rtl::OUString exp1(RTL_CONSTASCII_USTRINGPARAM("text()")); + css::uno::Reference< css::xml::dom::XNode > xPathName; + try { + xPathName = m_xpath->selectSingleNode(node, exp1); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + OSL_ASSERT(xPathName.is()); + if (xPathName.is()) + sPublisherName = xPathName->getNodeValue(); + + const ::rtl::OUString exp2(RTL_CONSTASCII_USTRINGPARAM("@xlink:href")); + css::uno::Reference< css::xml::dom::XNode > xURL; + try { + xURL = m_xpath->selectSingleNode(node, exp2); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + OSL_ASSERT(xURL.is()); + if (xURL.is()) + sURL = xURL->getNodeValue(); + } + return ::std::make_pair(sPublisherName, sURL); +} + +::rtl::OUString DescriptionInfoset::getLocalizedReleaseNotesURL() const +{ + return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "/desc:description/desc:release-notes")), NULL); +} + +::rtl::OUString DescriptionInfoset::getLocalizedDisplayName() const +{ + css::uno::Reference< css::xml::dom::XNode > node = + getLocalizedChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:display-name"))); + if (node.is()) + { + const ::rtl::OUString exp(RTL_CONSTASCII_USTRINGPARAM("text()")); + css::uno::Reference< css::xml::dom::XNode > xtext; + try { + xtext = m_xpath->selectSingleNode(node, exp); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + if (xtext.is()) + return xtext->getNodeValue(); + } + return ::rtl::OUString(); +} + +::rtl::OUString DescriptionInfoset::getLocalizedLicenseURL() const +{ + return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "/desc:description/desc:registration/desc:simple-license")), NULL); + +} + +::boost::optional<SimpleLicenseAttributes> +DescriptionInfoset::getSimpleLicenseAttributes() const +{ + //Check if the node exist + css::uno::Reference< css::xml::dom::XNode > n; + if (m_element.is()) { + try { + n = m_xpath->selectSingleNode(m_element, + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "/desc:description/desc:registration/desc:simple-license/@accept-by"))); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + if (n.is()) + { + SimpleLicenseAttributes attributes; + attributes.acceptBy = + getNodeValueFromExpression(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "/desc:description/desc:registration/desc:simple-license/@accept-by"))); + + ::boost::optional< ::rtl::OUString > suppressOnUpdate = getOptionalValue( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "/desc:description/desc:registration/desc:simple-license/@suppress-on-update"))); + if (suppressOnUpdate) + attributes.suppressOnUpdate = (*suppressOnUpdate).trim().equalsIgnoreAsciiCase( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("true"))); + else + attributes.suppressOnUpdate = false; + + ::boost::optional< ::rtl::OUString > suppressIfRequired = getOptionalValue( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "/desc:description/desc:registration/desc:simple-license/@suppress-if-required"))); + if (suppressIfRequired) + attributes.suppressIfRequired = (*suppressIfRequired).trim().equalsIgnoreAsciiCase( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("true"))); + else + attributes.suppressIfRequired = false; + + return ::boost::optional<SimpleLicenseAttributes>(attributes); + } + } + return ::boost::optional<SimpleLicenseAttributes>(); +} + +::rtl::OUString DescriptionInfoset::getLocalizedDescriptionURL() const +{ + return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "/desc:description/desc:extension-description")), NULL); +} + +css::uno::Reference< css::xml::dom::XNode > +DescriptionInfoset::getLocalizedChild( const ::rtl::OUString & sParent) const +{ + if ( ! m_element.is() || !sParent.getLength()) + return css::uno::Reference< css::xml::dom::XNode > (); + + css::uno::Reference< css::xml::dom::XNode > xParent; + try { + xParent = m_xpath->selectSingleNode(m_element, sParent); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + css::uno::Reference<css::xml::dom::XNode> nodeMatch; + if (xParent.is()) + { + const ::rtl::OUString sLocale = getOfficeLocaleString(); + nodeMatch = matchFullLocale(xParent, sLocale); + + //office: en-DE, en, en-DE-altmark + if (! nodeMatch.is()) + { + const css::lang::Locale officeLocale = getOfficeLocale(); + nodeMatch = matchCountryAndLanguage(xParent, officeLocale); + if ( ! nodeMatch.is()) + { + nodeMatch = matchLanguage(xParent, officeLocale); + if (! nodeMatch.is()) + nodeMatch = getChildWithDefaultLocale(xParent); + } + } + } + + return nodeMatch; +} + +css::uno::Reference<css::xml::dom::XNode> +DescriptionInfoset::matchFullLocale(css::uno::Reference< css::xml::dom::XNode > + const & xParent, ::rtl::OUString const & sLocale) const +{ + OSL_ASSERT(xParent.is()); + const ::rtl::OUString exp1( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\"")) + + sLocale + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]"))); + try { + return m_xpath->selectSingleNode(xParent, exp1); + } catch (css::xml::xpath::XPathException &) { + // ignore + return 0; + } +} + +css::uno::Reference<css::xml::dom::XNode> +DescriptionInfoset::matchCountryAndLanguage( + css::uno::Reference< css::xml::dom::XNode > const & xParent, css::lang::Locale const & officeLocale) const +{ + OSL_ASSERT(xParent.is()); + css::uno::Reference<css::xml::dom::XNode> nodeMatch; + + if (officeLocale.Country.getLength()) + { + const ::rtl::OUString sLangCountry(officeLocale.Language + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-")) + + officeLocale.Country); + //first try exact match for lang-country + const ::rtl::OUString exp1( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\"")) + + sLangCountry + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]"))); + try { + nodeMatch = m_xpath->selectSingleNode(xParent, exp1); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + + //try to match in strings that also have a variant, for example en-US matches in + //en-US-montana + if (!nodeMatch.is()) + { + const ::rtl::OUString exp2( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[starts-with(@lang,\"")) + + sLangCountry + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-\")]"))); + try { + nodeMatch = m_xpath->selectSingleNode(xParent, exp2); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + } + } + + return nodeMatch; +} + + +css::uno::Reference<css::xml::dom::XNode> +DescriptionInfoset::matchLanguage( + css::uno::Reference< css::xml::dom::XNode > const & xParent, css::lang::Locale const & officeLocale) const +{ + OSL_ASSERT(xParent.is()); + css::uno::Reference<css::xml::dom::XNode> nodeMatch; + + //first try exact match for lang + const ::rtl::OUString exp1( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\"")) + + officeLocale.Language + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]"))); + try { + nodeMatch = m_xpath->selectSingleNode(xParent, exp1); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + + //try to match in strings that also have a country and/orvariant, for example en matches in + //en-US-montana, en-US, en-montana + if (!nodeMatch.is()) + { + const ::rtl::OUString exp2( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[starts-with(@lang,\"")) + + officeLocale.Language + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-\")]"))); + try { + nodeMatch = m_xpath->selectSingleNode(xParent, exp2); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + } + return nodeMatch; +} + +css::uno::Reference<css::xml::dom::XNode> +DescriptionInfoset::getChildWithDefaultLocale(css::uno::Reference< css::xml::dom::XNode > + const & xParent) const +{ + OSL_ASSERT(xParent.is()); + if (xParent->getNodeName().equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("simple-license")))) + { + css::uno::Reference<css::xml::dom::XNode> nodeDefault; + try { + nodeDefault = m_xpath->selectSingleNode(xParent, ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("@default-license-id"))); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + if (nodeDefault.is()) + { + //The old way + const ::rtl::OUString exp1( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:license-text[@license-id = \"")) + + nodeDefault->getNodeValue() + + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]"))); + try { + return m_xpath->selectSingleNode(xParent, exp1); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + } + } + + const ::rtl::OUString exp2(RTL_CONSTASCII_USTRINGPARAM("*[1]")); + try { + return m_xpath->selectSingleNode(xParent, exp2); + } catch (css::xml::xpath::XPathException &) { + // ignore + return 0; + } +} + +::rtl::OUString DescriptionInfoset::getLocalizedHREFAttrFromChild( + ::rtl::OUString const & sXPathParent, bool * out_bParentExists) + const +{ + css::uno::Reference< css::xml::dom::XNode > node = + getLocalizedChild(sXPathParent); + + ::rtl::OUString sURL; + if (node.is()) + { + if (out_bParentExists) + *out_bParentExists = true; + const ::rtl::OUString exp(RTL_CONSTASCII_USTRINGPARAM("@xlink:href")); + css::uno::Reference< css::xml::dom::XNode > xURL; + try { + xURL = m_xpath->selectSingleNode(node, exp); + } catch (css::xml::xpath::XPathException &) { + // ignore + } + OSL_ASSERT(xURL.is()); + if (xURL.is()) + sURL = xURL->getNodeValue(); + } + else + { + if (out_bParentExists) + *out_bParentExists = false; + } + return sURL; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_identifier.cxx b/desktop/source/deployment/misc/dp_identifier.cxx new file mode 100644 index 000000000000..f9fb809b5161 --- /dev/null +++ b/desktop/source/deployment/misc/dp_identifier.cxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "sal/config.h" + +#include "boost/optional.hpp" +#include "com/sun/star/beans/Optional.hpp" +#include "com/sun/star/deployment/XPackage.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "osl/diagnose.h" +#include "rtl/string.h" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.hxx" + +#include "dp_identifier.hxx" + +namespace { + namespace css = ::com::sun::star; +} + +namespace dp_misc { + +::rtl::OUString generateIdentifier( + ::boost::optional< ::rtl::OUString > const & optional, + ::rtl::OUString const & fileName) +{ + return optional ? *optional : generateLegacyIdentifier(fileName); +} + +::rtl::OUString getIdentifier( + css::uno::Reference< css::deployment::XPackage > const & package) +{ + OSL_ASSERT(package.is()); + css::beans::Optional< ::rtl::OUString > id(package->getIdentifier()); + return id.IsPresent + ? id.Value : generateLegacyIdentifier(package->getName()); +} + +::rtl::OUString generateLegacyIdentifier(::rtl::OUString const & fileName) { + rtl::OUStringBuffer b; + b.appendAscii(RTL_CONSTASCII_STRINGPARAM("org.openoffice.legacy.")); + b.append(fileName); + return b.makeStringAndClear(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_interact.cxx b/desktop/source/deployment/misc/dp_interact.cxx new file mode 100644 index 000000000000..57cc3bf2e7ad --- /dev/null +++ b/desktop/source/deployment/misc/dp_interact.cxx @@ -0,0 +1,187 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_interact.h" +#include "cppuhelper/exc_hlp.hxx" +#include "cppuhelper/implbase1.hxx" +#include "com/sun/star/task/XInteractionAbort.hpp" + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; + +namespace dp_misc { +namespace { + +//============================================================================== +class InteractionContinuationImpl : public ::cppu::OWeakObject, + public task::XInteractionContinuation +{ + const Type m_type; + bool * m_pselect; + +public: + inline InteractionContinuationImpl( Type const & type, bool * pselect ) + : m_type( type ), + m_pselect( pselect ) + { OSL_ASSERT( + ::getCppuType( + static_cast< Reference<task::XInteractionContinuation> + const *>(0) ).isAssignableFrom(m_type) ); } + + // XInterface + virtual void SAL_CALL acquire() throw (); + virtual void SAL_CALL release() throw (); + virtual Any SAL_CALL queryInterface( Type const & type ) + throw (RuntimeException); + + // XInteractionContinuation + virtual void SAL_CALL select() throw (RuntimeException); +}; + +// XInterface +//______________________________________________________________________________ +void InteractionContinuationImpl::acquire() throw () +{ + OWeakObject::acquire(); +} + +//______________________________________________________________________________ +void InteractionContinuationImpl::release() throw () +{ + OWeakObject::release(); +} + +//______________________________________________________________________________ +Any InteractionContinuationImpl::queryInterface( Type const & type ) + throw (RuntimeException) +{ + if (type.isAssignableFrom( m_type )) { + Reference<task::XInteractionContinuation> xThis(this); + return Any( &xThis, type ); + } + else + return OWeakObject::queryInterface(type); +} + +// XInteractionContinuation +//______________________________________________________________________________ +void InteractionContinuationImpl::select() throw (RuntimeException) +{ + *m_pselect = true; +} + +//============================================================================== +class InteractionRequest : + public ::cppu::WeakImplHelper1<task::XInteractionRequest> +{ + Any m_request; + Sequence< Reference<task::XInteractionContinuation> > m_conts; + +public: + inline InteractionRequest( + Any const & request, + Sequence< Reference<task::XInteractionContinuation> > const & conts ) + : m_request( request ), + m_conts( conts ) + {} + + // XInteractionRequest + virtual Any SAL_CALL getRequest() + throw (RuntimeException); + virtual Sequence< Reference<task::XInteractionContinuation> > + SAL_CALL getContinuations() throw (RuntimeException); +}; + +// XInteractionRequest +//______________________________________________________________________________ +Any InteractionRequest::getRequest() throw (RuntimeException) +{ + return m_request; +} + +//______________________________________________________________________________ +Sequence< Reference< task::XInteractionContinuation > > +InteractionRequest::getContinuations() throw (RuntimeException) +{ + return m_conts; +} + +} // anon namespace + +//============================================================================== +bool interactContinuation( Any const & request, + Type const & continuation, + Reference<XCommandEnvironment> const & xCmdEnv, + bool * pcont, bool * pabort ) +{ + OSL_ASSERT( + task::XInteractionContinuation::static_type().isAssignableFrom( + continuation ) ); + if (xCmdEnv.is()) { + Reference<task::XInteractionHandler> xInteractionHandler( + xCmdEnv->getInteractionHandler() ); + if (xInteractionHandler.is()) { + bool cont = false; + bool abort = false; + Sequence< Reference<task::XInteractionContinuation> > conts( 2 ); + conts[ 0 ] = new InteractionContinuationImpl( + continuation, &cont ); + conts[ 1 ] = new InteractionContinuationImpl( + task::XInteractionAbort::static_type(), &abort ); + xInteractionHandler->handle( + new InteractionRequest( request, conts ) ); + if (cont || abort) { + if (pcont != 0) + *pcont = cont; + if (pabort != 0) + *pabort = abort; + return true; + } + } + } + return false; +} + +// XAbortChannel +//______________________________________________________________________________ +void AbortChannel::sendAbort() throw (RuntimeException) +{ + m_aborted = true; + if (m_xNext.is()) + m_xNext->sendAbort(); +} + +} // dp_misc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_misc.cxx b/desktop/source/deployment/misc/dp_misc.cxx new file mode 100644 index 000000000000..f0ac23d2fb19 --- /dev/null +++ b/desktop/source/deployment/misc/dp_misc.cxx @@ -0,0 +1,632 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_misc.h" +#include "dp_version.hxx" +#include "dp_interact.h" +#include "rtl/uri.hxx" +#include "rtl/digest.h" +#include "rtl/random.h" +#include "rtl/bootstrap.hxx" +#include "unotools/bootstrap.hxx" +#include "osl/file.hxx" +#include "osl/pipe.hxx" +#include "osl/security.hxx" +#include "osl/thread.hxx" +#include "osl/mutex.hxx" +#include "com/sun/star/ucb/CommandAbortedException.hpp" +#include "com/sun/star/task/XInteractionHandler.hpp" +#include "com/sun/star/bridge/UnoUrlResolver.hpp" +#include "com/sun/star/bridge/XUnoUrlResolver.hpp" +#include "com/sun/star/deployment/ExtensionManager.hpp" +#include "com/sun/star/task/XRestartManager.hpp" +#include "boost/scoped_array.hpp" +#include "boost/shared_ptr.hpp" +#include <comphelper/processfactory.hxx> + +#ifdef WNT +#define UNICODE +#define _UNICODE +#define WIN32_LEAN_AND_MEAN +#include <Windows.h> +#endif + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; +using ::rtl::OString; + + +#define SOFFICE1 "soffice.exe" +#define SOFFICE2 "soffice.bin" +#define SBASE "sbase.exe" +#define SCALC "scalc.exe" +#define SDRAW "sdraw.exe" +#define SIMPRESS "simpress.exe" +#define SWRITER "swriter.exe" + +namespace dp_misc { +namespace { + +struct UnoRc : public rtl::StaticWithInit< + const boost::shared_ptr<rtl::Bootstrap>, UnoRc> { + const boost::shared_ptr<rtl::Bootstrap> operator () () { + OUString unorc( RTL_CONSTASCII_USTRINGPARAM( + "$OOO_BASE_DIR/program/" SAL_CONFIGFILE("uno")) ); + ::rtl::Bootstrap::expandMacros( unorc ); + ::boost::shared_ptr< ::rtl::Bootstrap > ret( + new ::rtl::Bootstrap( unorc ) ); + OSL_ASSERT( ret->getHandle() != 0 ); + return ret; + } +}; + +struct OfficePipeId : public rtl::StaticWithInit<const OUString, OfficePipeId> { + const OUString operator () (); +}; + +const OUString OfficePipeId::operator () () +{ + OUString userPath; + ::utl::Bootstrap::PathStatus aLocateResult = + ::utl::Bootstrap::locateUserInstallation( userPath ); + if (!(aLocateResult == ::utl::Bootstrap::PATH_EXISTS || + aLocateResult == ::utl::Bootstrap::PATH_VALID)) + { + throw Exception(OUSTR("Extension Manager: Could not obtain path for UserInstallation."), 0); + } + + rtlDigest digest = rtl_digest_create( rtl_Digest_AlgorithmMD5 ); + if (digest <= 0) { + throw RuntimeException( + OUSTR("cannot get digest rtl_Digest_AlgorithmMD5!"), 0 ); + } + + sal_uInt8 const * data = + reinterpret_cast<sal_uInt8 const *>(userPath.getStr()); + sal_Size size = (userPath.getLength() * sizeof (sal_Unicode)); + sal_uInt32 md5_key_len = rtl_digest_queryLength( digest ); + ::boost::scoped_array<sal_uInt8> md5_buf( new sal_uInt8 [ md5_key_len ] ); + + rtl_digest_init( digest, data, static_cast<sal_uInt32>(size) ); + rtl_digest_update( digest, data, static_cast<sal_uInt32>(size) ); + rtl_digest_get( digest, md5_buf.get(), md5_key_len ); + rtl_digest_destroy( digest ); + + // create hex-value string from the MD5 value to keep + // the string size minimal + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("SingleOfficeIPC_") ); + for ( sal_uInt32 i = 0; i < md5_key_len; ++i ) { + buf.append( static_cast<sal_Int32>(md5_buf[ i ]), 0x10 ); + } + return buf.makeStringAndClear(); +} + +bool existsOfficePipe() +{ + OUString const & pipeId = OfficePipeId::get(); + if (pipeId.getLength() == 0) + return false; + ::osl::Security sec; + ::osl::Pipe pipe( pipeId, osl_Pipe_OPEN, sec ); + return pipe.is(); +} + + +//Returns true if the Folder was more recently modified then +//the lastsynchronized file. That is the repository needs to +//be synchronized. +bool compareExtensionFolderWithLastSynchronizedFile( + OUString const & folderURL, OUString const & fileURL) +{ + bool bNeedsSync = false; + ::osl::DirectoryItem itemExtFolder; + ::osl::File::RC err1 = + ::osl::DirectoryItem::get(folderURL, itemExtFolder); + //If it does not exist, then there is nothing to be done + if (err1 == ::osl::File::E_NOENT) + { + return false; + } + else if (err1 != ::osl::File::E_None) + { + OSL_ENSURE(0, "Cannot access extension folder"); + return true; //sync just in case + } + + //If last synchronized does not exist, then OOo is started for the first time + ::osl::DirectoryItem itemFile; + ::osl::File::RC err2 = ::osl::DirectoryItem::get(fileURL, itemFile); + if (err2 == ::osl::File::E_NOENT) + { + return true; + + } + else if (err2 != ::osl::File::E_None) + { + OSL_ENSURE(0, "Cannot access file lastsynchronized"); + return true; //sync just in case + } + + //compare the modification time of the extension folder and the last + //modified file + ::osl::FileStatus statFolder(FileStatusMask_ModifyTime); + ::osl::FileStatus statFile(FileStatusMask_ModifyTime); + if (itemExtFolder.getFileStatus(statFolder) == ::osl::File::E_None) + { + if (itemFile.getFileStatus(statFile) == ::osl::File::E_None) + { + TimeValue timeFolder = statFolder.getModifyTime(); + TimeValue timeFile = statFile.getModifyTime(); + + if (timeFile.Seconds < timeFolder.Seconds) + bNeedsSync = true; + } + else + { + OSL_ASSERT(0); + bNeedsSync = true; + } + } + else + { + OSL_ASSERT(0); + bNeedsSync = true; + } + return bNeedsSync; +} + +bool needToSyncRepostitory(OUString const & name) +{ + OUString folder; + OUString file; + if (name.equals(OUString(RTL_CONSTASCII_USTRINGPARAM("bundled")))) + { + folder = OUString( + RTL_CONSTASCII_USTRINGPARAM("$BUNDLED_EXTENSIONS")); + file = OUString ( + RTL_CONSTASCII_USTRINGPARAM( + "$BUNDLED_EXTENSIONS_USER/lastsynchronized")); + } + else if (name.equals(OUString(RTL_CONSTASCII_USTRINGPARAM("shared")))) + { + folder = OUString( + RTL_CONSTASCII_USTRINGPARAM( + "$UNO_SHARED_PACKAGES_CACHE/uno_packages")); + file = OUString ( + RTL_CONSTASCII_USTRINGPARAM( + "$SHARED_EXTENSIONS_USER/lastsynchronized")); + } + else + { + OSL_ASSERT(0); + return true; + } + ::rtl::Bootstrap::expandMacros(folder); + ::rtl::Bootstrap::expandMacros(file); + return compareExtensionFolderWithLastSynchronizedFile( + folder, file); +} + + +} // anon namespace + +//============================================================================== + +namespace { +inline OUString encodeForRcFile( OUString const & str ) +{ + // escape $\{} (=> rtl bootstrap files) + ::rtl::OUStringBuffer buf; + sal_Int32 pos = 0; + const sal_Int32 len = str.getLength(); + for ( ; pos < len; ++pos ) { + sal_Unicode c = str[ pos ]; + switch (c) { + case '$': + case '\\': + case '{': + case '}': + buf.append( static_cast<sal_Unicode>('\\') ); + break; + } + buf.append( c ); + } + return buf.makeStringAndClear(); +} +} + +//============================================================================== +OUString makeURL( OUString const & baseURL, OUString const & relPath_ ) +{ + ::rtl::OUStringBuffer buf; + if (baseURL.getLength() > 1 && baseURL[ baseURL.getLength() - 1 ] == '/') + buf.append( baseURL.copy( 0, baseURL.getLength() - 1 ) ); + else + buf.append( baseURL ); + OUString relPath(relPath_); + if (relPath.getLength() > 0 && relPath[ 0 ] == '/') + relPath = relPath.copy( 1 ); + if (relPath.getLength() > 0) + { + buf.append( static_cast<sal_Unicode>('/') ); + if (baseURL.matchAsciiL( + RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.expand:") )) { + // encode for macro expansion: relPath is supposed to have no + // macros, so encode $, {} \ (bootstrap mimic) + relPath = encodeForRcFile(relPath); + + // encode once more for vnd.sun.star.expand schema: + // vnd.sun.star.expand:$UNO_... + // will expand to file-url + relPath = ::rtl::Uri::encode( relPath, rtl_UriCharClassUric, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ); + } + buf.append( relPath ); + } + return buf.makeStringAndClear(); +} + +OUString makeURLAppendSysPathSegment( OUString const & baseURL, OUString const & relPath_ ) +{ + OUString segment = relPath_; + OSL_ASSERT(segment.indexOf(static_cast<sal_Unicode>('/')) == -1); + + ::rtl::Uri::encode( + segment, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8); + return makeURL(baseURL, segment); +} + + + +//============================================================================== +OUString expandUnoRcTerm( OUString const & term_ ) +{ + OUString term(term_); + UnoRc::get()->expandMacrosFrom( term ); + return term; +} + +OUString makeRcTerm( OUString const & url ) +{ + OSL_ASSERT( url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( + "vnd.sun.star.expand:") ) ); + if (url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.expand:") )) { + // cut protocol: + OUString rcterm( url.copy( sizeof ("vnd.sun.star.expand:") - 1 ) ); + // decode uric class chars: + rcterm = ::rtl::Uri::decode( + rcterm, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); + return rcterm; + } + else + return url; +} + +//============================================================================== +OUString expandUnoRcUrl( OUString const & url ) +{ + if (url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.expand:") )) { + // cut protocol: + OUString rcurl( url.copy( sizeof ("vnd.sun.star.expand:") - 1 ) ); + // decode uric class chars: + rcurl = ::rtl::Uri::decode( + rcurl, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); + // expand macro string: + UnoRc::get()->expandMacrosFrom( rcurl ); + return rcurl; + } + else { + return url; + } +} + +//============================================================================== +bool office_is_running() +{ + //We need to check if we run within the office process. Then we must not use the pipe, because + //this could cause a deadlock. This is actually a workaround for i82778 + OUString sFile; + oslProcessError err = osl_getExecutableFile(& sFile.pData); + bool ret = false; + if (osl_Process_E_None == err) + { + sFile = sFile.copy(sFile.lastIndexOf('/') + 1); + if ( +#if defined UNIX + sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SOFFICE2))) +#elif defined WNT || defined OS2 + //osl_getExecutableFile should deliver "soffice.bin" on windows + //even if swriter.exe, scalc.exe etc. was started. This is a bug + //in osl_getExecutableFile + sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SOFFICE1))) + || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SOFFICE2))) + || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SBASE))) + || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SCALC))) + || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SDRAW))) + || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SIMPRESS))) + || sFile.equals(OUString(RTL_CONSTASCII_USTRINGPARAM(SWRITER))) +#else +#error "Unsupported platform" +#endif + + ) + ret = true; + else + ret = existsOfficePipe(); + } + else + { + OSL_ENSURE(0, "NOT osl_Process_E_None "); + //if osl_getExecutable file than we take the risk of creating a pipe + ret = existsOfficePipe(); + } + return ret; +} + +//============================================================================== +oslProcess raiseProcess( + OUString const & appURL, Sequence<OUString> const & args ) +{ + ::osl::Security sec; + oslProcess hProcess = 0; + oslProcessError rc = osl_executeProcess( + appURL.pData, + reinterpret_cast<rtl_uString **>( + const_cast<OUString *>(args.getConstArray()) ), + args.getLength(), + osl_Process_DETACHED, + sec.getHandle(), + 0, // => current working dir + 0, 0, // => no env vars + &hProcess ); + + switch (rc) { + case osl_Process_E_None: + break; + case osl_Process_E_NotFound: + throw RuntimeException( OUSTR("image not found!"), 0 ); + case osl_Process_E_TimedOut: + throw RuntimeException( OUSTR("timout occured!"), 0 ); + case osl_Process_E_NoPermission: + throw RuntimeException( OUSTR("permission denied!"), 0 ); + case osl_Process_E_Unknown: + throw RuntimeException( OUSTR("unknown error!"), 0 ); + case osl_Process_E_InvalidError: + default: + throw RuntimeException( OUSTR("unmapped error!"), 0 ); + } + + return hProcess; +} + +//============================================================================== +OUString generateRandomPipeId() +{ + // compute some good pipe id: + static rtlRandomPool s_hPool = rtl_random_createPool(); + if (s_hPool == 0) + throw RuntimeException( OUSTR("cannot create random pool!?"), 0 ); + sal_uInt8 bytes[ 32 ]; + if (rtl_random_getBytes( + s_hPool, bytes, ARLEN(bytes) ) != rtl_Random_E_None) { + throw RuntimeException( OUSTR("random pool error!?"), 0 ); + } + ::rtl::OUStringBuffer buf; + for ( sal_uInt32 i = 0; i < ARLEN(bytes); ++i ) { + buf.append( static_cast<sal_Int32>(bytes[ i ]), 0x10 ); + } + return buf.makeStringAndClear(); +} + +//============================================================================== +Reference<XInterface> resolveUnoURL( + OUString const & connectString, + Reference<XComponentContext> const & xLocalContext, + AbortChannel * abortChannel ) +{ + Reference<bridge::XUnoUrlResolver> xUnoUrlResolver( + bridge::UnoUrlResolver::create( xLocalContext ) ); + + for (;;) + { + if (abortChannel != 0 && abortChannel->isAborted()) { + throw ucb::CommandAbortedException( + OUSTR("abort!"), Reference<XInterface>() ); + } + try { + return xUnoUrlResolver->resolve( connectString ); + } + catch (connection::NoConnectException &) { + TimeValue tv = { 0 /* secs */, 500000000 /* nanosecs */ }; + ::osl::Thread::wait( tv ); + } + } +} + +#ifdef WNT +void writeConsoleWithStream(::rtl::OUString const & sText, HANDLE stream) +{ + DWORD nWrittenChars = 0; + WriteFile(stream, sText.getStr(), + sText.getLength() * 2, &nWrittenChars, NULL); +} +#else +void writeConsoleWithStream(::rtl::OUString const & sText, FILE * stream) +{ + OString s = OUStringToOString(sText, osl_getThreadTextEncoding()); + fprintf(stream, "%s", s.getStr()); + fflush(stream); +} +#endif + +#ifdef WNT +void writeConsoleWithStream(::rtl::OString const & sText, HANDLE stream) +{ + writeConsoleWithStream(OStringToOUString( + sText, RTL_TEXTENCODING_UTF8), stream); +} +#else +void writeConsoleWithStream(::rtl::OString const & sText, FILE * stream) +{ + fprintf(stream, "%s", sText.getStr()); + fflush(stream); +} +#endif + +void writeConsole(::rtl::OUString const & sText) +{ +#ifdef WNT + writeConsoleWithStream(sText, GetStdHandle(STD_OUTPUT_HANDLE)); +#else + writeConsoleWithStream(sText, stdout); +#endif +} + +void writeConsole(::rtl::OString const & sText) +{ +#ifdef WNT + writeConsoleWithStream(sText, GetStdHandle(STD_OUTPUT_HANDLE)); +#else + writeConsoleWithStream(sText, stdout); +#endif +} + +void writeConsoleError(::rtl::OUString const & sText) +{ +#ifdef WNT + writeConsoleWithStream(sText, GetStdHandle(STD_ERROR_HANDLE)); +#else + writeConsoleWithStream(sText, stderr); +#endif +} + + +void writeConsoleError(::rtl::OString const & sText) +{ +#ifdef WNT + writeConsoleWithStream(sText, GetStdHandle(STD_ERROR_HANDLE)); +#else + writeConsoleWithStream(sText, stderr); +#endif +} + + + +OUString readConsole() +{ +#ifdef WNT + sal_Unicode aBuffer[1024]; + DWORD dwRead = 0; + //unopkg.com feeds unopkg.exe with wchar_t|s + if (ReadFile( GetStdHandle(STD_INPUT_HANDLE), &aBuffer, sizeof(aBuffer), &dwRead, NULL ) ) + { + OSL_ASSERT((dwRead % 2) == 0); + OUString value( aBuffer, dwRead / 2); + return value.trim(); + } +#else + char buf[1024]; + rtl_zeroMemory(buf, 1024); + // read one char less so that the last char in buf is always zero + if (fgets(buf, 1024, stdin) != NULL) + { + OUString value = ::rtl::OStringToOUString(::rtl::OString(buf), osl_getThreadTextEncoding()); + return value.trim(); + } +#endif + return OUString(); +} + +void TRACE(::rtl::OUString const & sText) +{ + (void) sText; +#if OSL_DEBUG_LEVEL > 1 + writeConsole(sText); +#endif +} + +void TRACE(::rtl::OString const & sText) +{ + (void) sText; +#if OSL_DEBUG_LEVEL > 1 + writeConsole(sText); +#endif +} + +void syncRepositories(Reference<ucb::XCommandEnvironment> const & xCmdEnv) +{ + OUString sDisable; + ::rtl::Bootstrap::get( OUSTR( "DISABLE_EXTENSION_SYNCHRONIZATION" ), sDisable, OUString() ); + if (sDisable.getLength() > 0) + return; + + Reference<deployment::XExtensionManager> xExtensionManager; + //synchronize shared before bundled otherewise there are + //more revoke and registration calls. + sal_Bool bModified = false; + if (needToSyncRepostitory(OUString(RTL_CONSTASCII_USTRINGPARAM("shared"))) + || needToSyncRepostitory(OUString(RTL_CONSTASCII_USTRINGPARAM("bundled")))) + { + xExtensionManager = + deployment::ExtensionManager::get( + comphelper_getProcessComponentContext()); + + if (xExtensionManager.is()) + { + bModified = xExtensionManager->synchronize( + Reference<task::XAbortChannel>(), xCmdEnv); + } + } + + if (bModified) + { + Reference<task::XRestartManager> restarter( + comphelper_getProcessComponentContext()->getValueByName( + OUSTR( "/singletons/com.sun.star.task.OfficeRestartManager") ), UNO_QUERY ); + if (restarter.is()) + { + OSL_TRACE( "Request restart for modified extensions manager" ); + restarter->requestRestart(xCmdEnv.is() == sal_True ? xCmdEnv->getInteractionHandler() : + Reference<task::XInteractionHandler>()); + } + } +} + + + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_misc.hrc b/desktop/source/deployment/misc/dp_misc.hrc new file mode 100644 index 000000000000..e5d749fc62a1 --- /dev/null +++ b/desktop/source/deployment/misc/dp_misc.hrc @@ -0,0 +1,33 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_MISC_HRC +#define INCLUDED_DP_MISC_HRC + +#include "deployment.hrc" + +#endif diff --git a/desktop/source/deployment/misc/dp_misc.src b/desktop/source/deployment/misc/dp_misc.src new file mode 100644 index 000000000000..78e87c20787a --- /dev/null +++ b/desktop/source/deployment/misc/dp_misc.src @@ -0,0 +1,40 @@ +/************************************************************************* + * + * 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 "dp_misc.hrc" + +String RID_DEPLYOMENT_DEPENDENCIES_UNKNOWN { + Text[en-US] = "Unknown"; +}; + +String RID_DEPLYOMENT_DEPENDENCIES_MIN { + Text[en-US] = "Extensions requires at least OpenOffice.org %VERSION"; +}; + +String RID_DEPLYOMENT_DEPENDENCIES_MAX { + Text[en-US] = "Extension doesn't support versions greater than: OpenOffice.org %VERSION"; +}; diff --git a/desktop/source/deployment/misc/dp_platform.cxx b/desktop/source/deployment/misc/dp_platform.cxx new file mode 100644 index 000000000000..0e67097df572 --- /dev/null +++ b/desktop/source/deployment/misc/dp_platform.cxx @@ -0,0 +1,249 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_misc.h" +#include "dp_platform.hxx" +#include "rtl/ustring.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/instance.hxx" +#include "rtl/bootstrap.hxx" + +#define PLATFORM_ALL "all" +#define PLATFORM_WIN_X86 "windows_x86" +#define PLATFORM_LINUX_X86 "linux_x86" +#define PLATFORM_LINUX_X86_64 "linux_x86_64" +#define PLATFORM_KFREEBSD_X86 "kfreebsd_x86" +#define PLATFORM_KFREEBSD_X86_64 "kfreebsd_x86_64" +#define PLATFORM_LINUX_SPARC "linux_sparc" +#define PLATFORM_LINUX_POWERPC "linux_powerpc" +#define PLATFORM_LINUX_POWERPC64 "linux_powerpc64" +#define PLATFORM_LINUX_ARM_EABI "linux_arm_eabi" +#define PLATFORM_LINUX_ARM_OABI "linux_arm_oabi" +#define PLATFORM_LINUX_MIPS_EL "linux_mips_el" +#define PLATFORM_LINUX_MIPS_EB "linux_mips_eb" +#define PLATFORM_LINUX_IA64 "linux_ia64" +#define PLATFORM_LINUX_M68K "linux_m68k" +#define PLATFORM_LINUX_S390 "linux_s390" +#define PLATFORM_LINUX_S390x "linux_s390x" +#define PLATFORM_LINUX_HPPA "linux_hppa" +#define PLATFORM_LINUX_ALPHA "linux_alpha" + + + +#define PLATFORM_SOLARIS_SPARC "solaris_sparc" +#define PLATFORM_SOLARIS_SPARC64 "solaris_sparc64" +#define PLATFORM_SOLARIS_X86 "solaris_x86" +#define PLATFORM_FREEBSD_X86 "freebsd_x86" +#define PLATFORM_FREEBSD_X86_64 "freebsd_x86_64" +#define PLATFORM_NETBSD_X86 "netbsd_x86" +#define PLATFORM_NETBSD_X86_64 "netbsd_x86_64" +#define PLATFORM_MACOSX_X86 "macosx_x86" +#define PLATFORM_MACOSX_PPC "macosx_powerpc" +#define PLATFORM_OS2_X86 "os2_x86" +#define PLATFORM_OPENBSD_X86 "openbsd_x86" +#define PLATFORM_OPENBSD_X86_64 "openbsd_x86_64" + + +#define PLATFORM_AIX_POWERPC "aix_powerpc" + + + + + + + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) +using ::rtl::OUString; +namespace css = ::com::sun::star; + +namespace dp_misc +{ +namespace +{ + struct StrOperatingSystem : + public rtl::StaticWithInit<const OUString, StrOperatingSystem> { + const OUString operator () () { + OUString os( RTL_CONSTASCII_USTRINGPARAM("$_OS") ); + ::rtl::Bootstrap::expandMacros( os ); + return os; + } + }; + + struct StrCPU : + public rtl::StaticWithInit<const OUString, StrCPU> { + const OUString operator () () { + OUString arch( RTL_CONSTASCII_USTRINGPARAM("$_ARCH") ); + ::rtl::Bootstrap::expandMacros( arch ); + return arch; + } + }; + + + struct StrPlatform : public rtl::StaticWithInit< + const OUString, StrPlatform> { + const OUString operator () () { + ::rtl::OUStringBuffer buf; + buf.append( StrOperatingSystem::get() ); + buf.append( static_cast<sal_Unicode>('_') ); + OUString arch( RTL_CONSTASCII_USTRINGPARAM("$_ARCH") ); + ::rtl::Bootstrap::expandMacros( arch ); + buf.append( arch ); + return buf.makeStringAndClear(); + } + }; + + bool checkOSandCPU(OUString const & os, OUString const & cpu) + { + return os.equals(StrOperatingSystem::get()) + && cpu.equals(StrCPU::get()); + } + + bool isValidPlatform(OUString const & token ) + { + bool ret = false; + if (token.equals(OUSTR(PLATFORM_ALL))) + ret = true; + else if (token.equals(OUSTR(PLATFORM_WIN_X86))) + ret = checkOSandCPU(OUSTR("Windows"), OUSTR("x86")); + else if (token.equals(OUSTR(PLATFORM_LINUX_X86))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("x86")); + else if (token.equals(OUSTR(PLATFORM_LINUX_X86_64))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("X86_64")); + else if (token.equals(OUSTR(PLATFORM_KFREEBSD_X86))) + ret = checkOSandCPU(OUSTR("kFreeBSD"), OUSTR("x86")); + else if (token.equals(OUSTR(PLATFORM_KFREEBSD_X86_64))) + ret = checkOSandCPU(OUSTR("kFreeBSD"), OUSTR("X86_64")); + else if (token.equals(OUSTR(PLATFORM_LINUX_SPARC))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("SPARC")); + else if (token.equals(OUSTR(PLATFORM_LINUX_POWERPC))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("PowerPC")); + else if (token.equals(OUSTR(PLATFORM_LINUX_POWERPC64))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("PowerPC_64")); + else if (token.equals(OUSTR(PLATFORM_LINUX_ARM_EABI))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("ARM_EABI")); + else if (token.equals(OUSTR(PLATFORM_LINUX_ARM_OABI))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("ARM_OABI")); + else if (token.equals(OUSTR(PLATFORM_LINUX_MIPS_EL))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("MIPS_EL")); + else if (token.equals(OUSTR(PLATFORM_LINUX_MIPS_EB))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("MIPS_EB")); + else if (token.equals(OUSTR(PLATFORM_LINUX_IA64))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("IA64")); + else if (token.equals(OUSTR(PLATFORM_LINUX_M68K))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("M68K")); + else if (token.equals(OUSTR(PLATFORM_LINUX_S390))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("S390")); + else if (token.equals(OUSTR(PLATFORM_LINUX_S390x))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("S390x")); + else if (token.equals(OUSTR(PLATFORM_LINUX_HPPA))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("HPPA")); + else if (token.equals(OUSTR(PLATFORM_LINUX_ALPHA))) + ret = checkOSandCPU(OUSTR("Linux"), OUSTR("ALPHA")); + else if (token.equals(OUSTR(PLATFORM_SOLARIS_SPARC))) + ret = checkOSandCPU(OUSTR("Solaris"), OUSTR("SPARC")); + else if (token.equals(OUSTR(PLATFORM_SOLARIS_SPARC64))) + ret = checkOSandCPU(OUSTR("Solaris"), OUSTR("SPARC64")); + else if (token.equals(OUSTR(PLATFORM_SOLARIS_X86))) + ret = checkOSandCPU(OUSTR("Solaris"), OUSTR("x86")); + else if (token.equals(OUSTR(PLATFORM_FREEBSD_X86))) + ret = checkOSandCPU(OUSTR("FreeBSD"), OUSTR("x86")); + else if (token.equals(OUSTR(PLATFORM_FREEBSD_X86_64))) + ret = checkOSandCPU(OUSTR("FreeBSD"), OUSTR("X86_64")); + else if (token.equals(OUSTR(PLATFORM_NETBSD_X86))) + ret = checkOSandCPU(OUSTR("NetBSD"), OUSTR("x86")); + else if (token.equals(OUSTR(PLATFORM_NETBSD_X86_64))) + ret = checkOSandCPU(OUSTR("NetBSD"), OUSTR("X86_64")); + else if (token.equals(OUSTR(PLATFORM_MACOSX_X86))) + ret = checkOSandCPU(OUSTR("MacOSX"), OUSTR("x86")); + else if (token.equals(OUSTR(PLATFORM_MACOSX_PPC))) + ret = checkOSandCPU(OUSTR("MacOSX"), OUSTR("PowerPC")); + else if (token.equals(OUSTR(PLATFORM_OS2_X86))) + ret = checkOSandCPU(OUSTR("OS2"), OUSTR("x86")); + else if (token.equals(OUSTR(PLATFORM_AIX_POWERPC))) + ret = checkOSandCPU(OUSTR("AIX"), OUSTR("PowerPC")); + else if (token.equals(OUSTR(PLATFORM_OPENBSD_X86))) + ret = checkOSandCPU(OUSTR("OpenBSD"), OUSTR("x86")); + else if (token.equals(OUSTR(PLATFORM_OPENBSD_X86_64))) + ret = checkOSandCPU(OUSTR("OpenBSD"), OUSTR("X86_64")); + else + { + OSL_ENSURE(0, "Extension Manager: The extension supports an unknown platform. " + "Check the platform element in the description.xml"); + ret = false; + } + return ret; + } + +} // anon namespace +//============================================================================= + +OUString const & getPlatformString() +{ + return StrPlatform::get(); +} + +bool platform_fits( OUString const & platform_string ) +{ + sal_Int32 index = 0; + for (;;) + { + const OUString token( + platform_string.getToken( 0, ',', index ).trim() ); + // check if this platform: + if (token.equalsIgnoreAsciiCase( StrPlatform::get() ) || + (token.indexOf( '_' ) < 0 && /* check OS part only */ + token.equalsIgnoreAsciiCase( StrOperatingSystem::get() ))) + { + return true; + } + if (index < 0) + break; + } + return false; +} + +bool hasValidPlatform( css::uno::Sequence<OUString> const & platformStrings) +{ + bool ret = false; + for (sal_Int32 i = 0; i < platformStrings.getLength(); i++) + { + if (isValidPlatform(platformStrings[i])) + { + ret = true; + break; + } + } + return ret; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_resource.cxx b/desktop/source/deployment/misc/dp_resource.cxx new file mode 100644 index 000000000000..eb92eabba38d --- /dev/null +++ b/desktop/source/deployment/misc/dp_resource.cxx @@ -0,0 +1,235 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_misc.h" +#include "dp_resource.h" +#include "osl/module.hxx" +#include "osl/mutex.hxx" +#include "rtl/ustring.h" +#include "cppuhelper/implbase1.hxx" +#include "unotools/configmgr.hxx" + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +namespace dp_misc { +namespace { + +struct OfficeLocale : + public rtl::StaticWithInit<const OUString, OfficeLocale> { + const OUString operator () () { + OUString slang; + if (! (::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::LOCALE ) >>= slang)) + throw RuntimeException( OUSTR("Cannot determine language!"), 0 ); + //fallback, the locale is currently only set when the user starts the + //office for the first time. + if (slang.getLength() == 0) + slang = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("en-US")); + return slang; + } +}; + +struct DeploymentResMgr : public rtl::StaticWithInit< + ResMgr *, DeploymentResMgr> { + ResMgr * operator () () { + return ResMgr::CreateResMgr( "deployment", getOfficeLocale() ); + } +}; + +osl::Mutex s_mutex; + +} // anon namespace + +//============================================================================== +ResId getResId( USHORT id ) +{ + const osl::MutexGuard guard( s_mutex ); + return ResId( id, *DeploymentResMgr::get() ); +} + +//============================================================================== +String getResourceString( USHORT id ) +{ + const osl::MutexGuard guard( s_mutex ); + String ret( ResId( id, *DeploymentResMgr::get() ) ); + if (ret.SearchAscii( "%PRODUCTNAME" ) != STRING_NOTFOUND) { + static String s_brandName; + if (s_brandName.Len() == 0) { + OUString brandName( + ::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::PRODUCTNAME ).get<OUString>() ); + s_brandName = brandName; + } + ret.SearchAndReplaceAllAscii( "%PRODUCTNAME", s_brandName ); + } + return ret; +} + +//throws an Exception on failure +//primary subtag 2 or three letters(A-Z, a-z), i or x +void checkPrimarySubtag(::rtl::OUString const & tag) +{ + sal_Int32 len = tag.getLength(); + sal_Unicode const * arLang = tag.getStr(); + if (len < 1 || len > 3) + throw Exception(OUSTR("Invalid language string."), 0); + + if (len == 1 + && (arLang[0] != 'i' && arLang[0] != 'x')) + throw Exception(OUSTR("Invalid language string."), 0); + + if (len == 2 || len == 3) + { + for (sal_Int32 i = 0; i < len; i++) + { + if ( !((arLang[i] >= 'A' && arLang[i] <= 'Z') + || (arLang[i] >= 'a' && arLang[i] <= 'z'))) + { + throw Exception(OUSTR("Invalid language string."), 0); + } + } + } +} + +//throws an Exception on failure +//second subtag 2 letter country code or 3-8 letter other code(A-Z, a-z, 0-9) +void checkSecondSubtag(::rtl::OUString const & tag, bool & bIsCountry) +{ + sal_Int32 len = tag.getLength(); + sal_Unicode const * arLang = tag.getStr(); + if (len < 2 || len > 8) + throw Exception(OUSTR("Invalid language string."), 0); + //country code + bIsCountry = false; + if (len == 2) + { + for (sal_Int32 i = 0; i < 2; i++) + { + if (!( (arLang[i] >= 'A' && arLang[i] <= 'Z') + || (arLang[i] >= 'a' && arLang[i] <= 'z'))) + { + throw Exception(OUSTR("Invalid language string."), 0); + } + } + bIsCountry = true; + } + + if (len > 2) + { + for (sal_Int32 i = 0; i < len; i++) + { + if (!( (arLang[i] >= 'A' && arLang[i] <= 'Z') + || (arLang[i] >= 'a' && arLang[i] <= 'z') + || (arLang[i] >= '0' && arLang[i] <= '9') )) + { + throw Exception(OUSTR("Invalid language string."), 0); + } + } + } +} + +void checkThirdSubtag(::rtl::OUString const & tag) +{ + sal_Int32 len = tag.getLength(); + sal_Unicode const * arLang = tag.getStr(); + if (len < 1 || len > 8) + throw Exception(OUSTR("Invalid language string."), 0); + + for (sal_Int32 i = 0; i < len; i++) + { + if (!( (arLang[i] >= 'A' && arLang[i] <= 'Z') + || (arLang[i] >= 'a' && arLang[i] <= 'z') + || (arLang[i] >= '0' && arLang[i] <= '9') )) + { + throw Exception(OUSTR("Invalid language string."), 0); + } + } +} + +//============================================================================= + +//We parse the string acording to RFC 3066 +//We only use the primary sub-tag and two subtags. That is lang-country-variant +//We do some simple tests if the string is correct. Actually this should do a +//validating parser +//We may have the case that there is no country tag, for example en-welsh +::com::sun::star::lang::Locale toLocale( ::rtl::OUString const & slang ) +{ + OUString _sLang = slang.trim(); + ::com::sun::star::lang::Locale locale; + sal_Int32 nIndex = 0; + OUString lang = _sLang.getToken( 0, '-', nIndex ); + checkPrimarySubtag(lang); + locale.Language = lang; + OUString country = _sLang.getToken( 0, '-', nIndex ); + if (country.getLength() > 0) + { + bool bIsCountry = false; + checkSecondSubtag(country, bIsCountry); + if (bIsCountry) + { + locale.Country = country; + } + else + { + locale.Variant = country; + } + } + if (locale.Variant.getLength() == 0) + { + OUString variant = _sLang.getToken( 0, '-', nIndex ); + if (variant.getLength() > 0) + { + checkThirdSubtag(variant); + locale.Variant = variant; + } + } + + return locale; +} + +//============================================================================== +lang::Locale getOfficeLocale() +{ + return toLocale(OfficeLocale::get()); +} + +::rtl::OUString getOfficeLocaleString() +{ + return OfficeLocale::get(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_ucb.cxx b/desktop/source/deployment/misc/dp_ucb.cxx new file mode 100644 index 000000000000..170a403ddc74 --- /dev/null +++ b/desktop/source/deployment/misc/dp_ucb.cxx @@ -0,0 +1,323 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_misc.hrc" +#include "dp_misc.h" +#include "dp_ucb.h" +#include "rtl/uri.hxx" +#include "rtl/ustrbuf.hxx" +#include "ucbhelper/content.hxx" +#include "xmlscript/xml_helper.hxx" +#include "com/sun/star/io/XInputStream.hpp" +#include "com/sun/star/ucb/CommandFailedException.hpp" +#include "com/sun/star/ucb/ContentInfo.hpp" +#include "com/sun/star/ucb/ContentInfoAttribute.hpp" + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; + +namespace dp_misc +{ + +const OUString StrTitle::operator () () +{ + return OUSTR("Title"); +} + +//============================================================================== +bool create_ucb_content( + ::ucbhelper::Content * ret_ucbContent, OUString const & url, + Reference<XCommandEnvironment> const & xCmdEnv, + bool throw_exc ) +{ + try { + // Existense check... + // content ctor/isFolder() will throw exception in case the resource + // does not exist. + + // dilemma: no chance to use the given iahandler here, because it would + // raise no such file dialogs, else no interaction for + // passwords, ...? xxx todo + ::ucbhelper::Content ucbContent( + url, Reference<XCommandEnvironment>() ); + + ucbContent.isFolder(); + + if (ret_ucbContent != 0) + { + ucbContent.setCommandEnvironment( xCmdEnv ); + *ret_ucbContent = ucbContent; + } + return true; + } + catch (RuntimeException &) { + throw; + } + catch (Exception &) { + if (throw_exc) + throw; + } + return false; +} + +//============================================================================== +bool create_folder( + ::ucbhelper::Content * ret_ucb_content, OUString const & url_, + Reference<XCommandEnvironment> const & xCmdEnv, bool throw_exc ) +{ + ::ucbhelper::Content ucb_content; + if (create_ucb_content( + &ucb_content, url_, xCmdEnv, false /* no throw */ )) + { + if (ucb_content.isFolder()) { + if (ret_ucb_content != 0) + *ret_ucb_content = ucb_content; + return true; + } + } + + OUString url( url_ ); + // xxx todo: find parent + sal_Int32 slash = url.lastIndexOf( '/' ); + if (slash < 0) { + // fallback: + url = expandUnoRcUrl( url ); + slash = url.lastIndexOf( '/' ); + } + if (slash < 0) { + // invalid: has to be at least "auth:/..." + if (throw_exc) + throw ContentCreationException( + OUSTR("Cannot create folder (invalid path): ") + url, + Reference<XInterface>(), ContentCreationError_UNKNOWN ); + return false; + } + ::ucbhelper::Content parentContent; + if (! create_folder( + &parentContent, url.copy( 0, slash ), xCmdEnv, throw_exc )) + return false; + const Any title( ::rtl::Uri::decode( url.copy( slash + 1 ), + rtl_UriDecodeWithCharset, + RTL_TEXTENCODING_UTF8 ) ); + const Sequence<ContentInfo> infos( + parentContent.queryCreatableContentsInfo() ); + for ( sal_Int32 pos = 0; pos < infos.getLength(); ++pos ) + { + // look KIND_FOLDER: + ContentInfo const & info = infos[ pos ]; + if ((info.Attributes & ContentInfoAttribute::KIND_FOLDER) != 0) + { + // make sure the only required bootstrap property is "Title": + Sequence<beans::Property> const & rProps = info.Properties; + if (rProps.getLength() != 1 || + !rProps[ 0 ].Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("Title") )) + continue; + + try { + if (parentContent.insertNewContent( + info.Type, + Sequence<OUString>( &StrTitle::get(), 1 ), + Sequence<Any>( &title, 1 ), + ucb_content )) { + if (ret_ucb_content != 0) + *ret_ucb_content = ucb_content; + return true; + } + } + catch (RuntimeException &) { + throw; + } + catch (CommandFailedException &) { + // Interaction Handler already handled the error + // that has occured... + } + catch (Exception &) { + if (throw_exc) + throw; + return false; + } + } + } + if (throw_exc) + throw ContentCreationException( + OUSTR("Cannot create folder: ") + url, + Reference<XInterface>(), ContentCreationError_UNKNOWN ); + return false; +} + +//============================================================================== +bool erase_path( OUString const & url, + Reference<XCommandEnvironment> const & xCmdEnv, + bool throw_exc ) +{ + ::ucbhelper::Content ucb_content; + if (create_ucb_content( &ucb_content, url, xCmdEnv, false /* no throw */ )) + { + try { + ucb_content.executeCommand( + OUSTR("delete"), Any( true /* delete physically */ ) ); + } + catch (RuntimeException &) { + throw; + } + catch (Exception &) { + if (throw_exc) + throw; + return false; + } + } + return true; +} + +//============================================================================== +::rtl::ByteSequence readFile( ::ucbhelper::Content & ucb_content ) +{ + ::rtl::ByteSequence bytes; + Reference<io::XOutputStream> xStream( + ::xmlscript::createOutputStream( &bytes ) ); + if (! ucb_content.openStream( xStream )) + throw RuntimeException( + OUSTR( + "::ucbhelper::Content::openStream( XOutputStream ) failed!"), + 0 ); + return bytes; +} + +//============================================================================== +bool readLine( OUString * res, OUString const & startingWith, + ::ucbhelper::Content & ucb_content, rtl_TextEncoding textenc ) +{ + // read whole file: + ::rtl::ByteSequence bytes( readFile( ucb_content ) ); + OUString file( reinterpret_cast<sal_Char const *>(bytes.getConstArray()), + bytes.getLength(), textenc ); + sal_Int32 pos = 0; + for (;;) + { + if (file.match( startingWith, pos )) + { + ::rtl::OUStringBuffer buf; + sal_Int32 start = pos; + pos += startingWith.getLength(); + for (;;) + { + pos = file.indexOf( LF, pos ); + if (pos < 0) { // EOF + buf.append( file.copy( start ) ); + } + else + { + if (pos > 0 && file[ pos - 1 ] == CR) + { + // consume extra CR + buf.append( file.copy( start, pos - start - 1 ) ); + ++pos; + } + else + buf.append( file.copy( start, pos - start ) ); + ++pos; // consume LF + // check next line: + if (pos < file.getLength() && + (file[ pos ] == ' ' || file[ pos ] == '\t')) + { + buf.append( static_cast<sal_Unicode>(' ') ); + ++pos; + start = pos; + continue; + } + } + break; + } + *res = buf.makeStringAndClear(); + return true; + } + // next line: + sal_Int32 next_lf = file.indexOf( LF, pos ); + if (next_lf < 0) // EOF + break; + pos = next_lf + 1; + } + return false; +} + +bool readProperties( ::std::list< ::std::pair< ::rtl::OUString, ::rtl::OUString> > & out_result, + ::ucbhelper::Content & ucb_content ) +{ + // read whole file: + ::rtl::ByteSequence bytes( readFile( ucb_content ) ); + OUString file( reinterpret_cast<sal_Char const *>(bytes.getConstArray()), + bytes.getLength(), RTL_TEXTENCODING_UTF8); + sal_Int32 pos = 0; + + for (;;) + { + + ::rtl::OUStringBuffer buf; + sal_Int32 start = pos; + + bool bEOF = false; + pos = file.indexOf( LF, pos ); + if (pos < 0) { // EOF + buf.append( file.copy( start ) ); + bEOF = true; + } + else + { + if (pos > 0 && file[ pos - 1 ] == CR) + // consume extra CR + buf.append( file.copy( start, pos - start - 1 ) ); + else + buf.append( file.copy( start, pos - start ) ); + pos++; + } + OUString aLine = buf.makeStringAndClear(); + + sal_Int32 posEqual = aLine.indexOf('='); + if (posEqual > 0 && (posEqual + 1) < aLine.getLength()) + { + OUString name = aLine.copy(0, posEqual); + OUString value = aLine.copy(posEqual + 1); + out_result.push_back(::std::make_pair(name, value)); + } + + if (bEOF) + break; + } + return false; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_update.cxx b/desktop/source/deployment/misc/dp_update.cxx new file mode 100644 index 000000000000..531409f0630a --- /dev/null +++ b/desktop/source/deployment/misc/dp_update.cxx @@ -0,0 +1,450 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_update.hxx" +#include "dp_version.hxx" +#include "dp_identifier.hxx" +#include "dp_descriptioninfoset.hxx" + +#include "rtl/bootstrap.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; +using ::rtl::OString; + + +namespace dp_misc { +namespace { + +int determineHighestVersion( + ::rtl::OUString const & userVersion, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion) +{ + int index = 0; + OUString greatest = userVersion; + if (dp_misc::compareVersions(sharedVersion, greatest) == dp_misc::GREATER) + { + index = 1; + greatest = sharedVersion; + } + if (dp_misc::compareVersions(bundledVersion, greatest) == dp_misc::GREATER) + { + index = 2; + greatest = bundledVersion; + } + if (dp_misc::compareVersions(onlineVersion, greatest) == dp_misc::GREATER) + { + index = 3; + } + return index; +} + +Sequence< Reference< xml::dom::XElement > > +getUpdateInformation( Reference<deployment::XUpdateInformationProvider > const & updateInformation, + Sequence< OUString > const & urls, + OUString const & identifier, + uno::Any & out_error) +{ + try { + return updateInformation->getUpdateInformation(urls, identifier); + } catch (uno::RuntimeException &) { + throw; + } catch (ucb::CommandFailedException & e) { + out_error = e.Reason; + } catch (ucb::CommandAbortedException &) { + } catch (uno::Exception & e) { + out_error = uno::makeAny(e); + } + return + Sequence<Reference< xml::dom::XElement > >(); +} + +void getOwnUpdateInfos( + Reference<uno::XComponentContext> const & xContext, + Reference<deployment::XUpdateInformationProvider > const & updateInformation, + UpdateInfoMap& inout_map, std::vector<std::pair<Reference<deployment::XPackage>, uno::Any> > & out_errors, + bool & out_allFound) +{ + bool allHaveOwnUpdateInformation = true; + for (UpdateInfoMap::iterator i = inout_map.begin(); i != inout_map.end(); i++) + { + OSL_ASSERT(i->second.extension.is()); + Sequence<OUString> urls(i->second.extension->getUpdateInformationURLs()); + if (urls.getLength()) + { + const OUString id = dp_misc::getIdentifier(i->second.extension); + uno::Any anyError; + //It is unclear from the idl if there can be a null reference returned. + //However all valid information should be the same + Sequence<Reference< xml::dom::XElement > > + infos(getUpdateInformation(updateInformation, urls, id, anyError)); + if (anyError.hasValue()) + out_errors.push_back(std::make_pair(i->second.extension, anyError)); + + for (sal_Int32 j = 0; j < infos.getLength(); ++j) + { + dp_misc::DescriptionInfoset infoset( + xContext, + Reference< xml::dom::XNode >(infos[j], UNO_QUERY_THROW)); + if (!infoset.hasDescription()) + continue; + boost::optional< OUString > id2(infoset.getIdentifier()); + if (!id2) + continue; + OSL_ASSERT(*id2 == id); + if (*id2 == id) + { + i->second.version = infoset.getVersion(); + i->second.info = Reference< xml::dom::XNode >( + infos[j], UNO_QUERY_THROW); + } + break; + } + } + else + { + allHaveOwnUpdateInformation &= false; + } + } + out_allFound = allHaveOwnUpdateInformation; +} + +void getDefaultUpdateInfos( + Reference<uno::XComponentContext> const & xContext, + Reference<deployment::XUpdateInformationProvider > const & updateInformation, + UpdateInfoMap& inout_map, + std::vector<std::pair<Reference<deployment::XPackage>, uno::Any> > & out_errors) +{ + const rtl::OUString sDefaultURL(dp_misc::getExtensionDefaultUpdateURL()); + OSL_ASSERT(sDefaultURL.getLength()); + + Any anyError; + Sequence< Reference< xml::dom::XElement > > + infos( + getUpdateInformation( + updateInformation, + Sequence< OUString >(&sDefaultURL, 1), OUString(), anyError)); + if (anyError.hasValue()) + out_errors.push_back(std::make_pair(Reference<deployment::XPackage>(), anyError)); + for (sal_Int32 i = 0; i < infos.getLength(); ++i) + { + Reference< xml::dom::XNode > node(infos[i], UNO_QUERY_THROW); + dp_misc::DescriptionInfoset infoset(xContext, node); + boost::optional< OUString > id(infoset.getIdentifier()); + if (!id) { + continue; + } + UpdateInfoMap::iterator j = inout_map.find(*id); + if (j != inout_map.end()) + { + //skip those extension which provide its own update urls + if (j->second.extension->getUpdateInformationURLs().getLength()) + continue; + OUString v(infoset.getVersion()); + //look for the highest version in the online repository + if (dp_misc::compareVersions(v, j->second.version) == + dp_misc::GREATER) + { + j->second.version = v; + j->second.info = node; + } + } + } +} + +bool containsBundledOnly(Sequence<Reference<deployment::XPackage> > const & sameIdExtensions) +{ + OSL_ASSERT(sameIdExtensions.getLength() == 3); + if (!sameIdExtensions[0].is() && !sameIdExtensions[1].is() && sameIdExtensions[2].is()) + return true; + else + return false; +} +/** Returns true if the list of extensions are bundled extensions and there are no + other extensions with the same identifier in the shared or user repository. + If extensionList is NULL, then it is checked if there are only bundled extensions. +*/ +bool onlyBundledExtensions( + Reference<deployment::XExtensionManager> const & xExtMgr, + std::vector< Reference<deployment::XPackage > > const * extensionList) +{ + OSL_ASSERT(xExtMgr.is()); + bool onlyBundled = true; + if (extensionList) + { + typedef std::vector<Reference<deployment::XPackage > >::const_iterator CIT; + for (CIT i = extensionList->begin(); i != extensionList->end(); i++) + { + Sequence<Reference<deployment::XPackage> > seqExt = xExtMgr->getExtensionsWithSameIdentifier( + dp_misc::getIdentifier(*i), (*i)->getName(), Reference<ucb::XCommandEnvironment>()); + + if (!containsBundledOnly(seqExt)) + { + onlyBundled = false; + break; + } + + } + } + else + { + const uno::Sequence< uno::Sequence< Reference<deployment::XPackage > > > seqAllExt = + xExtMgr->getAllExtensions(Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>()); + + for (int pos = seqAllExt.getLength(); pos --; ) + { + if (!containsBundledOnly(seqAllExt[pos])) + { + onlyBundled = false; + break; + } + } + } + return onlyBundled; +} + +} // anon namespace + + +OUString getExtensionDefaultUpdateURL() +{ + ::rtl::OUString sUrl( + RTL_CONSTASCII_USTRINGPARAM( + "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") + ":Version:ExtensionUpdateURL}")); + ::rtl::Bootstrap::expandMacros(sUrl); + return sUrl; +} + +/* returns the index of the greatest version, starting with 0 + + */ +UPDATE_SOURCE isUpdateUserExtension( + bool bReadOnlyShared, + ::rtl::OUString const & userVersion, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion) +{ + UPDATE_SOURCE retVal = UPDATE_SOURCE_NONE; + if (bReadOnlyShared) + { + if (userVersion.getLength()) + { + int index = determineHighestVersion( + userVersion, sharedVersion, bundledVersion, onlineVersion); + if (index == 1) + retVal = UPDATE_SOURCE_SHARED; + else if (index == 2) + retVal = UPDATE_SOURCE_BUNDLED; + else if (index == 3) + retVal = UPDATE_SOURCE_ONLINE; + } + else if (sharedVersion.getLength()) + { + int index = determineHighestVersion( + OUString(), sharedVersion, bundledVersion, onlineVersion); + if (index == 2) + retVal = UPDATE_SOURCE_BUNDLED; + else if (index == 3) + retVal = UPDATE_SOURCE_ONLINE; + + } + //No update for bundled extensions, they are updated only by the setup + //else if (bundledVersion.getLength()) + //{ + // int index = determineHighestVersion( + // OUString(), OUString(), bundledVersion, onlineVersion); + // if (index == 3) + // retVal = UPDATE_SOURCE_ONLINE; + //} + } + else + { + if (userVersion.getLength()) + { + int index = determineHighestVersion( + userVersion, sharedVersion, bundledVersion, onlineVersion); + if (index == 1) + retVal = UPDATE_SOURCE_SHARED; + else if (index == 2) + retVal = UPDATE_SOURCE_BUNDLED; + else if (index == 3) + retVal = UPDATE_SOURCE_ONLINE; + } + } + + return retVal; +} + +UPDATE_SOURCE isUpdateSharedExtension( + bool bReadOnlyShared, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion) +{ + if (bReadOnlyShared) + return UPDATE_SOURCE_NONE; + UPDATE_SOURCE retVal = UPDATE_SOURCE_NONE; + + if (sharedVersion.getLength()) + { + int index = determineHighestVersion( + OUString(), sharedVersion, bundledVersion, onlineVersion); + if (index == 2) + retVal = UPDATE_SOURCE_BUNDLED; + else if (index == 3) + retVal = UPDATE_SOURCE_ONLINE; + } + //No update for bundled extensions, they are updated only by the setup + //else if (bundledVersion.getLength()) + //{ + // int index = determineHighestVersion( + // OUString(), OUString(), bundledVersion, onlineVersion); + // if (index == 3) + // retVal = UPDATE_SOURCE_ONLINE; + //} + return retVal; +} + +Reference<deployment::XPackage> +getExtensionWithHighestVersion( + Sequence<Reference<deployment::XPackage> > const & seqExt) +{ + if (seqExt.getLength() == 0) + return Reference<deployment::XPackage>(); + + Reference<deployment::XPackage> greatest; + sal_Int32 len = seqExt.getLength(); + + for (sal_Int32 i = 0; i < len; i++) + { + if (!greatest.is()) + { + greatest = seqExt[i]; + continue; + } + Reference<deployment::XPackage> const & current = seqExt[i]; + //greatest has a value + if (! current.is()) + continue; + + if (dp_misc::compareVersions(current->getVersion(), greatest->getVersion()) == dp_misc::GREATER) + greatest = current; + } + return greatest; +} + +UpdateInfo::UpdateInfo( Reference< deployment::XPackage> const & ext): +extension(ext) +{ +} + + + +UpdateInfoMap getOnlineUpdateInfos( + Reference<uno::XComponentContext> const &xContext, + Reference<deployment::XExtensionManager> const & xExtMgr, + Reference<deployment::XUpdateInformationProvider > const & updateInformation, + std::vector<Reference<deployment::XPackage > > const * extensionList, + std::vector<std::pair< Reference<deployment::XPackage>, uno::Any> > & out_errors) +{ + OSL_ASSERT(xExtMgr.is()); + UpdateInfoMap infoMap; + if (!xExtMgr.is() || onlyBundledExtensions(xExtMgr, extensionList)) + return infoMap; + + if (!extensionList) + { + const uno::Sequence< uno::Sequence< Reference<deployment::XPackage > > > seqAllExt = xExtMgr->getAllExtensions( + Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>()); + + //fill the UpdateInfoMap. key = extension identifier, value = UpdateInfo + for (int pos = seqAllExt.getLength(); pos --; ) + { + uno::Sequence<Reference<deployment::XPackage> > const & seqExt = seqAllExt[pos]; + + Reference<deployment::XPackage> extension = getExtensionWithHighestVersion(seqExt); + OSL_ASSERT(extension.is()); + + std::pair<UpdateInfoMap::iterator, bool> insertRet = infoMap.insert( + UpdateInfoMap::value_type( + dp_misc::getIdentifier(extension), UpdateInfo(extension))); + OSL_ASSERT(insertRet.second == true); + } + } + else + { + typedef std::vector<Reference<deployment::XPackage > >::const_iterator CIT; + for (CIT i = extensionList->begin(); i != extensionList->end(); i++) + { + OSL_ASSERT(i->is()); + std::pair<UpdateInfoMap::iterator, bool> insertRet = infoMap.insert( + UpdateInfoMap::value_type( + dp_misc::getIdentifier(*i), UpdateInfo(*i))); + OSL_ASSERT(insertRet.second == true); + } + } + + //Now find the update information for the extensions which provide their own + //URLs to update information. + bool allInfosObtained = false; + getOwnUpdateInfos(xContext, updateInformation, infoMap, out_errors, allInfosObtained); + + if (!allInfosObtained) + getDefaultUpdateInfos(xContext, updateInformation, infoMap, out_errors); + return infoMap; +} +OUString getHighestVersion( + ::rtl::OUString const & userVersion, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion) +{ + int index = determineHighestVersion(userVersion, sharedVersion, bundledVersion, onlineVersion); + switch (index) + { + case 0: return userVersion; + case 1: return sharedVersion; + case 2: return bundledVersion; + case 3: return onlineVersion; + default: OSL_ASSERT(0); + } + + return OUString(); +} +} //namespace dp_misc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/dp_version.cxx b/desktop/source/deployment/misc/dp_version.cxx new file mode 100644 index 000000000000..c999d32cc252 --- /dev/null +++ b/desktop/source/deployment/misc/dp_version.cxx @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "sal/config.h" + +#include "com/sun/star/deployment/XPackage.hpp" +#include "rtl/ustring.hxx" + +#include "dp_version.hxx" + +namespace { + +namespace css = ::com::sun::star; + +::rtl::OUString getElement(::rtl::OUString const & version, ::sal_Int32 * index) +{ + while (*index < version.getLength() && version[*index] == '0') { + ++*index; + } + return version.getToken(0, '.', *index); +} + +} + +namespace dp_misc { + +::dp_misc::Order compareVersions( + ::rtl::OUString const & version1, ::rtl::OUString const & version2) +{ + for (::sal_Int32 i1 = 0, i2 = 0; i1 >= 0 || i2 >= 0;) { + ::rtl::OUString e1(getElement(version1, &i1)); + ::rtl::OUString e2(getElement(version2, &i2)); + if (e1.getLength() < e2.getLength()) { + return ::dp_misc::LESS; + } else if (e1.getLength() > e2.getLength()) { + return ::dp_misc::GREATER; + } else if (e1 < e2) { + return ::dp_misc::LESS; + } else if (e1 > e2) { + return ::dp_misc::GREATER; + } + } + return ::dp_misc::EQUAL; +} + + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/misc/makefile.mk b/desktop/source/deployment/misc/makefile.mk new file mode 100644 index 000000000000..3e4bd68cb4c0 --- /dev/null +++ b/desktop/source/deployment/misc/makefile.mk @@ -0,0 +1,95 @@ +#************************************************************************* +# +# 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 = deployment_misc +USE_DEFFILE = TRUE +ENABLE_EXCEPTIONS = TRUE +VISIBILITY_HIDDEN=TRUE + +.IF "$(GUI)"=="OS2" +TARGET = deplmisc +.ENDIF + +.INCLUDE : settings.mk + +# Reduction of exported symbols: +CDEFS += -DDESKTOP_DEPLOYMENTMISC_DLLIMPLEMENTATION + +.IF "$(SYSTEM_DB)" == "YES" +CFLAGS+=-DSYSTEM_DB -I$(DB_INCLUDES) +.ENDIF + +SRS1NAME = $(TARGET) +SRC1FILES = \ + dp_misc.src + +.IF "$(GUI)"=="OS2" +SHL1TARGET = $(TARGET) +.ELSE +SHL1TARGET = deploymentmisc$(DLLPOSTFIX) +.ENDIF +SHL1OBJS = \ + $(SLO)$/dp_misc.obj \ + $(SLO)$/dp_resource.obj \ + $(SLO)$/dp_identifier.obj \ + $(SLO)$/dp_interact.obj \ + $(SLO)$/dp_ucb.obj \ + $(SLO)$/db.obj \ + $(SLO)$/dp_version.obj \ + $(SLO)$/dp_descriptioninfoset.obj \ + $(SLO)$/dp_dependencies.obj \ + $(SLO)$/dp_platform.obj \ + $(SLO)$/dp_update.obj + +SHL1STDLIBS = \ + $(BERKELEYLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(TOOLSLIB) \ + $(UCBHELPERLIB) \ + $(UNOTOOLSLIB) \ + $(XMLSCRIPTLIB) \ + $(COMPHELPERLIB) +.IF "$(GUI)"=="OS2" +SHL1IMPLIB = ideploymentmisc$(DLLPOSTFIX) +LIB1TARGET = $(SLB)$/_deplmisc.lib +LIB1OBJFILES = $(SHL1OBJS) +DEFLIB1NAME = _deplmisc +.ELSE +SHL1IMPLIB = i$(SHL1TARGET) +.ENDIF +DEF1NAME = $(SHL1TARGET) + +SLOFILES = $(SHL1OBJS) + +.INCLUDE : ..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/registry/component/dp_compbackenddb.cxx b/desktop/source/deployment/registry/component/dp_compbackenddb.cxx new file mode 100644 index 000000000000..09f06638ecde --- /dev/null +++ b/desktop/source/deployment/registry/component/dp_compbackenddb.cxx @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "rtl/string.h" +#include "rtl/bootstrap.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "dp_misc.h" + +#include "dp_compbackenddb.hxx" + + +namespace css = ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +#define EXTENSION_REG_NS "http://openoffice.org/extensionmanager/component-registry/2010" +#define NS_PREFIX "comp" +#define ROOT_ELEMENT_NAME "component-backend-db" +#define KEY_ELEMENT_NAME "component" + +namespace dp_registry { +namespace backend { +namespace component { + +ComponentBackendDb::ComponentBackendDb( + Reference<XComponentContext> const & xContext, + ::rtl::OUString const & url):BackendDb(xContext, url) +{ + +} + +OUString ComponentBackendDb::getDbNSName() +{ + return OUSTR(EXTENSION_REG_NS); +} + +OUString ComponentBackendDb::getNSPrefix() +{ + return OUSTR(NS_PREFIX); +} + +OUString ComponentBackendDb::getRootElementName() +{ + return OUSTR(ROOT_ELEMENT_NAME); +} + +OUString ComponentBackendDb::getKeyElementName() +{ + return OUSTR(KEY_ELEMENT_NAME); +} + +void ComponentBackendDb::addEntry(::rtl::OUString const & url, Data const & data) +{ + try{ + Reference<css::xml::dom::XNode> componentNode = writeKeyElement(url); + writeSimpleElement(OUSTR("java-type-library"), + OUString::valueOf((sal_Bool) data.javaTypeLibrary), + componentNode); + + writeSimpleList( + data.implementationNames, + OUSTR("implementation-names"), + OUSTR("name"), + componentNode); + + writeVectorOfPair( + data.singletons, + OUSTR("singletons"), + OUSTR("item"), + OUSTR("key"), + OUSTR("value"), + componentNode); + + save(); + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +ComponentBackendDb::Data ComponentBackendDb::getEntry(::rtl::OUString const & url) +{ + try + { + ComponentBackendDb::Data retData; + Reference<css::xml::dom::XNode> aNode = getKeyElement(url); + if (aNode.is()) + { + bool bJava = readSimpleElement(OUSTR("java-type-library"), aNode) + .equals(OUSTR("true")) ? true : false; + retData.javaTypeLibrary = bJava; + + retData.implementationNames = + readList( + aNode, + OUSTR("implementation-names"), + OUSTR("name")); + + retData.singletons = + readVectorOfPair( + aNode, + OUSTR("singletons"), + OUSTR("item"), + OUSTR("key"), + OUSTR("value")); + } + return retData; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + + +} // namespace bundle +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/component/dp_compbackenddb.hxx b/desktop/source/deployment/registry/component/dp_compbackenddb.hxx new file mode 100644 index 000000000000..8af1ad639622 --- /dev/null +++ b/desktop/source/deployment/registry/component/dp_compbackenddb.hxx @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_COMPBACKENDDB_HXX +#define INCLUDED_DP_COMPBACKENDDB_HXX + +#include "rtl/ustring.hxx" +#include "rtl/string.hxx" +#include <vector> +#include <list> +#include "dp_backenddb.hxx" + +namespace css = ::com::sun::star; + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } + namespace xml { namespace dom { + class XDocument; + class XNode; + }} + namespace xml { namespace xpath { + class XXPathAPI; + }} +}}} + +namespace dp_registry { +namespace backend { +namespace component { + +/* The XML file stores the extensions which are currently registered. + They will be removed when they are revoked. + The format looks like this: + +<?xml version="1.0"?> +<component-backend-db xmlns="http://openoffice.org/extensionmanager/component-registry/2010"> + <component url="vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/uno_packages/5CD5.tmp_/leaves1.oxt/extensionoptions.jar"> + <name>FileName</name> + <java-type-library>true</java-type-library> + <implementation-names> + <name>com.sun.star.comp.extensionoptions.OptionsEventHandler$_OptionsEventHandler</name> + ... + </implementation-names> + <singletons> + <item> + <key>com.sun.star.java.theJavaVirtualMachine</key> + <value>com.sun.star.java.JavaVirtualMachine</value> + </item> + ... + </singletons> + </component> + + <component ...> + ... +</component-backend-db> + */ +class ComponentBackendDb: public dp_registry::backend::BackendDb +{ +protected: + virtual ::rtl::OUString getDbNSName(); + virtual ::rtl::OUString getNSPrefix(); + virtual ::rtl::OUString getRootElementName(); + virtual ::rtl::OUString getKeyElementName(); + +public: + struct Data + { + Data(): javaTypeLibrary(false) {}; + + ::std::list< ::rtl::OUString> implementationNames; + /* every singleton has a key and a value + */ + ::std::vector< ::std::pair< ::rtl::OUString, ::rtl::OUString> >singletons; + bool javaTypeLibrary; + }; + +public: + + ComponentBackendDb( css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); + + void addEntry(::rtl::OUString const & url, Data const & data); + + Data getEntry(::rtl::OUString const & url); + + +}; + + + +} +} +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/component/dp_component.cxx b/desktop/source/deployment/registry/component/dp_component.cxx new file mode 100644 index 000000000000..b1e22d35c0a0 --- /dev/null +++ b/desktop/source/deployment/registry/component/dp_component.cxx @@ -0,0 +1,1588 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_component.hrc" +#include "dp_backend.h" +#include "dp_platform.hxx" +#include "dp_ucb.h" +#include "rtl/string.hxx" +#include "rtl/strbuf.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/uri.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "ucbhelper/content.hxx" +#include "comphelper/anytostring.hxx" +#include "comphelper/servicedecl.hxx" +#include "comphelper/sequence.hxx" +#include "xmlscript/xml_helper.hxx" +#include "svl/inettype.hxx" +#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" +#include "com/sun/star/container/XNameContainer.hpp" +#include "com/sun/star/container/XHierarchicalNameAccess.hpp" +#include "com/sun/star/container/XSet.hpp" +#include "com/sun/star/registry/XSimpleRegistry.hpp" +#include "com/sun/star/registry/XImplementationRegistration.hpp" +#include "com/sun/star/loader/XImplementationLoader.hpp" +#include "com/sun/star/io/XInputStream.hpp" +#include "com/sun/star/ucb/NameClash.hpp" +#include "com/sun/star/util/XMacroExpander.hpp" +#include <list> +#include <hash_map> +#include <vector> +#include <memory> +#include <algorithm> +#include "dp_compbackenddb.hxx" + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; + +namespace dp_registry { +namespace backend { +namespace component { +namespace { + +typedef ::std::list<OUString> t_stringlist; +typedef ::std::vector< ::std::pair<OUString, OUString> > t_stringpairvec; + +#define IMPLEMENTATION_NAME "com.sun.star.comp.deployment.component.PackageRegistryBackend" + +/** return a vector of bootstrap variables which have been provided + as command arguments. +*/ +::std::vector<OUString> getCmdBootstrapVariables() +{ + ::std::vector<OUString> ret; + sal_uInt32 count = osl_getCommandArgCount(); + for (sal_uInt32 i = 0; i < count; i++) + { + OUString arg; + osl_getCommandArg(i, &arg.pData); + if (arg.matchAsciiL("-env:", 5)) + ret.push_back(arg); + } + return ret; +} + +bool jarManifestHeaderPresent( + OUString const & url, OUString const & name, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.zip://") ); + buf.append( + ::rtl::Uri::encode( + url, rtl_UriCharClassRegName, rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("/META-INF/MANIFEST.MF") ); + ::ucbhelper::Content manifestContent; + OUString line; + return + create_ucb_content( + &manifestContent, buf.makeStringAndClear(), xCmdEnv, + false /* no throw */ ) + && readLine( &line, name, manifestContent, RTL_TEXTENCODING_ASCII_US ); +} + +//============================================================================== +class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend +{ + class ComponentPackageImpl : public ::dp_registry::backend::Package + { + BackendImpl * getMyBackend() const; + + const OUString m_loader; + ComponentBackendDb::Data m_registeredComponentsDb; + + enum reg { + REG_UNINIT, REG_VOID, REG_REGISTERED, REG_NOT_REGISTERED, REG_MAYBE_REGISTERED + } m_registered; + + Reference<loader::XImplementationLoader> getComponentInfo( + t_stringlist * pImplNames, t_stringpairvec * pSingletons, + Reference<XComponentContext> const & xContext ); + + virtual void SAL_CALL disposing(); + + // Package + virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + + const Reference<registry::XSimpleRegistry> getRDB() const; + + //Provides the read-only registry (e.g. not the one based on the duplicated + //rdb files + const Reference<registry::XSimpleRegistry> getRDB_RO() const; + + public: + ComponentPackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + OUString const & loader, bool bRemoved, + OUString const & identifier); + }; + friend class ComponentPackageImpl; + + class TypelibraryPackageImpl : public ::dp_registry::backend::Package + { + BackendImpl * getMyBackend() const; + + const bool m_jarFile; + Reference<container::XHierarchicalNameAccess> m_xTDprov; + + virtual void SAL_CALL disposing(); + + // Package + virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + + public: + TypelibraryPackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool jarFile, bool bRemoved, + OUString const & identifier); + }; + friend class TypelibraryPackageImpl; + + t_stringlist m_jar_typelibs; + t_stringlist m_rdb_typelibs; + t_stringlist & getTypelibs( bool jar ) { + return jar ? m_jar_typelibs : m_rdb_typelibs; + } + + bool m_unorc_inited; + bool m_unorc_modified; + bool bSwitchedRdbFiles; + + typedef ::std::hash_map< OUString, Reference<XInterface>, + ::rtl::OUStringHash > t_string2object; + t_string2object m_backendObjects; + + // PackageRegistryBackend + virtual Reference<deployment::XPackage> bindPackage_( + OUString const & url, OUString const & mediaType, + sal_Bool bRemoved, OUString const & identifier, + Reference<XCommandEnvironment> const & xCmdEnv ); + + virtual void SAL_CALL disposing(); + + const Reference<deployment::XPackageTypeInfo> m_xDynComponentTypeInfo; + const Reference<deployment::XPackageTypeInfo> m_xJavaComponentTypeInfo; + const Reference<deployment::XPackageTypeInfo> m_xPythonComponentTypeInfo; + const Reference<deployment::XPackageTypeInfo> m_xRDBTypelibTypeInfo; + const Reference<deployment::XPackageTypeInfo> m_xJavaTypelibTypeInfo; + Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos; + + OUString m_commonRDB; + OUString m_nativeRDB; + + //URLs of the read-only rdbs (e.g. not the ones of the duplicated files) + OUString m_commonRDB_RO; + OUString m_nativeRDB_RO; + + std::auto_ptr<ComponentBackendDb> m_backendDb; + + void addDataToDb(OUString const & url, ComponentBackendDb::Data const & data); + void deleteDataFromDb(OUString const & url); + ComponentBackendDb::Data readDataFromDb(OUString const & url); + + + //These rdbs are for writing new service entries. The rdb files are copies + //which are created when services are added or removed. + Reference<registry::XSimpleRegistry> m_xCommonRDB; + Reference<registry::XSimpleRegistry> m_xNativeRDB; + + //These rdbs are created on the read-only rdbs which are already used + //by UNO since the startup of the current session. + Reference<registry::XSimpleRegistry> m_xCommonRDB_RO; + Reference<registry::XSimpleRegistry> m_xNativeRDB_RO; + + + void unorc_verify_init( Reference<XCommandEnvironment> const & xCmdEnv ); + void unorc_flush( Reference<XCommandEnvironment> const & xCmdEnv ); + + Reference<XInterface> getObject( OUString const & id ); + Reference<XInterface> insertObject( + OUString const & id, Reference<XInterface> const & xObject ); + void releaseObject( OUString const & id ); + + bool addToUnoRc( bool jarFile, OUString const & url, + Reference<XCommandEnvironment> const & xCmdEnv ); + bool removeFromUnoRc( bool jarFile, OUString const & url, + Reference<XCommandEnvironment> const & xCmdEnv ); + bool hasInUnoRc( bool jarFile, OUString const & url ); + + + +public: + BackendImpl( Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ); + + // XPackageRegistry + virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() throw (RuntimeException); + + using PackageRegistryBackend::disposing; + + //Will be called from ComponentPackageImpl + void initServiceRdbFiles(); + + //Creates the READ ONLY registries (m_xCommonRDB_RO,m_xNativeRDB_RO) + void initServiceRdbFiles_RO(); +}; + +//______________________________________________________________________________ + +BackendImpl::ComponentPackageImpl::ComponentPackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + OUString const & loader, bool bRemoved, + OUString const & identifier) + : Package( myBackend, url, name, name /* display-name */, + xPackageType, bRemoved, identifier), + m_loader( loader ), + m_registered( REG_UNINIT ) +{ + if (bRemoved) + { + m_registeredComponentsDb = getMyBackend()->readDataFromDb(url); + } +} + + +const Reference<registry::XSimpleRegistry> +BackendImpl::ComponentPackageImpl::getRDB() const +{ + BackendImpl * that = getMyBackend(); + + //Late "initialization" of the services rdb files + //This is to prevent problems when running several + //instances of OOo with root rights in parallel. This + //would otherwise cause problems when copying the rdbs. + //See http://qa.openoffice.org/issues/show_bug.cgi?id=99257 + { + const ::osl::MutexGuard guard( getMutex() ); + if (!that->bSwitchedRdbFiles) + { + that->bSwitchedRdbFiles = true; + that->initServiceRdbFiles(); + } + } + if (m_loader.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.loader.SharedLibrary") )) + return that->m_xNativeRDB; + else + return that->m_xCommonRDB; +} + +//Returns the read only RDB. +const Reference<registry::XSimpleRegistry> +BackendImpl::ComponentPackageImpl::getRDB_RO() const +{ + BackendImpl * that = getMyBackend(); + + if (m_loader.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.loader.SharedLibrary") )) + return that->m_xNativeRDB_RO; + else + return that->m_xCommonRDB_RO; +} + +BackendImpl * BackendImpl::ComponentPackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); + if (NULL == pBackend) + { + //Throws a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<ComponentPackageImpl *>(this))); + } + return pBackend; +} + + +//______________________________________________________________________________ +void BackendImpl::ComponentPackageImpl::disposing() +{ +// m_xRemoteContext.clear(); + Package::disposing(); +} + +//______________________________________________________________________________ +void BackendImpl::TypelibraryPackageImpl::disposing() +{ + m_xTDprov.clear(); + Package::disposing(); +} + +//______________________________________________________________________________ +void BackendImpl::disposing() +{ + try { + m_backendObjects = t_string2object(); + if (m_xNativeRDB.is()) { + m_xNativeRDB->close(); + m_xNativeRDB.clear(); + } + if (m_xCommonRDB.is()) { + m_xCommonRDB->close(); + m_xCommonRDB.clear(); + } + unorc_flush( Reference<XCommandEnvironment>() ); + + PackageRegistryBackend::disposing(); + } + catch (RuntimeException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + throw lang::WrappedTargetRuntimeException( + OUSTR("caught unexpected exception while disposing..."), + static_cast<OWeakObject *>(this), exc ); + } +} + + +void BackendImpl::initServiceRdbFiles() +{ + const Reference<XCommandEnvironment> xCmdEnv; + + ::ucbhelper::Content cacheDir( getCachePath(), xCmdEnv ); + ::ucbhelper::Content oldRDB; + // switch common rdb: + if (m_commonRDB_RO.getLength() > 0) + { + create_ucb_content( + &oldRDB, makeURL( getCachePath(), m_commonRDB_RO), + xCmdEnv, false /* no throw */ ); + } + m_commonRDB = m_commonRDB_RO.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("common.rdb") ) + ? OUSTR("common_.rdb") : OUSTR("common.rdb"); + if (oldRDB.get().is()) + { + if (! cacheDir.transferContent( + oldRDB, ::ucbhelper::InsertOperation_COPY, + m_commonRDB, NameClash::OVERWRITE )) + { + + throw RuntimeException( + OUSTR("UCB transferContent() failed!"), 0 ); + } + oldRDB = ::ucbhelper::Content(); + } + // switch native rdb: + if (m_nativeRDB_RO.getLength() > 0) + { + create_ucb_content( + &oldRDB, makeURL(getCachePath(), m_nativeRDB_RO), + xCmdEnv, false /* no throw */ ); + } + const OUString plt_rdb( getPlatformString() + OUSTR(".rdb") ); + const OUString plt_rdb_( getPlatformString() + OUSTR("_.rdb") ); + m_nativeRDB = m_nativeRDB_RO.equals( plt_rdb ) ? plt_rdb_ : plt_rdb; + if (oldRDB.get().is()) + { + if (! cacheDir.transferContent( + oldRDB, ::ucbhelper::InsertOperation_COPY, + m_nativeRDB, NameClash::OVERWRITE )) + throw RuntimeException( + OUSTR("UCB transferContent() failed!"), 0 ); + } + + // UNO is bootstrapped, flush for next process start: + m_unorc_modified = true; + unorc_flush( Reference<XCommandEnvironment>() ); + + + // common rdb for java, native rdb for shared lib components + if (m_commonRDB.getLength() > 0) { + m_xCommonRDB.set( + m_xComponentContext->getServiceManager() + ->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), + m_xComponentContext ), UNO_QUERY_THROW ); + m_xCommonRDB->open( + makeURL( expandUnoRcUrl(getCachePath()), m_commonRDB ), +// m_readOnly, !m_readOnly ); + false, true); + } + if (m_nativeRDB.getLength() > 0) { + m_xNativeRDB.set( + m_xComponentContext->getServiceManager() + ->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), + m_xComponentContext ), UNO_QUERY_THROW ); + m_xNativeRDB->open( + makeURL( expandUnoRcUrl(getCachePath()), m_nativeRDB ), +// m_readOnly, !m_readOnly ); + false, true); + } +} + +void BackendImpl::initServiceRdbFiles_RO() +{ + const Reference<XCommandEnvironment> xCmdEnv; + + // common rdb for java, native rdb for shared lib components + if (m_commonRDB_RO.getLength() > 0) + { + m_xCommonRDB_RO.set( + m_xComponentContext->getServiceManager() + ->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), + m_xComponentContext), UNO_QUERY_THROW); + m_xCommonRDB_RO->open( + makeURL(expandUnoRcUrl(getCachePath()), m_commonRDB_RO), + sal_True, //read-only + sal_True); // create data source if necessary + } + if (m_nativeRDB_RO.getLength() > 0) + { + m_xNativeRDB_RO.set( + m_xComponentContext->getServiceManager() + ->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), + m_xComponentContext), UNO_QUERY_THROW); + m_xNativeRDB_RO->open( + makeURL(expandUnoRcUrl(getCachePath()), m_nativeRDB_RO), + sal_True, //read-only + sal_True); // create data source if necessary + } +} + +//______________________________________________________________________________ +BackendImpl::BackendImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ) + : PackageRegistryBackend( args, xComponentContext ), + m_unorc_inited( false ), + m_unorc_modified( false ), + bSwitchedRdbFiles(false), + m_xDynComponentTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.uno-component;" + "type=native;platform=") + + getPlatformString(), + OUSTR("*" SAL_DLLEXTENSION), + getResourceString(RID_STR_DYN_COMPONENT), + RID_IMG_COMPONENT, + RID_IMG_COMPONENT_HC ) ), + m_xJavaComponentTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.uno-component;" + "type=Java"), + OUSTR("*.jar"), + getResourceString(RID_STR_JAVA_COMPONENT), + RID_IMG_JAVA_COMPONENT, + RID_IMG_JAVA_COMPONENT_HC ) ), + m_xPythonComponentTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.uno-component;" + "type=Python"), + OUSTR("*.py"), + getResourceString( + RID_STR_PYTHON_COMPONENT), + RID_IMG_COMPONENT, + RID_IMG_COMPONENT_HC ) ), + m_xRDBTypelibTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.uno-typelibrary;" + "type=RDB"), + OUSTR("*.rdb"), + getResourceString(RID_STR_RDB_TYPELIB), + RID_IMG_TYPELIB, RID_IMG_TYPELIB_HC ) ), + m_xJavaTypelibTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.uno-typelibrary;" + "type=Java"), + OUSTR("*.jar"), + getResourceString(RID_STR_JAVA_TYPELIB), + RID_IMG_JAVA_TYPELIB, + RID_IMG_JAVA_TYPELIB_HC ) ), + m_typeInfos( 5 ) +{ + m_typeInfos[ 0 ] = m_xDynComponentTypeInfo; + m_typeInfos[ 1 ] = m_xJavaComponentTypeInfo; + m_typeInfos[ 2 ] = m_xPythonComponentTypeInfo; + m_typeInfos[ 3 ] = m_xRDBTypelibTypeInfo; + m_typeInfos[ 4 ] = m_xJavaTypelibTypeInfo; + + const Reference<XCommandEnvironment> xCmdEnv; + + if (transientMode()) + { + // in-mem rdbs: + // common rdb for java, native rdb for shared lib components + m_xCommonRDB.set( + xComponentContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), + xComponentContext ), UNO_QUERY_THROW ); + m_xCommonRDB->open( OUString() /* in-mem */, + false /* ! read-only */, true /* create */ ); + m_xNativeRDB.set( + xComponentContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), + xComponentContext ), UNO_QUERY_THROW ); + m_xNativeRDB->open( OUString() /* in-mem */, + false /* ! read-only */, true /* create */ ); + } + else + { + //do this before initServiceRdbFiles_RO, because it determines + //m_commonRDB and m_nativeRDB + unorc_verify_init( xCmdEnv ); + + initServiceRdbFiles_RO(); + + OUString dbFile = makeURL(getCachePath(), OUSTR("backenddb.xml")); + m_backendDb.reset( + new ComponentBackendDb(getComponentContext(), dbFile)); + } +} + +void BackendImpl::addDataToDb( + OUString const & url, ComponentBackendDb::Data const & data) +{ + if (m_backendDb.get()) + m_backendDb->addEntry(url, data); +} + +void BackendImpl::deleteDataFromDb(OUString const & url) +{ + if (m_backendDb.get()) + m_backendDb->removeEntry(url); +} + +ComponentBackendDb::Data BackendImpl::readDataFromDb(OUString const & url) +{ + ComponentBackendDb::Data data; + if (m_backendDb.get()) + data = m_backendDb->getEntry(url); + return data; +} + +// XPackageRegistry +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackageTypeInfo> > +BackendImpl::getSupportedPackageTypes() throw (RuntimeException) +{ + return m_typeInfos; +} + +// PackageRegistryBackend +//______________________________________________________________________________ +Reference<deployment::XPackage> BackendImpl::bindPackage_( + OUString const & url, OUString const & mediaType_, + sal_Bool bRemoved, OUString const & identifier, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + OUString mediaType(mediaType_); + if (mediaType.getLength() == 0 || + mediaType.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/vnd.sun.star.uno-component") ) || + mediaType.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/vnd.sun.star.uno-typelibrary") )) + { + // detect exact media-type: + ::ucbhelper::Content ucbContent; + if (create_ucb_content( &ucbContent, url, xCmdEnv )) { + const OUString title( ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>() ); + if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(SAL_DLLEXTENSION) )) + { + mediaType = OUSTR("application/vnd.sun.star.uno-component;" + "type=native;platform=") + + getPlatformString(); + } + else if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".jar") )) + { + if (jarManifestHeaderPresent( + url, OUSTR("RegistrationClassName"), xCmdEnv )) + mediaType = OUSTR( + "application/vnd.sun.star.uno-component;type=Java"); + if (mediaType.getLength() == 0) + mediaType = OUSTR( + "application/vnd.sun.star.uno-typelibrary;type=Java"); + } + else if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".py") )) + mediaType = + OUSTR("application/vnd.sun.star.uno-component;type=Python"); + else if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".rdb") )) + mediaType = + OUSTR("application/vnd.sun.star.uno-typelibrary;type=RDB"); + } + if (mediaType.getLength() == 0) + throw lang::IllegalArgumentException( + StrCannotDetectMediaType::get() + url, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); + } + + String type, subType; + INetContentTypeParameterList params; + if (INetContentTypes::parse( mediaType, type, subType, ¶ms )) + { + if (type.EqualsIgnoreCaseAscii("application")) + { + OUString name; + if (!bRemoved) + { + ::ucbhelper::Content ucbContent( url, xCmdEnv ); + name = ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>(); + } + + if (subType.EqualsIgnoreCaseAscii("vnd.sun.star.uno-component")) + { + // xxx todo: probe and evaluate component xml description + + INetContentTypeParameter const * param = params.find( + ByteString("platform") ); + if (param == 0 || platform_fits( param->m_sValue )) { + param = params.find( ByteString("type") ); + if (param != 0) + { + String const & value = param->m_sValue; + if (value.EqualsIgnoreCaseAscii("native")) { + return new BackendImpl::ComponentPackageImpl( + this, url, name, m_xDynComponentTypeInfo, + OUSTR("com.sun.star.loader.SharedLibrary"), + bRemoved, identifier); + } + if (value.EqualsIgnoreCaseAscii("Java")) { + return new BackendImpl::ComponentPackageImpl( + this, url, name, m_xJavaComponentTypeInfo, + OUSTR("com.sun.star.loader.Java2"), + bRemoved, identifier); + } + if (value.EqualsIgnoreCaseAscii("Python")) { + return new BackendImpl::ComponentPackageImpl( + this, url, name, m_xPythonComponentTypeInfo, + OUSTR("com.sun.star.loader.Python"), + bRemoved, identifier); + } + } + } + } + else if (subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.uno-typelibrary")) + { + INetContentTypeParameter const * param = params.find( + ByteString("type") ); + if (param != 0) { + String const & value = param->m_sValue; + if (value.EqualsIgnoreCaseAscii("RDB")) + { + return new BackendImpl::TypelibraryPackageImpl( + this, url, name, m_xRDBTypelibTypeInfo, + false /* rdb */, bRemoved, identifier); + } + if (value.EqualsIgnoreCaseAscii("Java")) { + return new BackendImpl::TypelibraryPackageImpl( + this, url, name, m_xJavaTypelibTypeInfo, + true /* jar */, bRemoved, identifier); + } + } + } + } + } + throw lang::IllegalArgumentException( + StrUnsupportedMediaType::get() + mediaType, + static_cast<OWeakObject *>(this), + static_cast<sal_Int16>(-1) ); +} + +//############################################################################## + +//______________________________________________________________________________ +void BackendImpl::unorc_verify_init( + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + if (transientMode()) + return; + const ::osl::MutexGuard guard( getMutex() ); + if (! m_unorc_inited) + { + // common rc: + ::ucbhelper::Content ucb_content; + if (create_ucb_content( + &ucb_content, + makeURL( getCachePath(), OUSTR("unorc") ), + xCmdEnv, false /* no throw */ )) + { + OUString line; + if (readLine( &line, OUSTR("UNO_JAVA_CLASSPATH="), ucb_content, + RTL_TEXTENCODING_UTF8 )) + { + sal_Int32 index = sizeof ("UNO_JAVA_CLASSPATH=") - 1; + do { + OUString token( line.getToken( 0, ' ', index ).trim() ); + if (token.getLength() > 0) + { + if (create_ucb_content( + 0, expandUnoRcTerm(token), xCmdEnv, + false /* no throw */ )) + { + //The jar file may not exist anymore if a shared or bundled + //extension was removed, but it can still be in the unorc + //After running XExtensionManager::synchronize, the unorc is + //cleaned up + m_jar_typelibs.push_back( token ); + } + } + } + while (index >= 0); + } + if (readLine( &line, OUSTR("UNO_TYPES="), ucb_content, + RTL_TEXTENCODING_UTF8 )) { + sal_Int32 index = sizeof ("UNO_TYPES=") - 1; + do { + OUString token( line.getToken( 0, ' ', index ).trim() ); + if (token.getLength() > 0) + { + if (token[ 0 ] == '?') + token = token.copy( 1 ); + if (create_ucb_content( + 0, expandUnoRcTerm(token), xCmdEnv, + false /* no throw */ )) + { + //The RDB file may not exist anymore if a shared or bundled + //extension was removed, but it can still be in the unorc. + //After running XExtensionManager::synchronize, the unorc is + //cleaned up + m_rdb_typelibs.push_back( token ); + } + } + } + while (index >= 0); + } + if (readLine( &line, OUSTR("UNO_SERVICES="), ucb_content, + RTL_TEXTENCODING_UTF8 )) { + sal_Int32 start = sizeof ("UNO_SERVICES=?$ORIGIN/") - 1; + sal_Int32 sep = line.indexOf( ' ', start ); + OSL_ASSERT( sep > 0 ); + m_commonRDB_RO = line.copy( start, sep - start ); + } + + // native rc: + if (create_ucb_content( + &ucb_content, + makeURL( getCachePath(), getPlatformString() + OUSTR("rc")), + xCmdEnv, false /* no throw */ )) { + if (readLine( &line, OUSTR("UNO_SERVICES="), ucb_content, + RTL_TEXTENCODING_UTF8 )) { + m_nativeRDB_RO = line.copy( + sizeof ("UNO_SERVICES=?$ORIGIN/") - 1 ); + } + } + } + m_unorc_modified = false; + m_unorc_inited = true; + } +} + +//______________________________________________________________________________ +void BackendImpl::unorc_flush( Reference<XCommandEnvironment> const & xCmdEnv ) +{ + if (transientMode()) + return; + if (!m_unorc_inited || !m_unorc_modified) + return; + + ::rtl::OStringBuffer buf; + + buf.append(RTL_CONSTASCII_STRINGPARAM("ORIGIN=")); + OUString sOrigin = dp_misc::makeRcTerm(m_cachePath); + ::rtl::OString osOrigin = ::rtl::OUStringToOString(sOrigin, RTL_TEXTENCODING_UTF8); + buf.append(osOrigin); + buf.append(LF); + + if (! m_jar_typelibs.empty()) + { + t_stringlist::const_iterator iPos( m_jar_typelibs.begin() ); + t_stringlist::const_iterator const iEnd( m_jar_typelibs.end() ); + buf.append( RTL_CONSTASCII_STRINGPARAM("UNO_JAVA_CLASSPATH=") ); + while (iPos != iEnd) { + // encoded ASCII file-urls: + const ::rtl::OString item( + ::rtl::OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( item ); + ++iPos; + if (iPos != iEnd) + buf.append( ' ' ); + } + buf.append(LF); + } + if (! m_rdb_typelibs.empty()) + { + t_stringlist::const_iterator iPos( m_rdb_typelibs.begin() ); + t_stringlist::const_iterator const iEnd( m_rdb_typelibs.end() ); + buf.append( RTL_CONSTASCII_STRINGPARAM("UNO_TYPES=") ); + while (iPos != iEnd) { + buf.append( '?' ); + // encoded ASCII file-urls: + const ::rtl::OString item( + ::rtl::OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( item ); + ++iPos; + if (iPos != iEnd) + buf.append( ' ' ); + } + buf.append(LF); + } + + // If we duplicated the common or native rdb then we must use those urls + //otherwise we use those of the original files. That is, m_commonRDB_RO and + //m_nativeRDB_RO; + OUString sCommonRDB(m_commonRDB.getLength() > 0 ? m_commonRDB : m_commonRDB_RO); + OUString sNativeRDB(m_nativeRDB.getLength() > 0 ? m_nativeRDB : m_nativeRDB_RO); + + if (sCommonRDB.getLength() > 0 || sNativeRDB.getLength() > 0) + { + buf.append( RTL_CONSTASCII_STRINGPARAM("UNO_SERVICES=?$ORIGIN/") ); + buf.append( ::rtl::OUStringToOString( + sCommonRDB, RTL_TEXTENCODING_ASCII_US ) ); + if (sNativeRDB.getLength() > 0) + { + buf.append( RTL_CONSTASCII_STRINGPARAM( + " ${$ORIGIN/${_OS}_${_ARCH}rc:UNO_SERVICES}") ); + buf.append(LF); + + // write native rc: + ::rtl::OStringBuffer buf2; + buf2.append(RTL_CONSTASCII_STRINGPARAM("ORIGIN=")); + buf2.append(osOrigin); + buf2.append(LF); + buf2.append( RTL_CONSTASCII_STRINGPARAM("UNO_SERVICES=?$ORIGIN/") ); + buf2.append( ::rtl::OUStringToOString( + sNativeRDB, RTL_TEXTENCODING_ASCII_US ) ); + buf2.append(LF); + + const Reference<io::XInputStream> xData( + ::xmlscript::createInputStream( + ::rtl::ByteSequence( + reinterpret_cast<sal_Int8 const *>(buf2.getStr()), + buf2.getLength() ) ) ); + ::ucbhelper::Content ucb_content( + makeURL( getCachePath(), getPlatformString() + OUSTR("rc") ), + xCmdEnv ); + ucb_content.writeStream( xData, true /* replace existing */ ); + } + } + + // write unorc: + const Reference<io::XInputStream> xData( + ::xmlscript::createInputStream( + ::rtl::ByteSequence( + reinterpret_cast<sal_Int8 const *>(buf.getStr()), + buf.getLength() ) ) ); + ::ucbhelper::Content ucb_content( + makeURL( getCachePath(), OUSTR("unorc") ), xCmdEnv ); + ucb_content.writeStream( xData, true /* replace existing */ ); + + m_unorc_modified = false; +} + +//______________________________________________________________________________ +bool BackendImpl::addToUnoRc( bool jarFile, OUString const & url_, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + const OUString rcterm( dp_misc::makeRcTerm(url_) ); + const ::osl::MutexGuard guard( getMutex() ); + unorc_verify_init( xCmdEnv ); + t_stringlist & rSet = getTypelibs(jarFile); + if (::std::find( rSet.begin(), rSet.end(), rcterm ) == rSet.end()) { + rSet.push_front( rcterm ); // prepend to list, thus overriding + // write immediately: + m_unorc_modified = true; + unorc_flush( xCmdEnv ); + return true; + } + else + return false; +} + +//______________________________________________________________________________ +bool BackendImpl::removeFromUnoRc( + bool jarFile, OUString const & url_, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + const OUString rcterm( dp_misc::makeRcTerm(url_) ); + const ::osl::MutexGuard guard( getMutex() ); + unorc_verify_init( xCmdEnv ); + getTypelibs(jarFile).remove( rcterm ); + // write immediately: + m_unorc_modified = true; + unorc_flush( xCmdEnv ); + return true; +} + +//______________________________________________________________________________ +bool BackendImpl::hasInUnoRc( + bool jarFile, OUString const & url_ ) +{ + const OUString rcterm( dp_misc::makeRcTerm(url_) ); + const ::osl::MutexGuard guard( getMutex() ); + t_stringlist const & rSet = getTypelibs(jarFile); + return ::std::find( rSet.begin(), rSet.end(), rcterm ) != rSet.end(); +} + +//______________________________________________________________________________ +void BackendImpl::releaseObject( OUString const & id ) +{ + const ::osl::MutexGuard guard( getMutex() ); + if ( m_backendObjects.erase( id ) != 1 ) + { + OSL_ASSERT( false ); + } +} + +//______________________________________________________________________________ +Reference<XInterface> BackendImpl::getObject( OUString const & id ) +{ + const ::osl::MutexGuard guard( getMutex() ); + const t_string2object::const_iterator iFind( m_backendObjects.find( id ) ); + if (iFind == m_backendObjects.end()) + return Reference<XInterface>(); + else + return iFind->second; +} + +//______________________________________________________________________________ +Reference<XInterface> BackendImpl::insertObject( + OUString const & id, Reference<XInterface> const & xObject ) +{ + const ::osl::MutexGuard guard( getMutex() ); + const ::std::pair<t_string2object::iterator, bool> insertion( + m_backendObjects.insert( t_string2object::value_type( + id, xObject ) ) ); + return insertion.first->second; +} + +//------------------------------------------------------------------------------ +Reference<XComponentContext> raise_uno_process( + Reference<XComponentContext> const & xContext, + ::rtl::Reference<AbortChannel> const & abortChannel ) +{ + OSL_ASSERT( xContext.is() ); + + ::rtl::OUString url( + Reference<util::XMacroExpander>( + xContext->getValueByName( + OUSTR("/singletons/com.sun.star.util.theMacroExpander") ), + UNO_QUERY_THROW )-> + expandMacros( OUSTR("$URE_BIN_DIR/uno") ) ); + + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("uno:pipe,name=") ); + OUString pipeId( generateRandomPipeId() ); + buf.append( pipeId ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM(";urp;uno.ComponentContext") ); + const OUString connectStr( buf.makeStringAndClear() ); + + // raise core UNO process to register/run a component, + // javavm service uses unorc next to executable to retrieve deployed + // jar typelibs + + ::std::vector<OUString> args; +#if OSL_DEBUG_LEVEL <= 1 + args.push_back( OUSTR("--quiet") ); +#endif + args.push_back( OUSTR("--singleaccept") ); + args.push_back( OUSTR("-u") ); + args.push_back( connectStr ); + // don't inherit from unorc: + args.push_back( OUSTR("-env:INIFILENAME=") ); + + //now add the bootstrap variables which were supplied on the command line + ::std::vector<OUString> bootvars = getCmdBootstrapVariables(); + args.insert(args.end(), bootvars.begin(), bootvars.end()); + + oslProcess hProcess = raiseProcess( + url, comphelper::containerToSequence(args) ); + try { + return Reference<XComponentContext>( + resolveUnoURL( connectStr, xContext, abortChannel.get() ), + UNO_QUERY_THROW ); + } + catch (...) { + // try to terminate process: + if ( osl_terminateProcess( hProcess ) != osl_Process_E_None ) + { + OSL_ASSERT( false ); + } + throw; + } +} + +//------------------------------------------------------------------------------ +Reference<loader::XImplementationLoader> +BackendImpl::ComponentPackageImpl::getComponentInfo( + t_stringlist * pImplNames, t_stringpairvec * pSingletons, + Reference<XComponentContext> const & xContext ) +{ + const Reference<loader::XImplementationLoader> xLoader( + xContext->getServiceManager()->createInstanceWithContext( + m_loader, xContext ), UNO_QUERY ); + if (! xLoader.is()) + return Reference<loader::XImplementationLoader>(); + + // HACK: highly dependent on stoc/source/servicemanager + // and stoc/source/implreg implementation which rely on the same + // services.rdb format! + + const Reference<registry::XSimpleRegistry> xMemReg( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), xContext ), + UNO_QUERY_THROW ); + xMemReg->open( OUString() /* in mem */, false, true ); + xLoader->writeRegistryInfo( xMemReg->getRootKey(), OUString(), getURL() ); + + const Sequence< Reference<registry::XRegistryKey> > keys( + xMemReg->getRootKey()->openKeys() ); + for ( sal_Int32 pos = keys.getLength(); pos--; ) + { + Reference<registry::XRegistryKey> const & xImplKey = keys[ pos ]; + const OUString implName( + xImplKey->getKeyName().copy( 1 /*leading slash*/ ) ); + + // check for singletons: + const Reference<registry::XRegistryKey> xSingletonKey( + xImplKey->openKey( OUSTR("UNO/SINGLETONS") ) ); + if (xSingletonKey.is() && xSingletonKey->isValid()) + { + const Sequence< Reference<registry::XRegistryKey> > singletonKeys( + xSingletonKey->openKeys() ); + for ( sal_Int32 i = singletonKeys.getLength(); i--; ) + { + Reference<registry::XRegistryKey> const & xSingleton = + singletonKeys[ i ]; + pSingletons->push_back( + ::std::pair<OUString, OUString>( + xSingleton->getKeyName().copy( + implName.getLength() + + sizeof ("//UNO/SINGLETONS/") - 1 ), + xSingleton->getStringValue() ) ); + } + } + else + { + pImplNames->push_back( implName ); + } + } + + return xLoader; +} + +// Package +//______________________________________________________________________________ +beans::Optional< beans::Ambiguous<sal_Bool> > +BackendImpl::ComponentPackageImpl::isRegistered_( + ::osl::ResettableMutexGuard &, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & ) +{ + if (m_registered == REG_UNINIT) + { + m_registered = REG_NOT_REGISTERED; + bool bAmbiguousComponentName = false; + const Reference<registry::XSimpleRegistry> xRDB( getRDB_RO() ); + if (xRDB.is()) + { + // lookup rdb for location URL: + const Reference<registry::XRegistryKey> xRootKey( + xRDB->getRootKey() ); + const Reference<registry::XRegistryKey> xImplKey( + xRootKey->openKey( OUSTR("IMPLEMENTATIONS") ) ); + Sequence<OUString> implNames; + if (xImplKey.is() && xImplKey->isValid()) + implNames = xImplKey->getKeyNames(); + OUString const * pImplNames = implNames.getConstArray(); + sal_Int32 pos = implNames.getLength(); + for ( ; pos--; ) + { + checkAborted( abortChannel ); + const OUString key( + pImplNames[ pos ] + OUSTR("/UNO/LOCATION") ); + const Reference<registry::XRegistryKey> xKey( + xRootKey->openKey(key) ); + if (xKey.is() && xKey->isValid()) + { + const OUString location( xKey->getAsciiValue() ); + if (location.equalsIgnoreAsciiCase( getURL() )) + { + break; + } + else + { + //try to match only the file name + OUString thisUrl(getURL()); + OUString thisFileName(thisUrl.copy(thisUrl.lastIndexOf('/'))); + + OUString locationFileName(location.copy(location.lastIndexOf('/'))); + if (locationFileName.equalsIgnoreAsciiCase(thisFileName)) + bAmbiguousComponentName = true; + } + } + } + if (pos >= 0) + m_registered = REG_REGISTERED; + else if (bAmbiguousComponentName) + m_registered = REG_MAYBE_REGISTERED; + } + } + + //Different extensions can use the same service implementations. Then the extensions + //which was installed last will overwrite the one from the other extension. That is + //the registry will contain the path (the location) of the library or jar of the + //second extension. In this case isRegistered called for the lib of the first extension + //would return "not registered". That would mean that during uninstallation + //XPackage::registerPackage is not called, because it just was not registered. This is, + //however, necessary for jar files. Registering and unregistering update + //uno_packages/cache/registry/com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc + //Therefore, we will return always "is ambiguous" if the path of this component cannot + //be found in the registry and if there is another path and both have the same file name (but + //the rest of the path is different). + //If the caller cannot precisely determine that this package was registered, then it must + //call registerPackage. + sal_Bool bAmbiguous = m_registered == REG_VOID // REG_VOID == we are in the progress of unregistration + || m_registered == REG_MAYBE_REGISTERED; + return beans::Optional< beans::Ambiguous<sal_Bool> >( + true /* IsPresent */, + beans::Ambiguous<sal_Bool>( + m_registered == REG_REGISTERED, bAmbiguous) ); +} + +//______________________________________________________________________________ +void BackendImpl::ComponentPackageImpl::processPackage_( + ::osl::ResettableMutexGuard &, + bool doRegisterPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + BackendImpl * that = getMyBackend(); + + + const bool java = m_loader.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.loader.Java2") ); + const OUString url( getURL() ); + bool isJavaTypelib; + if (m_bRemoved) + isJavaTypelib = m_registeredComponentsDb.javaTypeLibrary; + else + isJavaTypelib = java && + !jarManifestHeaderPresent( url, OUSTR("UNO-Type-Path"), xCmdEnv ); + + ComponentBackendDb::Data data; + data.javaTypeLibrary = isJavaTypelib; + if (doRegisterPackage) + { + Reference <uno::XComponentContext> context(that->getComponentContext()); + if (! startup) + { + context.set( + that->getObject( url ), UNO_QUERY ); + + if (! context.is()) { + context.set( + that->insertObject( url, raise_uno_process( + that->getComponentContext(), + abortChannel ) ), + UNO_QUERY_THROW ); + } + } + + const Reference<registry::XSimpleRegistry> xServicesRDB( getRDB() ); + const Reference<registry::XImplementationRegistration> xImplReg( + context->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.registry.ImplementationRegistration"), + context ), UNO_QUERY_THROW ); + + xImplReg->registerImplementation( m_loader, url, xServicesRDB ); + //only write to unorc if registration was successful. + //It may fail if there is no suitable java. + if (isJavaTypelib) + { + that->addToUnoRc( java, url, xCmdEnv ); + data.javaTypeLibrary = true; + } + + t_stringlist implNames; + t_stringpairvec singletons; + const Reference<loader::XImplementationLoader> xLoader( + getComponentInfo( &implNames, &singletons, context ) ); + data.implementationNames = implNames; + data.singletons = singletons; + + if (!startup) + { + // factories live insertion: + const Reference<container::XSet> xSet( + that->getComponentContext()->getServiceManager(), UNO_QUERY_THROW ); + for ( t_stringlist::const_iterator iPos( implNames.begin() ); + iPos != implNames.end(); ++iPos ) + { + checkAborted( abortChannel ); + OUString const & implName = *iPos; + // activate factory: + const Reference<XInterface> xFactory( + xLoader->activate( + implName, OUString(), url, + xServicesRDB->getRootKey()->openKey( + OUSTR("/IMPLEMENTATIONS/") + implName ) ) ); + try { + xSet->insert( Any(xFactory) ); + } // ignore if factory has already been inserted: + catch (container::ElementExistException &) { + OSL_ENSURE( 0, "### factory already registered?" ); + } + } + + if (! singletons.empty()) + { + // singletons live insertion: + const Reference<container::XNameContainer> xRootContext( + that->getComponentContext()->getValueByName( + OUSTR("_root") ), UNO_QUERY ); + if (xRootContext.is()) + { + for ( t_stringpairvec::const_iterator iPos( + singletons.begin() ); + iPos != singletons.end(); ++iPos ) + { + ::std::pair<OUString, OUString> const & sp = *iPos; + const OUString name( OUSTR("/singletons/") + sp.first ); + // assure no arguments: + try { + xRootContext->removeByName( name + OUSTR("/arguments")); + } catch (container::NoSuchElementException &) {} + // used service: + try { + xRootContext->insertByName( + name + OUSTR("/service"), Any(sp.second) ); + } catch (container::ElementExistException &) { + xRootContext->replaceByName( + name + OUSTR("/service"), Any(sp.second) ); + } + // singleton entry: + try { + xRootContext->insertByName( name, Any() ); + } catch (container::ElementExistException & exc) { + (void) exc; // avoid warnings + OSL_ENSURE( + 0, OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + xRootContext->replaceByName( name, Any() ); + } + } + } + } + } + + m_registered = REG_REGISTERED; + getMyBackend()->addDataToDb(url, data); + } + else // revokePackage() + { + // set to VOID during revocation process: + m_registered = REG_VOID; + + //get the remote context. If it does not exist then use the local one + Reference<XComponentContext> xContext( + that->getObject( url ), UNO_QUERY ); + bool bRemoteContext = false; + if (!xContext.is()) + xContext = that->getComponentContext(); + else + bRemoteContext = true; + + t_stringlist implNames; + t_stringpairvec singletons; + if (m_bRemoved) + { + implNames = m_registeredComponentsDb.implementationNames; + singletons = m_registeredComponentsDb.singletons; + } + else + { + getComponentInfo( &implNames, &singletons, xContext ); + } + + if (!startup) + { + // factories live removal: + const Reference<container::XSet> xSet( + that->getComponentContext()->getServiceManager(), UNO_QUERY_THROW ); + for ( t_stringlist::const_iterator iPos( implNames.begin() ); + iPos != implNames.end(); ++iPos ) + { + OUString const & implName = *iPos; + try { + xSet->remove( Any(implName) ); + } // ignore if factory has not been live deployed: + catch (container::NoSuchElementException &) { + } + } + + if (! singletons.empty()) + { + // singletons live removal: + const Reference<container::XNameContainer> xRootContext( + that->getComponentContext()->getValueByName( + OUSTR("_root") ), UNO_QUERY ); + if (xRootContext.is()) + { + for ( t_stringpairvec::const_iterator iPos( + singletons.begin() ); + iPos != singletons.end(); ++iPos ) + { + ::std::pair<OUString, OUString> const & sp = *iPos; + const OUString name( OUSTR("/singletons/") + sp.first ); + // arguments: + try { + xRootContext->removeByName( name + OUSTR("/arguments")); + } + catch (container::NoSuchElementException &) {} + // used service: + try { + xRootContext->removeByName( name + OUSTR("/service") ); + } + catch (container::NoSuchElementException &) {} + // singleton entry: + try { + xRootContext->removeByName( name ); + } + catch (container::NoSuchElementException & exc) { + (void) exc; // avoid warnings + OSL_ENSURE( + 0, OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + } + } + } + } + + const Reference<registry::XSimpleRegistry> xServicesRDB( getRDB() ); + const Reference<registry::XImplementationRegistration> xImplReg( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.registry.ImplementationRegistration"), + xContext ), UNO_QUERY_THROW ); + xImplReg->revokeImplementation( url, xServicesRDB ); + + if (isJavaTypelib) + that->removeFromUnoRc( java, url, xCmdEnv ); + + if (bRemoteContext) + that->releaseObject( url ); + + m_registered = REG_NOT_REGISTERED; + getMyBackend()->deleteDataFromDb(url); + } +} + +//############################################################################## +BackendImpl::TypelibraryPackageImpl::TypelibraryPackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool jarFile, bool bRemoved, OUString const & identifier) + : Package( myBackend, url, name, name /* display-name */, + xPackageType, bRemoved, identifier), + m_jarFile( jarFile ) +{ +} + +// Package +BackendImpl * BackendImpl::TypelibraryPackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); + if (NULL == pBackend) + { + //May throw a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<TypelibraryPackageImpl *>(this))); + } + return pBackend; +} +//______________________________________________________________________________ +beans::Optional< beans::Ambiguous<sal_Bool> > +BackendImpl::TypelibraryPackageImpl::isRegistered_( + ::osl::ResettableMutexGuard &, + ::rtl::Reference<AbortChannel> const &, + Reference<XCommandEnvironment> const & ) +{ + BackendImpl * that = getMyBackend(); + return beans::Optional< beans::Ambiguous<sal_Bool> >( + true /* IsPresent */, + beans::Ambiguous<sal_Bool>( + that->hasInUnoRc( m_jarFile, getURL() ), + false /* IsAmbiguous */ ) ); +} + +//______________________________________________________________________________ +void BackendImpl::TypelibraryPackageImpl::processPackage_( + ::osl::ResettableMutexGuard &, + bool doRegisterPackage, + bool /*startup*/, + ::rtl::Reference<AbortChannel> const &, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + BackendImpl * that = getMyBackend(); + const OUString url( getURL() ); + + if (doRegisterPackage) + { + // live insertion: + if (m_jarFile) { + // xxx todo add to classpath at runtime: ??? + //SB: It is probably not worth it to add the live inserted type + // library JAR to the UnoClassLoader in the soffice process. Any + // live inserted component JAR that might reference this type + // library JAR runs in its own uno process, so there is probably no + // Java code in the soffice process that would see any UNO types + // introduced by this type library JAR. + } + else // RDB: + { + Reference<XComponentContext> const & xContext = + that->getComponentContext(); + if (! m_xTDprov.is()) + { + m_xTDprov.set( that->getObject( url ), UNO_QUERY ); + if (! m_xTDprov.is()) + { + const Reference<registry::XSimpleRegistry> xReg( + xContext->getServiceManager() + ->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), + xContext ), UNO_QUERY_THROW ); + xReg->open( expandUnoRcUrl(url), + true /* read-only */, false /* ! create */ ); + const Any arg(xReg); + Reference<container::XHierarchicalNameAccess> xTDprov( + xContext->getServiceManager() + ->createInstanceWithArgumentsAndContext( + OUSTR("com.sun.star.comp.stoc." + "RegistryTypeDescriptionProvider"), + Sequence<Any>( &arg, 1 ), xContext ), UNO_QUERY ); + OSL_ASSERT( xTDprov.is() ); + if (xTDprov.is()) + m_xTDprov.set( that->insertObject( url, xTDprov ), + UNO_QUERY_THROW ); + } + } + if (m_xTDprov.is()) { + Reference<container::XSet> xSet( + xContext->getValueByName( + OUSTR("/singletons/com.sun.star." + "reflection.theTypeDescriptionManager") ), + UNO_QUERY_THROW ); + xSet->insert( Any(m_xTDprov) ); + } + } + + that->addToUnoRc( m_jarFile, url, xCmdEnv ); + } + else // revokePackage() + { + that->removeFromUnoRc( m_jarFile, url, xCmdEnv ); + + // revoking types at runtime, possible, sensible? + if (!m_xTDprov.is()) + m_xTDprov.set( that->getObject( url ), UNO_QUERY ); + if (m_xTDprov.is()) { + // remove live: + const Reference<container::XSet> xSet( + that->getComponentContext()->getValueByName( + OUSTR("/singletons/com.sun.star." + "reflection.theTypeDescriptionManager") ), + UNO_QUERY_THROW ); + xSet->remove( Any(m_xTDprov) ); + + that->releaseObject( url ); + m_xTDprov.clear(); + } + } +} + +} // anon namespace + +namespace sdecl = comphelper::service_decl; +sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI; +extern sdecl::ServiceDecl const serviceDecl( + serviceBI, + IMPLEMENTATION_NAME, + BACKEND_SERVICE_NAME ); + +} // namespace component +} // namespace backend +} // namespace dp_registry + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/component/dp_component.hrc b/desktop/source/deployment/registry/component/dp_component.hrc new file mode 100644 index 000000000000..5e9993ab1222 --- /dev/null +++ b/desktop/source/deployment/registry/component/dp_component.hrc @@ -0,0 +1,39 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_COMPONENT_HRC +#define INCLUDED_DP_COMPONENT_HRC + +#include "deployment.hrc" + +#define RID_STR_DYN_COMPONENT (RID_DEPLOYMENT_COMPONENT_START+10) +#define RID_STR_JAVA_COMPONENT (RID_DEPLOYMENT_COMPONENT_START+11) +#define RID_STR_PYTHON_COMPONENT (RID_DEPLOYMENT_COMPONENT_START+12) +#define RID_STR_RDB_TYPELIB (RID_DEPLOYMENT_COMPONENT_START+20) +#define RID_STR_JAVA_TYPELIB (RID_DEPLOYMENT_COMPONENT_START+21) + +#endif diff --git a/desktop/source/deployment/registry/component/dp_component.src b/desktop/source/deployment/registry/component/dp_component.src new file mode 100644 index 000000000000..52dfa568ebe3 --- /dev/null +++ b/desktop/source/deployment/registry/component/dp_component.src @@ -0,0 +1,54 @@ +/************************************************************************* + * + * 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 "dp_component.hrc" + +String RID_STR_DYN_COMPONENT +{ + Text [ en-US ] = "UNO Dynamic Library Component"; +}; + +String RID_STR_JAVA_COMPONENT +{ + Text [ en-US ] = "UNO Java Component"; +}; + +String RID_STR_PYTHON_COMPONENT +{ + Text [ en-US ] = "UNO Python Component"; +}; + +String RID_STR_RDB_TYPELIB +{ + Text [ en-US ] = "UNO RDB Type Library"; +}; + +String RID_STR_JAVA_TYPELIB +{ + Text [ en-US ] = "UNO Java Type Library"; +}; + diff --git a/desktop/source/deployment/registry/component/makefile.mk b/desktop/source/deployment/registry/component/makefile.mk new file mode 100644 index 000000000000..b7ee5c203cd5 --- /dev/null +++ b/desktop/source/deployment/registry/component/makefile.mk @@ -0,0 +1,48 @@ +#************************************************************************* +# +# 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 = deployment_registry_component +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE : settings.mk + +SRS1NAME = $(TARGET) +SRC1FILES = \ + dp_component.src + +INCPRE += ..$/..$/inc + +SLOFILES = \ + $(SLO)$/dp_component.obj \ + $(SLO)$/dp_compbackenddb.obj + +.INCLUDE : ..$/..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/registry/configuration/dp_configuration.cxx b/desktop/source/deployment/registry/configuration/dp_configuration.cxx new file mode 100644 index 000000000000..2688a277f947 --- /dev/null +++ b/desktop/source/deployment/registry/configuration/dp_configuration.cxx @@ -0,0 +1,785 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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" + +//TODO: Large parts of this file were copied from dp_component.cxx; those parts +// should be consolidated. + +#include "dp_configuration.hrc" +#include "dp_backend.h" +#include "dp_persmap.h" +#include "dp_ucb.h" +#include "rtl/string.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/uri.hxx" +#include "rtl/memory.h" +#include "osl/file.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "ucbhelper/content.hxx" +#include "comphelper/anytostring.hxx" +#include "comphelper/servicedecl.hxx" +#include "xmlscript/xml_helper.hxx" +#include "svl/inettype.hxx" +#include "com/sun/star/configuration/Update.hpp" +#include "com/sun/star/ucb/NameClash.hpp" +#include "com/sun/star/io/XActiveDataSink.hpp" +#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" +#include "com/sun/star/util/XRefreshable.hpp" +#include <list> +#include <memory> + +#include "dp_configurationbackenddb.hxx" + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; + +namespace dp_registry { +namespace backend { +namespace configuration { +namespace { + +typedef ::std::list<OUString> t_stringlist; + +//============================================================================== +class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend +{ + class PackageImpl : public ::dp_registry::backend::Package + { + BackendImpl * getMyBackend() const ; + + const bool m_isSchema; + + // Package + virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + + public: + inline PackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool isSchema, bool bRemoved, OUString const & identifier) + : Package( myBackend, url, name, name /* display-name */, + xPackageType, bRemoved, identifier), + m_isSchema( isSchema ) + {} + }; + friend class PackageImpl; + + t_stringlist m_xcs_files; + t_stringlist m_xcu_files; + t_stringlist & getFiles( bool xcs ) { + return xcs ? m_xcs_files : m_xcu_files; + } + + bool m_configmgrini_inited; + bool m_configmgrini_modified; + std::auto_ptr<ConfigurationBackendDb> m_backendDb; + + // PackageRegistryBackend + virtual Reference<deployment::XPackage> bindPackage_( + OUString const & url, OUString const & mediaType, sal_Bool bRemoved, + OUString const & identifier, + Reference<XCommandEnvironment> const & xCmdEnv ); + + ::std::auto_ptr<PersistentMap> m_registeredPackages; + // for backwards compatibility + + virtual void SAL_CALL disposing(); + + const Reference<deployment::XPackageTypeInfo> m_xConfDataTypeInfo; + const Reference<deployment::XPackageTypeInfo> m_xConfSchemaTypeInfo; + Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos; + + void configmgrini_verify_init( + Reference<XCommandEnvironment> const & xCmdEnv ); + void configmgrini_flush( Reference<XCommandEnvironment> const & xCmdEnv ); + + bool addToConfigmgrIni( bool isSchema, OUString const & url, + Reference<XCommandEnvironment> const & xCmdEnv ); + bool removeFromConfigmgrIni( bool isSchema, OUString const & url, + Reference<XCommandEnvironment> const & xCmdEnv ); + + void addDataToDb(OUString const & url, ConfigurationBackendDb::Data const & data); + ::boost::optional<ConfigurationBackendDb::Data> readDataFromDb(OUString const & url); + OUString deleteDataFromDb(OUString const & url); + ::std::list<OUString> getAllIniEntries(); + +public: + BackendImpl( Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ); + + // XPackageRegistry + virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() throw (RuntimeException); + + using PackageRegistryBackend::disposing; +}; + +//______________________________________________________________________________ +void BackendImpl::disposing() +{ + try { + configmgrini_flush( Reference<XCommandEnvironment>() ); + + PackageRegistryBackend::disposing(); + } + catch (RuntimeException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + throw lang::WrappedTargetRuntimeException( + OUSTR("caught unexpected exception while disposing..."), + static_cast<OWeakObject *>(this), exc ); + } +} + +//______________________________________________________________________________ +BackendImpl::BackendImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ) + : PackageRegistryBackend( args, xComponentContext ), + m_configmgrini_inited( false ), + m_configmgrini_modified( false ), + m_xConfDataTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.configuration-data"), + OUSTR("*.xcu"), + getResourceString(RID_STR_CONF_DATA), + RID_IMG_CONF_XML, RID_IMG_CONF_XML_HC ) ), + m_xConfSchemaTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.configuration-schema"), + OUSTR("*.xcs"), + getResourceString(RID_STR_CONF_SCHEMA), + RID_IMG_CONF_XML, RID_IMG_CONF_XML_HC ) ), + m_typeInfos( 2 ) +{ + m_typeInfos[ 0 ] = m_xConfDataTypeInfo; + m_typeInfos[ 1 ] = m_xConfSchemaTypeInfo; + + const Reference<XCommandEnvironment> xCmdEnv; + + if (transientMode()) + { + //TODO + } + else + { + OUString dbFile = makeURL(getCachePath(), OUSTR("backenddb.xml")); + m_backendDb.reset( + new ConfigurationBackendDb(getComponentContext(), dbFile)); + //clean up data folders which are no longer used. + //This must not be done in the same process where the help files + //are still registers. Only after revoking and restarting OOo the folders + //can be removed. This works now, because the extension manager is a singleton + //and the backends are only create once per process. + ::std::list<OUString> folders = m_backendDb->getAllDataUrls(); + deleteUnusedFolders(OUString(), folders); + + + configmgrini_verify_init( xCmdEnv ); + m_registeredPackages.reset( + new PersistentMap( + makeURL( getCachePath(), OUSTR("registered_packages.db") ), + false ) ); + } +} + +void BackendImpl::addDataToDb( + OUString const & url, ConfigurationBackendDb::Data const & data) +{ + if (m_backendDb.get()) + m_backendDb->addEntry(url, data); +} + +::boost::optional<ConfigurationBackendDb::Data> BackendImpl::readDataFromDb( + OUString const & url) +{ + ::boost::optional<ConfigurationBackendDb::Data> data; + if (m_backendDb.get()) + data = m_backendDb->getEntry(url); + return data; +} + +OUString BackendImpl::deleteDataFromDb(OUString const & url) +{ + OUString url2(url); + if (m_backendDb.get()) { + boost::optional< ConfigurationBackendDb::Data > data( + m_backendDb->getEntry(url)); + if (data) { + url2 = expandUnoRcTerm(data->iniEntry); + } + m_backendDb->removeEntry(url); + } + return url2; +} + +::std::list<OUString> BackendImpl::getAllIniEntries() +{ + if (m_backendDb.get()) + return m_backendDb->getAllIniEntries(); + else + return ::std::list<OUString>(); +} + + + +// XPackageRegistry +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackageTypeInfo> > +BackendImpl::getSupportedPackageTypes() throw (RuntimeException) +{ + return m_typeInfos; +} + +// PackageRegistryBackend +//______________________________________________________________________________ +Reference<deployment::XPackage> BackendImpl::bindPackage_( + OUString const & url, OUString const & mediaType_, + sal_Bool bRemoved, OUString const & identifier, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + OUString mediaType( mediaType_ ); + if (mediaType.getLength() == 0) + { + // detect media-type: + ::ucbhelper::Content ucbContent; + if (create_ucb_content( &ucbContent, url, xCmdEnv )) + { + const OUString title( ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>() ); + if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".xcu") )) { + mediaType = OUSTR("application/" + "vnd.sun.star.configuration-data"); + } + if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".xcs") )) { + mediaType = OUSTR("application/" + "vnd.sun.star.configuration-schema"); + } + } + if (mediaType.getLength() == 0) + throw lang::IllegalArgumentException( + StrCannotDetectMediaType::get() + url, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); + } + + String type, subType; + INetContentTypeParameterList params; + if (INetContentTypes::parse( mediaType, type, subType, ¶ms )) + { + if (type.EqualsIgnoreCaseAscii("application")) + { + OUString name; + if (!bRemoved) + { + ::ucbhelper::Content ucbContent( url, xCmdEnv ); + name = ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>(); + } + + ::ucbhelper::Content ucbContent( url, xCmdEnv ); + if (subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.configuration-data")) + { + return new PackageImpl( + this, url, name, m_xConfDataTypeInfo, false /* data file */, + bRemoved, identifier); + } + else if (subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.configuration-schema")) { + return new PackageImpl( + this, url, name, m_xConfSchemaTypeInfo, true /* schema file */, + bRemoved, identifier); + } + } + } + throw lang::IllegalArgumentException( + StrUnsupportedMediaType::get() + mediaType, + static_cast<OWeakObject *>(this), + static_cast<sal_Int16>(-1) ); +} + +//############################################################################## + +//______________________________________________________________________________ +void BackendImpl::configmgrini_verify_init( + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + if (transientMode()) + return; + const ::osl::MutexGuard guard( getMutex() ); + if (! m_configmgrini_inited) + { + // common rc: + ::ucbhelper::Content ucb_content; + if (create_ucb_content( + &ucb_content, + makeURL( getCachePath(), OUSTR("configmgr.ini") ), + xCmdEnv, false /* no throw */ )) + { + OUString line; + if (readLine( &line, OUSTR("SCHEMA="), ucb_content, + RTL_TEXTENCODING_UTF8 )) + { + sal_Int32 index = sizeof ("SCHEMA=") - 1; + do { + OUString token( line.getToken( 0, ' ', index ).trim() ); + if (token.getLength() > 0) { + //The file may not exist anymore if a shared or bundled + //extension was removed, but it can still be in the configmgrini. + //After running XExtensionManager::synchronize, the configmgrini is + //cleaned up + m_xcs_files.push_back( token ); + } + } + while (index >= 0); + } + if (readLine( &line, OUSTR("DATA="), ucb_content, + RTL_TEXTENCODING_UTF8 )) { + sal_Int32 index = sizeof ("DATA=") - 1; + do { + OUString token( line.getToken( 0, ' ', index ).trim() ); + if (token.getLength() > 0) + { + if (token[ 0 ] == '?') + token = token.copy( 1 ); + //The file may not exist anymore if a shared or bundled + //extension was removed, but it can still be in the configmgrini. + //After running XExtensionManager::synchronize, the configmgrini is + //cleaned up + m_xcu_files.push_back( token ); + } + } + while (index >= 0); + } + } + m_configmgrini_modified = false; + m_configmgrini_inited = true; + } +} + +//______________________________________________________________________________ +void BackendImpl::configmgrini_flush( + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + if (transientMode()) + return; + if (!m_configmgrini_inited || !m_configmgrini_modified) + return; + + ::rtl::OStringBuffer buf; + if (! m_xcs_files.empty()) + { + t_stringlist::const_iterator iPos( m_xcs_files.begin() ); + t_stringlist::const_iterator const iEnd( m_xcs_files.end() ); + buf.append( RTL_CONSTASCII_STRINGPARAM("SCHEMA=") ); + while (iPos != iEnd) { + // encoded ASCII file-urls: + const ::rtl::OString item( + ::rtl::OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( item ); + ++iPos; + if (iPos != iEnd) + buf.append( ' ' ); + } + buf.append(LF); + } + if (! m_xcu_files.empty()) + { + t_stringlist::const_iterator iPos( m_xcu_files.begin() ); + t_stringlist::const_iterator const iEnd( m_xcu_files.end() ); + buf.append( RTL_CONSTASCII_STRINGPARAM("DATA=") ); + while (iPos != iEnd) { + // encoded ASCII file-urls: + const ::rtl::OString item( + ::rtl::OUStringToOString( *iPos, RTL_TEXTENCODING_ASCII_US ) ); + buf.append( item ); + ++iPos; + if (iPos != iEnd) + buf.append( ' ' ); + } + buf.append(LF); + } + + // write configmgr.ini: + const Reference<io::XInputStream> xData( + ::xmlscript::createInputStream( + ::rtl::ByteSequence( + reinterpret_cast<sal_Int8 const *>(buf.getStr()), + buf.getLength() ) ) ); + ::ucbhelper::Content ucb_content( + makeURL( getCachePath(), OUSTR("configmgr.ini") ), xCmdEnv ); + ucb_content.writeStream( xData, true /* replace existing */ ); + + m_configmgrini_modified = false; +} + +//______________________________________________________________________________ +bool BackendImpl::addToConfigmgrIni( bool isSchema, OUString const & url_, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + const OUString rcterm( dp_misc::makeRcTerm(url_) ); + const ::osl::MutexGuard guard( getMutex() ); + configmgrini_verify_init( xCmdEnv ); + t_stringlist & rSet = getFiles(isSchema); + if (::std::find( rSet.begin(), rSet.end(), rcterm ) == rSet.end()) { + rSet.push_front( rcterm ); // prepend to list, thus overriding + // write immediately: + m_configmgrini_modified = true; + configmgrini_flush( xCmdEnv ); + return true; + } + else + return false; +} + +//______________________________________________________________________________ +bool BackendImpl::removeFromConfigmgrIni( + bool isSchema, OUString const & url_, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + const OUString rcterm( dp_misc::makeRcTerm(url_) ); + const ::osl::MutexGuard guard( getMutex() ); + configmgrini_verify_init( xCmdEnv ); + t_stringlist & rSet = getFiles(isSchema); + t_stringlist::iterator i(std::find(rSet.begin(), rSet.end(), rcterm)); + if (i == rSet.end() && !isSchema) + { + //in case the xcu contained %origin% then the configmr.ini contains the + //url to the file in the user installation (e.g. $BUNDLED_EXTENSIONS_USER) + //However, m_url (getURL()) contains the URL for the file in the actual + //extension installatation. + ::boost::optional<ConfigurationBackendDb::Data> data = readDataFromDb(url_); + if (data) + i = std::find(rSet.begin(), rSet.end(), data->iniEntry); + } + if (i == rSet.end()) { + return false; + } + rSet.erase(i); + // write immediately: + m_configmgrini_modified = true; + configmgrini_flush( xCmdEnv ); + return true; +} + +//############################################################################## + +// Package +//______________________________________________________________________________ +BackendImpl * BackendImpl::PackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); + if (NULL == pBackend) + { + //May throw a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<PackageImpl *>(this))); + } + return pBackend; +} + +beans::Optional< beans::Ambiguous<sal_Bool> > +BackendImpl::PackageImpl::isRegistered_( + ::osl::ResettableMutexGuard &, + ::rtl::Reference<AbortChannel> const &, + Reference<XCommandEnvironment> const & ) +{ + BackendImpl * that = getMyBackend(); + const rtl::OUString url(getURL()); + + bool bReg = false; + if (that->readDataFromDb(getURL())) + bReg = true; + if (!bReg) + //fallback for user extension registered in berkeley DB + bReg = that->m_registeredPackages->has( + rtl::OUStringToOString( url, RTL_TEXTENCODING_UTF8 )); + + return beans::Optional< beans::Ambiguous<sal_Bool> >( + true, beans::Ambiguous<sal_Bool>( bReg, false ) ); +} + +//------------------------------------------------------------------------------ +OUString encodeForXml( OUString const & text ) +{ + // encode conforming xml: + sal_Int32 len = text.getLength(); + ::rtl::OUStringBuffer buf; + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + sal_Unicode c = text[ pos ]; + switch (c) { + case '<': + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("<") ); + break; + case '>': + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(">") ); + break; + case '&': + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("&") ); + break; + case '\'': + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("'") ); + break; + case '\"': + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(""") ); + break; + default: + buf.append( c ); + break; + } + } + return buf.makeStringAndClear(); +} + +//______________________________________________________________________________ +OUString replaceOrigin( + OUString const & url, OUString const & destFolder, Reference< XCommandEnvironment > const & xCmdEnv, bool & out_replaced) +{ + // looking for %origin%: + ::ucbhelper::Content ucb_content( url, xCmdEnv ); + ::rtl::ByteSequence bytes( readFile( ucb_content ) ); + ::rtl::ByteSequence filtered( bytes.getLength() * 2, + ::rtl::BYTESEQ_NODEFAULT ); + bool use_filtered = false; + ::rtl::OString origin; + sal_Char const * pBytes = reinterpret_cast<sal_Char const *>( + bytes.getConstArray()); + sal_Size nBytes = bytes.getLength(); + sal_Int32 write_pos = 0; + while (nBytes > 0) + { + sal_Int32 index = rtl_str_indexOfChar_WithLength( pBytes, nBytes, '%' ); + if (index < 0) { + if (! use_filtered) // opt + break; + index = nBytes; + } + + if ((write_pos + index) > filtered.getLength()) + filtered.realloc( (filtered.getLength() + index) * 2 ); + rtl_copyMemory( filtered.getArray() + write_pos, pBytes, index ); + write_pos += index; + pBytes += index; + nBytes -= index; + if (nBytes == 0) + break; + + // consume %: + ++pBytes; + --nBytes; + sal_Char const * pAdd = "%"; + sal_Int32 nAdd = 1; + if (nBytes > 1 && pBytes[ 0 ] == '%') + { + // %% => % + ++pBytes; + --nBytes; + use_filtered = true; + } + else if (rtl_str_shortenedCompare_WithLength( + pBytes, nBytes, + RTL_CONSTASCII_STRINGPARAM("origin%"), + sizeof ("origin%") - 1 ) == 0) + { + if (origin.getLength() == 0) { + // encode only once + origin = ::rtl::OUStringToOString( + encodeForXml( url.copy( 0, url.lastIndexOf( '/' ) ) ), + // xxx todo: encode always for UTF-8? => lookup doc-header? + RTL_TEXTENCODING_UTF8 ); + } + pAdd = origin.getStr(); + nAdd = origin.getLength(); + pBytes += (sizeof ("origin%") - 1); + nBytes -= (sizeof ("origin%") - 1); + use_filtered = true; + } + if ((write_pos + nAdd) > filtered.getLength()) + filtered.realloc( (filtered.getLength() + nAdd) * 2 ); + rtl_copyMemory( filtered.getArray() + write_pos, pAdd, nAdd ); + write_pos += nAdd; + } + if (!use_filtered) + return url; + if (write_pos < filtered.getLength()) + filtered.realloc( write_pos ); + rtl::OUString newUrl(url); + if (destFolder.getLength()) + { + //get the file name of the xcu and add it to the url of the temporary folder + sal_Int32 i = url.lastIndexOf('/'); + newUrl = destFolder + url.copy(i); + } + + ucbhelper::Content(newUrl, xCmdEnv).writeStream( + xmlscript::createInputStream(filtered), true); + out_replaced = true; + return newUrl; +} + +//______________________________________________________________________________ +void BackendImpl::PackageImpl::processPackage_( + ::osl::ResettableMutexGuard &, + bool doRegisterPackage, + bool startup, + ::rtl::Reference<AbortChannel> const &, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + BackendImpl * that = getMyBackend(); + OUString url( getURL() ); + + if (doRegisterPackage) + { + ConfigurationBackendDb::Data data; + if (!m_isSchema) + { + const OUString sModFolder = that->createFolder(OUString(), xCmdEnv); + bool out_replaced = false; + url = replaceOrigin(url, sModFolder, xCmdEnv, out_replaced); + if (out_replaced) + data.dataUrl = sModFolder; + else + deleteTempFolder(sModFolder); + } + //No need for live-deployment for bundled extension, because OOo + //restarts after installation + if (that->m_eContext != CONTEXT_BUNDLED + && !startup) + { + if (m_isSchema) + { + com::sun::star::configuration::Update::get( + that->m_xComponentContext)->insertExtensionXcsFile( + that->m_eContext == CONTEXT_SHARED, expandUnoRcUrl(url)); + } + else + { + com::sun::star::configuration::Update::get( + that->m_xComponentContext)->insertExtensionXcuFile( + that->m_eContext == CONTEXT_SHARED, expandUnoRcUrl(url)); + } + } + that->addToConfigmgrIni( m_isSchema, url, xCmdEnv ); + data.iniEntry = dp_misc::makeRcTerm(url); + that->addDataToDb(getURL(), data); + } + else // revoke + { + if (!that->removeFromConfigmgrIni(m_isSchema, url, xCmdEnv)) { + t_string2string_map entries( + that->m_registeredPackages->getEntries()); + for (t_string2string_map::iterator i(entries.begin()); + i != entries.end(); ++i) + { + //If the xcu file was installed before the configmgr was chaned + //to use the configmgr.ini, one needed to rebuild to whole directory + //structur containing the xcu, xcs files from all extensions. Now, + //we just add all other xcu/xcs files to the configmgr.ini instead of + //rebuilding the directory structure. + rtl::OUString url2( + rtl::OStringToOUString(i->first, RTL_TEXTENCODING_UTF8)); + if (url2 != url) { + bool schema = i->second.equalsIgnoreAsciiCase( + "vnd.sun.star.configuration-schema"); + OUString url_replaced(url2); + ConfigurationBackendDb::Data data; + if (!schema) + { + const OUString sModFolder = that->createFolder(OUString(), xCmdEnv); + bool out_replaced = false; + url_replaced = replaceOrigin( + url2, sModFolder, xCmdEnv, out_replaced); + if (out_replaced) + data.dataUrl = sModFolder; + else + deleteTempFolder(sModFolder); + } + that->addToConfigmgrIni(schema, url_replaced, xCmdEnv); + data.iniEntry = dp_misc::makeRcTerm(url_replaced); + that->addDataToDb(url2, data); + } + that->m_registeredPackages->erase(i->first); + } + try + { + ::ucbhelper::Content( + makeURL( that->getCachePath(), OUSTR("registry") ), + xCmdEnv ).executeCommand( + OUSTR("delete"), Any( true /* delete physically */ ) ); + } + catch(Exception&) + { + OSL_ASSERT(0); + } + } + url = that->deleteDataFromDb(url); + if (!m_isSchema) { + com::sun::star::configuration::Update::get( + that->m_xComponentContext)->removeExtensionXcuFile( + expandUnoRcUrl(url)); + } + } +} + +} // anon namespace + +namespace sdecl = comphelper::service_decl; +sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI; +extern sdecl::ServiceDecl const serviceDecl( + serviceBI, + "com.sun.star.comp.deployment.configuration.PackageRegistryBackend", + BACKEND_SERVICE_NAME ); + +} // namespace configuration +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/configuration/dp_configuration.hrc b/desktop/source/deployment/registry/configuration/dp_configuration.hrc new file mode 100644 index 000000000000..479f50e20baf --- /dev/null +++ b/desktop/source/deployment/registry/configuration/dp_configuration.hrc @@ -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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_CONFIGURATION_HRC +#define INCLUDED_DP_CONFIGURATION_HRC + +#include "deployment.hrc" + +#define RID_STR_CONF_SCHEMA (RID_DEPLOYMENT_CONF_START+10) +#define RID_STR_CONF_DATA (RID_DEPLOYMENT_CONF_START+11) + +#endif diff --git a/desktop/source/deployment/registry/configuration/dp_configuration.src b/desktop/source/deployment/registry/configuration/dp_configuration.src new file mode 100644 index 000000000000..3570eaf28fad --- /dev/null +++ b/desktop/source/deployment/registry/configuration/dp_configuration.src @@ -0,0 +1,39 @@ +/************************************************************************* + * + * 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 "dp_configuration.hrc" + +String RID_STR_CONF_SCHEMA +{ + Text [ en-US ] = "Configuration Schema"; +}; + +String RID_STR_CONF_DATA +{ + Text [ en-US ] = "Configuration Data"; +}; + diff --git a/desktop/source/deployment/registry/configuration/dp_configurationbackenddb.cxx b/desktop/source/deployment/registry/configuration/dp_configurationbackenddb.cxx new file mode 100644 index 000000000000..a0cafe03319c --- /dev/null +++ b/desktop/source/deployment/registry/configuration/dp_configurationbackenddb.cxx @@ -0,0 +1,185 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "rtl/string.h" +#include "rtl/bootstrap.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "dp_misc.h" + +#include "dp_configurationbackenddb.hxx" + + +namespace css = ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +#define EXTENSION_REG_NS "http://openoffice.org/extensionmanager/configuration-registry/2010" +#define NS_PREFIX "conf" +#define ROOT_ELEMENT_NAME "configuration-backend-db" +#define KEY_ELEMENT_NAME "configuration" + +namespace dp_registry { +namespace backend { +namespace configuration { + +ConfigurationBackendDb::ConfigurationBackendDb( + Reference<XComponentContext> const & xContext, + ::rtl::OUString const & url):BackendDb(xContext, url) +{ + +} + +OUString ConfigurationBackendDb::getDbNSName() +{ + return OUSTR(EXTENSION_REG_NS); +} + +OUString ConfigurationBackendDb::getNSPrefix() +{ + return OUSTR(NS_PREFIX); +} + +OUString ConfigurationBackendDb::getRootElementName() +{ + return OUSTR(ROOT_ELEMENT_NAME); +} + +OUString ConfigurationBackendDb::getKeyElementName() +{ + return OUSTR(KEY_ELEMENT_NAME); +} + + +void ConfigurationBackendDb::addEntry(::rtl::OUString const & url, Data const & data) +{ + try{ + Reference<css::xml::dom::XNode> helpNode + = writeKeyElement(url); + + writeSimpleElement(OUSTR("data-url"), data.dataUrl, helpNode); + writeSimpleElement(OUSTR("ini-entry"), data.iniEntry, helpNode); + save(); + } + catch (css::deployment::DeploymentException& ) + { + throw; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in configuration backend db: ") + + m_urlDb, 0, exc); + } +} + + +::boost::optional<ConfigurationBackendDb::Data> +ConfigurationBackendDb::getEntry(::rtl::OUString const & url) +{ + try + { + ConfigurationBackendDb::Data retData; + Reference<css::xml::dom::XNode> aNode = getKeyElement(url); + if (aNode.is()) + { + retData.dataUrl = readSimpleElement(OUSTR("data-url"), aNode); + retData.iniEntry = readSimpleElement(OUSTR("ini-entry"), aNode); + } + else + { + return ::boost::optional<Data>(); + } + return ::boost::optional<Data>(retData); + } + catch (css::deployment::DeploymentException& ) + { + throw; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in configuration backend db: ") + + m_urlDb, 0, exc); + } +} + +::std::list<OUString> ConfigurationBackendDb::getAllDataUrls() +{ + try + { + ::std::list<OUString> listRet; + Reference<css::xml::dom::XDocument> doc = getDocument(); + Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + + Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + const OUString sPrefix = getNSPrefix(); + OUString sExpression( + sPrefix + OUSTR(":configuration/") + sPrefix + OUSTR(":data-url/text()")); + Reference<css::xml::dom::XNodeList> nodes = + xpathApi->selectNodeList(root, sExpression); + if (nodes.is()) + { + sal_Int32 length = nodes->getLength(); + for (sal_Int32 i = 0; i < length; i++) + listRet.push_back(nodes->item(i)->getNodeValue()); + } + return listRet; + } + catch (css::deployment::DeploymentException& ) + { + throw; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in configuration backend db: ") + + m_urlDb, 0, exc); + } +} + +::std::list<OUString> ConfigurationBackendDb::getAllIniEntries() +{ + return getOneChildFromAllEntries(OUSTR("ini-entry")); +} + + + +} // namespace configuration +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/configuration/dp_configurationbackenddb.hxx b/desktop/source/deployment/registry/configuration/dp_configurationbackenddb.hxx new file mode 100644 index 000000000000..7cb02edf55cc --- /dev/null +++ b/desktop/source/deployment/registry/configuration/dp_configurationbackenddb.hxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_CONFIGURATIONBACKENDDB_HXX +#define INCLUDED_DP_CONFIGURATIONBACKENDDB_HXX + +#include "rtl/ustring.hxx" +#include "rtl/string.hxx" +#include <list> +#include "boost/optional.hpp" +#include "dp_backenddb.hxx" + +namespace css = ::com::sun::star; + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } +}}} + +namespace dp_registry { +namespace backend { +namespace configuration { + +/* The XML file stores the extensions which are currently registered. + They will be removed when they are revoked. + */ +class ConfigurationBackendDb: public dp_registry::backend::BackendDb +{ +protected: + virtual ::rtl::OUString getDbNSName(); + + virtual ::rtl::OUString getNSPrefix(); + + virtual ::rtl::OUString getRootElementName(); + + virtual ::rtl::OUString getKeyElementName(); + +public: + struct Data + { + /* the URL to the folder containing the xcu or xcs files which contained + %origin% + */ + ::rtl::OUString dataUrl; + /* the URL of the xcu or xcs file which is written in to the configmgr.ini + */ + ::rtl::OUString iniEntry; + }; + +public: + + ConfigurationBackendDb( css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); + + void addEntry(::rtl::OUString const & url, Data const & data); + + ::boost::optional<Data> getEntry(::rtl::OUString const & url); + ::std::list< ::rtl::OUString> getAllDataUrls(); + ::std::list< ::rtl::OUString> getAllIniEntries(); +}; + + + +} +} +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/configuration/makefile.mk b/desktop/source/deployment/registry/configuration/makefile.mk new file mode 100644 index 000000000000..9bcbd50d4230 --- /dev/null +++ b/desktop/source/deployment/registry/configuration/makefile.mk @@ -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. +# +#************************************************************************* + +PRJ = ..$/..$/..$/.. + +PRJNAME = desktop +TARGET = deployment_registry_configuration +ENABLE_EXCEPTIONS = TRUE + +INCPRE += ..$/..$/inc + +.INCLUDE : settings.mk + +.IF "$(SYSTEM_DB)" == "YES" +CFLAGS+=-DSYSTEM_DB -I$(DB_INCLUDES) +.ENDIF + +SRS1NAME = $(TARGET) +SRC1FILES = \ + dp_configuration.src + +SLOFILES = \ + $(SLO)$/dp_configuration.obj \ + $(SLO)$/dp_configurationbackenddb.obj + +.INCLUDE : ..$/..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/registry/dp_backend.cxx b/desktop/source/deployment/registry/dp_backend.cxx new file mode 100644 index 000000000000..957c55ef936b --- /dev/null +++ b/desktop/source/deployment/registry/dp_backend.cxx @@ -0,0 +1,812 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_backend.h" +#include "dp_ucb.h" +#include "rtl/uri.hxx" +#include "rtl/bootstrap.hxx" +#include "osl/file.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "comphelper/servicedecl.hxx" +#include "comphelper/unwrapargs.hxx" +#include "ucbhelper/content.hxx" +#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" +#include "com/sun/star/deployment/InvalidRemovedParameterException.hpp" +#include "com/sun/star/ucb/InteractiveAugmentedIOException.hpp" +#include "com/sun/star/ucb/IOErrorCode.hpp" +#include "com/sun/star/beans/StringPair.hpp" +#include "com/sun/star/sdbc/XResultSet.hpp" +#include "com/sun/star/sdbc/XRow.hpp" + + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; + +namespace dp_registry { +namespace backend { + +//______________________________________________________________________________ +PackageRegistryBackend::~PackageRegistryBackend() +{ +} + +//______________________________________________________________________________ +void PackageRegistryBackend::disposing( lang::EventObject const & event ) + throw (RuntimeException) +{ + Reference<deployment::XPackage> xPackage( + event.Source, UNO_QUERY_THROW ); + OUString url( xPackage->getURL() ); + ::osl::MutexGuard guard( getMutex() ); + if ( m_bound.erase( url ) != 1 ) + { + OSL_ASSERT( false ); + } +} + +//______________________________________________________________________________ +PackageRegistryBackend::PackageRegistryBackend( + Sequence<Any> const & args, + Reference<XComponentContext> const & xContext ) + : t_BackendBase( getMutex() ), + m_xComponentContext( xContext ), + m_eContext( CONTEXT_UNKNOWN ), + m_readOnly( false ) +{ + boost::optional<OUString> cachePath; + boost::optional<bool> readOnly; + comphelper::unwrapArgs( args, m_context, cachePath, readOnly ); + if (cachePath) + m_cachePath = *cachePath; + if (readOnly) + m_readOnly = *readOnly; + + if (m_context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("user") )) + m_eContext = CONTEXT_USER; + else if (m_context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("shared") )) + m_eContext = CONTEXT_SHARED; + else if (m_context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("bundled") )) + m_eContext = CONTEXT_BUNDLED; + else if (m_context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("tmp") )) + m_eContext = CONTEXT_TMP; + else if (m_context.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.tdoc:/") )) + m_eContext = CONTEXT_DOCUMENT; + else + m_eContext = CONTEXT_UNKNOWN; +} + +//______________________________________________________________________________ +void PackageRegistryBackend::check() +{ + ::osl::MutexGuard guard( getMutex() ); + if (rBHelper.bInDispose || rBHelper.bDisposed) { + throw lang::DisposedException( + OUSTR("PackageRegistryBackend instance has already been disposed!"), + static_cast<OWeakObject *>(this) ); + } +} + +//______________________________________________________________________________ +void PackageRegistryBackend::disposing() +{ + try { + for ( t_string2ref::const_iterator i = m_bound.begin(); i != m_bound.end(); i++) + i->second->removeEventListener(this); + m_bound.clear(); + m_xComponentContext.clear(); + WeakComponentImplHelperBase::disposing(); + } + catch (RuntimeException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + throw lang::WrappedTargetRuntimeException( + OUSTR("caught unexpected exception while disposing!"), + static_cast<OWeakObject *>(this), exc ); + } +} + +// XPackageRegistry +//______________________________________________________________________________ +Reference<deployment::XPackage> PackageRegistryBackend::bindPackage( + OUString const & url, OUString const & mediaType, sal_Bool bRemoved, + OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv ) + throw (deployment::DeploymentException, + deployment::InvalidRemovedParameterException, + ucb::CommandFailedException, + lang::IllegalArgumentException, RuntimeException) +{ + ::osl::ResettableMutexGuard guard( getMutex() ); + check(); + + t_string2ref::const_iterator const iFind( m_bound.find( url ) ); + if (iFind != m_bound.end()) + { + Reference<deployment::XPackage> xPackage( iFind->second ); + if (xPackage.is()) + { + if (mediaType.getLength() && + mediaType != xPackage->getPackageType()->getMediaType()) + throw lang::IllegalArgumentException + (OUSTR("XPackageRegistry::bindPackage: media type does not match"), + static_cast<OWeakObject*>(this), 1); + if (xPackage->isRemoved() != bRemoved) + throw deployment::InvalidRemovedParameterException( + OUSTR("XPackageRegistry::bindPackage: bRemoved parameter does not match"), + static_cast<OWeakObject*>(this), xPackage->isRemoved(), xPackage); + return xPackage; + } + } + + guard.clear(); + + Reference<deployment::XPackage> xNewPackage; + try { + xNewPackage = bindPackage_( url, mediaType, bRemoved, + identifier, xCmdEnv ); + } + catch (RuntimeException &) { + throw; + } + catch (lang::IllegalArgumentException &) { + throw; + } + catch (CommandFailedException &) { + throw; + } + catch (deployment::DeploymentException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + throw deployment::DeploymentException( + OUSTR("Error binding package: ") + url, + static_cast<OWeakObject *>(this), exc ); + } + + guard.reset(); + + ::std::pair< t_string2ref::iterator, bool > insertion( + m_bound.insert( t_string2ref::value_type( url, xNewPackage ) ) ); + if (insertion.second) + { // first insertion + OSL_ASSERT( Reference<XInterface>(insertion.first->second) + == xNewPackage ); + } + else + { // found existing entry + Reference<deployment::XPackage> xPackage( insertion.first->second ); + if (xPackage.is()) + return xPackage; + insertion.first->second = xNewPackage; + } + + guard.clear(); + xNewPackage->addEventListener( this ); // listen for disposing events + return xNewPackage; +} + +OUString PackageRegistryBackend::createFolder( + OUString const & relUrl, + Reference<ucb::XCommandEnvironment> const & xCmdEnv) +{ + OUString sDataFolder = makeURL(getCachePath(), relUrl); + //make sure the folder exist + ucbhelper::Content dataContent; + ::dp_misc::create_folder(&dataContent, sDataFolder, xCmdEnv); + + OUString sDataFolderURL = dp_misc::expandUnoRcUrl(sDataFolder); + + OUString tempEntry; + if (::osl::File::createTempFile( + &sDataFolderURL, 0, &tempEntry ) != ::osl::File::E_None) + throw RuntimeException( + OUSTR("::osl::File::createTempFile() failed!"), 0 ); + tempEntry = tempEntry.copy( tempEntry.lastIndexOf( '/' ) + 1 ); + OUString destFolder= makeURL(sDataFolder, tempEntry) + OUSTR("_"); + ::ucbhelper::Content destFolderContent; + dp_misc::create_folder( &destFolderContent, destFolder, xCmdEnv ); + + return destFolder; +} + +void PackageRegistryBackend::deleteTempFolder( + OUString const & folderUrl) +{ + OSL_ASSERT(folderUrl.getLength() + && folderUrl[folderUrl.getLength() - 1] == '_'); + if (folderUrl.getLength() + && folderUrl[folderUrl.getLength() - 1] == '_') + { + const OUString tempFile = folderUrl.copy(0, folderUrl.getLength() - 1); + erase_path( folderUrl, Reference<XCommandEnvironment>(), + false /* no throw: ignore errors */ ); + erase_path( tempFile, Reference<XCommandEnvironment>(), + false /* no throw: ignore errors */ ); + } +} + +void PackageRegistryBackend::deleteUnusedFolders( + OUString const & relUrl, + ::std::list< OUString> const & usedFolders) +{ + try + { + const OUString sDataFolder = makeURL(getCachePath(), relUrl); + ::ucbhelper::Content tempFolder( + sDataFolder, Reference<ucb::XCommandEnvironment>()); + Reference<sdbc::XResultSet> xResultSet( + tempFolder.createCursor( + Sequence<OUString>( &StrTitle::get(), 1 ), + ::ucbhelper::INCLUDE_DOCUMENTS_ONLY ) ); + // get all temp directories: + ::std::vector<OUString> tempEntries; + + char tmp[] = ".tmp"; + + while (xResultSet->next()) + { + OUString title( + Reference<sdbc::XRow>( + xResultSet, UNO_QUERY_THROW )->getString( + 1 /* Title */ ) ); + + if (title.endsWithAsciiL(tmp, sizeof(tmp) - 1)) + tempEntries.push_back( + makeURLAppendSysPathSegment(sDataFolder, title)); + } + + for ( ::std::size_t pos = 0; pos < tempEntries.size(); ++pos ) + { + //usedFolders contains the urls to the folders which have + //a trailing underscore + const OUString tempFolderName = tempEntries[ pos ] + OUSTR("_"); + + if (::std::find( usedFolders.begin(), usedFolders.end(), tempFolderName ) == + usedFolders.end()) + { + deleteTempFolder(tempFolderName); + } + } + } + catch (ucb::InteractiveAugmentedIOException& e) + { + //In case the folder containing all the data folder does not + //exist yet, we ignore the exception + if (e.Code != ucb::IOErrorCode_NOT_EXISTING) + throw e; + } + +} + +//############################################################################## + +//______________________________________________________________________________ +Package::~Package() +{ +} + +//______________________________________________________________________________ +Package::Package( ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, + OUString const & rName, + OUString const & displayName, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool bRemoved, + OUString const & identifier) + : t_PackageBase( getMutex() ), + m_myBackend( myBackend ), + m_url( url ), + m_name( rName ), + m_displayName( displayName ), + m_xPackageType( xPackageType ), + m_bRemoved(bRemoved), + m_identifier(identifier) +{ + if (m_bRemoved) + { + //We use the last segment of the URL + OSL_ASSERT(m_name.getLength() == 0); + OUString name = m_url; + rtl::Bootstrap::expandMacros(name); + sal_Int32 index = name.lastIndexOf('/'); + if (index != -1 && index < name.getLength()) + m_name = name.copy(index + 1); + } +} + +//______________________________________________________________________________ +void Package::disposing() +{ + m_myBackend.clear(); + WeakComponentImplHelperBase::disposing(); +} + +//______________________________________________________________________________ +void Package::check() const +{ + ::osl::MutexGuard guard( getMutex() ); + if (rBHelper.bInDispose || rBHelper.bDisposed) { + throw lang::DisposedException( + OUSTR("Package instance has already been disposed!"), + static_cast<OWeakObject *>(const_cast<Package *>(this))); + } +} + +// XComponent +//______________________________________________________________________________ +void Package::dispose() throw (RuntimeException) +{ + check(); + WeakComponentImplHelperBase::dispose(); +} + +//______________________________________________________________________________ +void Package::addEventListener( + Reference<lang::XEventListener> const & xListener ) throw (RuntimeException) +{ + check(); + WeakComponentImplHelperBase::addEventListener( xListener ); +} + +//______________________________________________________________________________ +void Package::removeEventListener( + Reference<lang::XEventListener> const & xListener ) throw (RuntimeException) +{ + check(); + WeakComponentImplHelperBase::removeEventListener( xListener ); +} + +// XModifyBroadcaster +//______________________________________________________________________________ +void Package::addModifyListener( + Reference<util::XModifyListener> const & xListener ) + throw (RuntimeException) +{ + check(); + rBHelper.addListener( ::getCppuType( &xListener ), xListener ); +} + +//______________________________________________________________________________ +void Package::removeModifyListener( + Reference<util::XModifyListener> const & xListener ) + throw (RuntimeException) +{ + check(); + rBHelper.removeListener( ::getCppuType( &xListener ), xListener ); +} + +//______________________________________________________________________________ +void Package::checkAborted( + ::rtl::Reference<AbortChannel> const & abortChannel ) +{ + if (abortChannel.is() && abortChannel->isAborted()) { + throw CommandAbortedException( + OUSTR("abort!"), static_cast<OWeakObject *>(this) ); + } +} + +// XPackage +//______________________________________________________________________________ +Reference<task::XAbortChannel> Package::createAbortChannel() + throw (RuntimeException) +{ + check(); + return new AbortChannel; +} + +//______________________________________________________________________________ +sal_Bool Package::isBundle() throw (RuntimeException) +{ + return false; // default +} + +//______________________________________________________________________________ +::sal_Int32 Package::checkPrerequisites( + const css::uno::Reference< css::task::XAbortChannel >&, + const css::uno::Reference< css::ucb::XCommandEnvironment >&, + sal_Bool) + throw (css::deployment::DeploymentException, + css::deployment::ExtensionRemovedException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::uno::RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return 0; +} + +//______________________________________________________________________________ +::sal_Bool Package::checkDependencies( + const css::uno::Reference< css::ucb::XCommandEnvironment >& ) + throw (css::deployment::DeploymentException, + css::deployment::ExtensionRemovedException, + css::ucb::CommandFailedException, + css::uno::RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return true; +} + + +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackage> > Package::getBundle( + Reference<task::XAbortChannel> const &, + Reference<XCommandEnvironment> const & ) + throw (deployment::DeploymentException, + CommandFailedException, CommandAbortedException, + lang::IllegalArgumentException, RuntimeException) +{ + return Sequence< Reference<deployment::XPackage> >(); +} + +//______________________________________________________________________________ +OUString Package::getName() throw (RuntimeException) +{ + return m_name; +} + +beans::Optional<OUString> Package::getIdentifier() throw (RuntimeException) +{ + if (m_bRemoved) + return beans::Optional<OUString>(true, m_identifier); + + return beans::Optional<OUString>(); +} + +//______________________________________________________________________________ +OUString Package::getVersion() throw ( + deployment::ExtensionRemovedException, + RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return OUString(); +} + +//______________________________________________________________________________ +OUString Package::getURL() throw (RuntimeException) +{ + return m_url; +} + +//______________________________________________________________________________ +OUString Package::getDisplayName() throw ( + deployment::ExtensionRemovedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return m_displayName; +} + +//______________________________________________________________________________ +OUString Package::getDescription() throw ( + deployment::ExtensionRemovedException,RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return OUString(); +} + +//______________________________________________________________________________ +Sequence<OUString> Package::getUpdateInformationURLs() throw ( + deployment::ExtensionRemovedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return Sequence<OUString>(); +} + +//______________________________________________________________________________ +css::beans::StringPair Package::getPublisherInfo() throw ( + deployment::ExtensionRemovedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + css::beans::StringPair aEmptyPair; + return aEmptyPair; +} + +//______________________________________________________________________________ +uno::Reference< css::graphic::XGraphic > Package::getIcon( sal_Bool /*bHighContrast*/ ) + throw (deployment::ExtensionRemovedException, RuntimeException ) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + + uno::Reference< css::graphic::XGraphic > aEmpty; + return aEmpty; +} + +//______________________________________________________________________________ +Reference<deployment::XPackageTypeInfo> Package::getPackageType() + throw (RuntimeException) +{ + return m_xPackageType; +} + +//______________________________________________________________________________ +void Package::exportTo( + OUString const & destFolderURL, OUString const & newTitle, + sal_Int32 nameClashAction, Reference<XCommandEnvironment> const & xCmdEnv ) + throw (deployment::ExtensionRemovedException, + CommandFailedException, CommandAbortedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + + ::ucbhelper::Content destFolder( destFolderURL, xCmdEnv ); + ::ucbhelper::Content sourceContent( getURL(), xCmdEnv ); + if (! destFolder.transferContent( + sourceContent, ::ucbhelper::InsertOperation_COPY, + newTitle, nameClashAction )) + throw RuntimeException( OUSTR("UCB transferContent() failed!"), 0 ); +} + +//______________________________________________________________________________ +void Package::fireModified() +{ + ::cppu::OInterfaceContainerHelper * container = rBHelper.getContainer( + ::getCppuType( static_cast<Reference< + util::XModifyListener> const *>(0) ) ); + if (container != 0) { + Sequence< Reference<XInterface> > elements( + container->getElements() ); + lang::EventObject evt( static_cast<OWeakObject *>(this) ); + for ( sal_Int32 pos = 0; pos < elements.getLength(); ++pos ) + { + Reference<util::XModifyListener> xListener( + elements[ pos ], UNO_QUERY ); + if (xListener.is()) + xListener->modified( evt ); + } + } +} + +// XPackage +//______________________________________________________________________________ +beans::Optional< beans::Ambiguous<sal_Bool> > Package::isRegistered( + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ) + throw (deployment::DeploymentException, + CommandFailedException, CommandAbortedException, RuntimeException) +{ + try { + ::osl::ResettableMutexGuard guard( getMutex() ); + return isRegistered_( guard, + AbortChannel::get(xAbortChannel), + xCmdEnv ); + } + catch (RuntimeException &) { + throw; + } + catch (CommandFailedException &) { + throw; + } + catch (CommandAbortedException &) { + throw; + } + catch (deployment::DeploymentException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + throw deployment::DeploymentException( + OUSTR("unexpected exception occured!"), + static_cast<OWeakObject *>(this), exc ); + } +} + +//______________________________________________________________________________ +void Package::processPackage_impl( + bool doRegisterPackage, + bool startup, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + check(); + bool action = false; + + try { + try { + ::osl::ResettableMutexGuard guard( getMutex() ); + beans::Optional< beans::Ambiguous<sal_Bool> > option( + isRegistered_( guard, AbortChannel::get(xAbortChannel), + xCmdEnv ) ); + action = (option.IsPresent && + (option.Value.IsAmbiguous || + (doRegisterPackage ? !option.Value.Value + : option.Value.Value))); + if (action) { + + OUString displayName = isRemoved() ? getName() : getDisplayName(); + ProgressLevel progress( + xCmdEnv, + (doRegisterPackage + ? PackageRegistryBackend::StrRegisteringPackage::get() + : PackageRegistryBackend::StrRevokingPackage::get()) + + displayName ); + processPackage_( guard, + doRegisterPackage, + startup, + AbortChannel::get(xAbortChannel), + xCmdEnv ); + } + } + catch (RuntimeException &) { + OSL_ENSURE( 0, "### unexpected RuntimeException!" ); + throw; + } + catch (CommandFailedException &) { + throw; + } + catch (CommandAbortedException &) { + throw; + } + catch (deployment::DeploymentException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + throw deployment::DeploymentException( + (doRegisterPackage + ? getResourceString(RID_STR_ERROR_WHILE_REGISTERING) + : getResourceString(RID_STR_ERROR_WHILE_REVOKING)) + + getDisplayName(), static_cast<OWeakObject *>(this), exc ); + } + } + catch (...) { + if (action) + fireModified(); + throw; + } + if (action) + fireModified(); +} + +//______________________________________________________________________________ +void Package::registerPackage( + sal_Bool startup, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ) + throw (deployment::DeploymentException, + deployment::ExtensionRemovedException, + CommandFailedException, CommandAbortedException, + lang::IllegalArgumentException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + processPackage_impl( true /* register */, startup, xAbortChannel, xCmdEnv ); +} + +//______________________________________________________________________________ +void Package::revokePackage( + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ) + throw (deployment::DeploymentException, + CommandFailedException, CommandAbortedException, + lang::IllegalArgumentException, RuntimeException) +{ + processPackage_impl( false /* revoke */, false, xAbortChannel, xCmdEnv ); + +} + +PackageRegistryBackend * Package::getMyBackend() const +{ + PackageRegistryBackend * pBackend = m_myBackend.get(); + if (NULL == pBackend) + { + //May throw a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<Package *>(this))); + } + return pBackend; +} +OUString Package::getRepositoryName() + throw (RuntimeException) +{ + PackageRegistryBackend * backEnd = getMyBackend(); + return backEnd->getContext(); +} + +beans::Optional< OUString > Package::getRegistrationDataURL() + throw (deployment::ExtensionRemovedException, + css::uno::RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return beans::Optional<OUString>(); +} + +sal_Bool Package::isRemoved() + throw (RuntimeException) +{ + return m_bRemoved; +} + +//############################################################################## + +//______________________________________________________________________________ +Package::TypeInfo::~TypeInfo() +{ +} + +// XPackageTypeInfo +//______________________________________________________________________________ +OUString Package::TypeInfo::getMediaType() throw (RuntimeException) +{ + return m_mediaType; +} + +//______________________________________________________________________________ +OUString Package::TypeInfo::getDescription() + throw (deployment::ExtensionRemovedException, RuntimeException) +{ + return getShortDescription(); +} + +//______________________________________________________________________________ +OUString Package::TypeInfo::getShortDescription() + throw (deployment::ExtensionRemovedException, RuntimeException) +{ + return m_shortDescr; +} + +//______________________________________________________________________________ +OUString Package::TypeInfo::getFileFilter() throw (RuntimeException) +{ + return m_fileFilter; +} + +//______________________________________________________________________________ +Any Package::TypeInfo::getIcon( sal_Bool highContrast, sal_Bool smallIcon ) + throw (RuntimeException) +{ + if (! smallIcon) + return Any(); + const sal_uInt16 nIconId = (highContrast ? m_smallIcon_HC : m_smallIcon); + return Any( &nIconId, getCppuType( static_cast<sal_uInt16 const *>(0) ) ); +} + +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/dp_backenddb.cxx b/desktop/source/deployment/registry/dp_backenddb.cxx new file mode 100644 index 000000000000..905ff6e95fd0 --- /dev/null +++ b/desktop/source/deployment/registry/dp_backenddb.cxx @@ -0,0 +1,651 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "rtl/string.h" +#include "rtl/strbuf.hxx" +#include "rtl/bootstrap.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "osl/file.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "com/sun/star/io/XActiveDataSource.hpp" +#include "com/sun/star/io/XActiveDataControl.hpp" +#include "dp_ucb.h" +#include "dp_misc.h" +#include "ucbhelper/content.hxx" +#include "xmlscript/xml_helper.hxx" +#include "dp_backenddb.hxx" + + +namespace css = ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + + +namespace dp_registry { +namespace backend { + +BackendDb::BackendDb( + Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url): + m_xContext(xContext) +{ + m_urlDb = dp_misc::expandUnoRcUrl(url); +} + +void BackendDb::save() +{ + const Reference<css::io::XActiveDataSource> xDataSource(m_doc,css::uno::UNO_QUERY_THROW); + ::rtl::ByteSequence bytes; + xDataSource->setOutputStream(::xmlscript::createOutputStream(&bytes)); + const Reference<css::io::XActiveDataControl> xDataControl(m_doc,css::uno::UNO_QUERY_THROW); + xDataControl->start(); + + const Reference<css::io::XInputStream> xData( + ::xmlscript::createInputStream(bytes)); + ::ucbhelper::Content ucbDb(m_urlDb, 0); + ucbDb.writeStream(xData, true /*replace existing*/); +} + +css::uno::Reference<css::xml::dom::XDocument> BackendDb::getDocument() +{ + if (!m_doc.is()) + { + const Reference<css::xml::dom::XDocumentBuilder> xDocBuilder( + m_xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.xml.dom.DocumentBuilder"), + m_xContext ), css::uno::UNO_QUERY); + if (!xDocBuilder.is()) + throw css::uno::RuntimeException( + OUSTR(" Could not create service com.sun.star.xml.dom.DocumentBuilder"), 0); + + ::osl::DirectoryItem item; + ::osl::File::RC err = ::osl::DirectoryItem::get(m_urlDb, item); + if (err == ::osl::File::E_None) + { + m_doc = xDocBuilder->parseURI(m_urlDb); + } + else if (err == ::osl::File::E_NOENT) + { + //Create a new document and insert some basic stuff + m_doc = xDocBuilder->newDocument(); + const Reference<css::xml::dom::XElement> rootNode = + m_doc->createElementNS(getDbNSName(), getNSPrefix() + + OUSTR(":") + getRootElementName()); + + m_doc->appendChild(Reference<css::xml::dom::XNode>( + rootNode, UNO_QUERY_THROW)); + save(); + } + else + throw css::uno::RuntimeException( + OUSTR("Extension manager could not access database file:" ) + + m_urlDb, 0); + + if (!m_doc.is()) + throw css::uno::RuntimeException( + OUSTR("Extension manager could not get root node of data base file: ") + + m_urlDb, 0); + } + + return m_doc; +} + +Reference<css::xml::xpath::XXPathAPI> BackendDb::getXPathAPI() +{ + if (!m_xpathApi.is()) + { + m_xpathApi = Reference< css::xml::xpath::XXPathAPI >( + m_xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.xml.xpath.XPathAPI"), + m_xContext), css::uno::UNO_QUERY); + + if (!m_xpathApi.is()) + throw css::uno::RuntimeException( + OUSTR(" Could not create service com.sun.star.xml.xpath.XPathAPI"), 0); + + m_xpathApi->registerNS( + getNSPrefix(), getDbNSName()); + } + + return m_xpathApi; +} + +void BackendDb::removeElement(::rtl::OUString const & sXPathExpression) +{ + try + { + const Reference<css::xml::dom::XDocument> doc = getDocument(); + const Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + const Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + //find the extension element that is to be removed + const Reference<css::xml::dom::XNode> aNode = + xpathApi->selectSingleNode(root, sXPathExpression); + + if (aNode.is()) + { + root->removeChild(aNode); + save(); + } + +#if OSL_DEBUG_LEVEL > 0 + //There must not be any other entry with the same url + const Reference<css::xml::dom::XNode> nextNode = + xpathApi->selectSingleNode(root, sXPathExpression); + OSL_ASSERT(! nextNode.is()); +#endif + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +void BackendDb::removeEntry(::rtl::OUString const & url) +{ + const OUString sKeyElement = getKeyElementName(); + const OUString sPrefix = getNSPrefix(); + ::rtl::OUStringBuffer sExpression(500); + sExpression.append(sPrefix); + sExpression.appendAscii(":"); + sExpression.append(sKeyElement); + sExpression.append(OUSTR("[@url = \"")); + sExpression.append(url); + sExpression.appendAscii("\"]"); + + removeElement(sExpression.makeStringAndClear()); +} + +Reference<css::xml::dom::XNode> BackendDb::getKeyElement( + ::rtl::OUString const & url) +{ + try + { + const OUString sPrefix = getNSPrefix(); + const OUString sKeyElement = getKeyElementName(); + ::rtl::OUStringBuffer sExpression(500); + sExpression.append(sPrefix); + sExpression.appendAscii(":"); + sExpression.append(sKeyElement); + sExpression.append(OUSTR("[@url = \"")); + sExpression.append(url); + sExpression.appendAscii("\"]"); + + const Reference<css::xml::dom::XDocument> doc = getDocument(); + const Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + const Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + return xpathApi->selectSingleNode(root, sExpression.makeStringAndClear()); + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read key element in backend db: ") + + m_urlDb, 0, exc); + } +} + +//Only writes the data if there is at least one entry +void BackendDb::writeVectorOfPair( + ::std::vector< ::std::pair< ::rtl::OUString, ::rtl::OUString > > const & vecPairs, + OUString const & sVectorTagName, + OUString const & sPairTagName, + OUString const & sFirstTagName, + OUString const & sSecondTagName, + css::uno::Reference<css::xml::dom::XNode> const & xParent) +{ + try{ + if (vecPairs.size() == 0) + return; + const OUString sNameSpace = getDbNSName(); + OSL_ASSERT(sNameSpace.getLength()); + const OUString sPrefix(getNSPrefix() + OUSTR(":")); + const Reference<css::xml::dom::XDocument> doc = getDocument(); + const Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + + const Reference<css::xml::dom::XElement> vectorNode( + doc->createElementNS(sNameSpace, sPrefix + sVectorTagName)); + + xParent->appendChild( + Reference<css::xml::dom::XNode>( + vectorNode, css::uno::UNO_QUERY_THROW)); + typedef ::std::vector< ::std::pair< OUString, OUString > >::const_iterator CIT; + for (CIT i = vecPairs.begin(); i != vecPairs.end(); i++) + { + const Reference<css::xml::dom::XElement> pairNode( + doc->createElementNS(sNameSpace, sPrefix + sPairTagName)); + + vectorNode->appendChild( + Reference<css::xml::dom::XNode>( + pairNode, css::uno::UNO_QUERY_THROW)); + + const Reference<css::xml::dom::XElement> firstNode( + doc->createElementNS(sNameSpace, sPrefix + sFirstTagName)); + + pairNode->appendChild( + Reference<css::xml::dom::XNode>( + firstNode, css::uno::UNO_QUERY_THROW)); + + const Reference<css::xml::dom::XText> firstTextNode( + doc->createTextNode( i->first)); + + firstNode->appendChild( + Reference<css::xml::dom::XNode>( + firstTextNode, css::uno::UNO_QUERY_THROW)); + + const Reference<css::xml::dom::XElement> secondNode( + doc->createElementNS(sNameSpace, sPrefix + sSecondTagName)); + + pairNode->appendChild( + Reference<css::xml::dom::XNode>( + secondNode, css::uno::UNO_QUERY_THROW)); + + const Reference<css::xml::dom::XText> secondTextNode( + doc->createTextNode( i->second)); + + secondNode->appendChild( + Reference<css::xml::dom::XNode>( + secondTextNode, css::uno::UNO_QUERY_THROW)); + } + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +::std::vector< ::std::pair< OUString, OUString > > +BackendDb::readVectorOfPair( + Reference<css::xml::dom::XNode> const & parent, + OUString const & sListTagName, + OUString const & sPairTagName, + OUString const & sFirstTagName, + OUString const & sSecondTagName) +{ + try + { + OSL_ASSERT(parent.is()); + const OUString sPrefix(getNSPrefix() + OUSTR(":")); + const Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + const OUString sExprPairs( + sPrefix + sListTagName + OUSTR("/") + sPrefix + sPairTagName); + const Reference<css::xml::dom::XNodeList> listPairs = + xpathApi->selectNodeList(parent, sExprPairs); + + ::std::vector< ::std::pair< OUString, OUString > > retVector; + sal_Int32 length = listPairs->getLength(); + for (sal_Int32 i = 0; i < length; i++) + { + const Reference<css::xml::dom::XNode> aPair = listPairs->item(i); + const OUString sExprFirst(sPrefix + sFirstTagName + OUSTR("/text()")); + const Reference<css::xml::dom::XNode> first = + xpathApi->selectSingleNode(aPair, sExprFirst); + + const OUString sExprSecond(sPrefix + sSecondTagName + OUSTR("/text()")); + const Reference<css::xml::dom::XNode> second = + xpathApi->selectSingleNode(aPair, sExprSecond); + OSL_ASSERT(first.is() && second.is()); + + retVector.push_back(::std::make_pair( + first->getNodeValue(), second->getNodeValue())); + } + return retVector; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +//Only writes the data if there is at least one entry +void BackendDb::writeSimpleList( + ::std::list< ::rtl::OUString> const & list, + OUString const & sListTagName, + OUString const & sMemberTagName, + Reference<css::xml::dom::XNode> const & xParent) +{ + try + { + if (list.size() == 0) + return; + const OUString sNameSpace = getDbNSName(); + const OUString sPrefix(getNSPrefix() + OUSTR(":")); + const Reference<css::xml::dom::XDocument> doc = getDocument(); + + const Reference<css::xml::dom::XElement> listNode( + doc->createElementNS(sNameSpace, sPrefix + sListTagName)); + + xParent->appendChild( + Reference<css::xml::dom::XNode>( + listNode, css::uno::UNO_QUERY_THROW)); + + typedef ::std::list<OUString>::const_iterator ITC_ITEMS; + for (ITC_ITEMS i = list.begin(); i != list.end(); i++) + { + const Reference<css::xml::dom::XNode> memberNode( + doc->createElementNS(sNameSpace, sPrefix + sMemberTagName), css::uno::UNO_QUERY_THROW); + + listNode->appendChild(memberNode); + + const Reference<css::xml::dom::XNode> textNode( + doc->createTextNode( *i), css::uno::UNO_QUERY_THROW); + + memberNode->appendChild(textNode); + } + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +//Writes only the element if is has a value. +//The prefix is automatically added to the element name +void BackendDb::writeSimpleElement( + OUString const & sElementName, OUString const & value, + Reference<css::xml::dom::XNode> const & xParent) +{ + try + { + if (value.getLength() == 0) + return; + const OUString sPrefix = getNSPrefix(); + const Reference<css::xml::dom::XDocument> doc = getDocument(); + const OUString sNameSpace = getDbNSName(); + const Reference<css::xml::dom::XNode> dataNode( + doc->createElementNS(sNameSpace, sPrefix + OUSTR(":") + sElementName), + UNO_QUERY_THROW); + xParent->appendChild(dataNode); + + const Reference<css::xml::dom::XNode> dataValue( + doc->createTextNode(value), UNO_QUERY_THROW); + dataNode->appendChild(dataValue); + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry(writeSimpleElement) in backend db: ") + + m_urlDb, 0, exc); + } + +} + +/** The key elements have an url attribute and are always children of the root + element. +*/ +Reference<css::xml::dom::XNode> BackendDb::writeKeyElement( + ::rtl::OUString const & url) +{ + try + { + const OUString sNameSpace = getDbNSName(); + const OUString sPrefix = getNSPrefix(); + const OUString sElementName = getKeyElementName(); + const Reference<css::xml::dom::XDocument> doc = getDocument(); + const Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + + //Check if there are an entry with the same url. This can be the case if the + //the status of an XPackage is ambiguous. In this case a call to activateExtension + //(dp_extensionmanager.cxx), will register the package again. See also + //Package::processPackage_impl in dp_backend.cxx. + //A package can become + //invalid after its successful registration, for example if a second extension with + //the same service is installed. + const OUString sExpression( + sPrefix + OUSTR(":") + sElementName + OUSTR("[@url = \"") + url + OUSTR("\"]")); + const Reference<css::xml::dom::XNode> existingNode = + getXPathAPI()->selectSingleNode(root, sExpression); + if (existingNode.is()) + { + OSL_ASSERT(0); + //replace the existing entry. + removeEntry(url); + } + + const Reference<css::xml::dom::XElement> keyElement( + doc->createElementNS(sNameSpace, sPrefix + OUSTR(":") + sElementName)); + + keyElement->setAttribute(OUSTR("url"), url); + + const Reference<css::xml::dom::XNode> keyNode( + keyElement, UNO_QUERY_THROW); + root->appendChild(keyNode); + return keyNode; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write key element in backend db: ") + + m_urlDb, 0, exc); + } +} + +OUString BackendDb::readSimpleElement( + OUString const & sElementName, Reference<css::xml::dom::XNode> const & xParent) +{ + try + { + const OUString sPrefix = getNSPrefix(); + const OUString sExpr(sPrefix + OUSTR(":") + sElementName + OUSTR("/text()")); + const Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + const Reference<css::xml::dom::XNode> val = + xpathApi->selectSingleNode(xParent, sExpr); + if (val.is()) + return val->getNodeValue(); + return OUString(); + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data (readSimpleElement) in backend db: ") + + m_urlDb, 0, exc); + } +} + + +::std::list< OUString> BackendDb::readList( + Reference<css::xml::dom::XNode> const & parent, + OUString const & sListTagName, + OUString const & sMemberTagName) +{ + try + { + OSL_ASSERT(parent.is()); + const OUString sPrefix(getNSPrefix() + OUSTR(":")); + const Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + const OUString sExprList( + sPrefix + sListTagName + OUSTR("/") + sPrefix + sMemberTagName + OUSTR("/text()")); + const Reference<css::xml::dom::XNodeList> list = + xpathApi->selectNodeList(parent, sExprList); + + ::std::list<OUString > retList; + sal_Int32 length = list->getLength(); + for (sal_Int32 i = 0; i < length; i++) + { + const Reference<css::xml::dom::XNode> member = list->item(i); + retList.push_back(member->getNodeValue()); + } + return retList; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +::std::list<OUString> BackendDb::getOneChildFromAllEntries( + OUString const & name) +{ + try + { + ::std::list<OUString> listRet; + Reference<css::xml::dom::XDocument> doc = getDocument(); + Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + + Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + const OUString sPrefix = getNSPrefix(); + const OUString sKeyElement = getKeyElementName(); + ::rtl::OUStringBuffer buf(512); + buf.append(sPrefix); + buf.appendAscii(":"); + buf.append(sKeyElement); + buf.appendAscii("/"); + buf.append(sPrefix); + buf.appendAscii(":"); + buf.append(name); + buf.append(OUSTR("/text()")); + + Reference<css::xml::dom::XNodeList> nodes = + xpathApi->selectNodeList(root, buf.makeStringAndClear()); + if (nodes.is()) + { + sal_Int32 length = nodes->getLength(); + for (sal_Int32 i = 0; i < length; i++) + listRet.push_back(nodes->item(i)->getNodeValue()); + } + return listRet; + } + catch (css::deployment::DeploymentException& ) + { + throw; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + + + +//================================================================================ +RegisteredDb::RegisteredDb( + Reference<XComponentContext> const & xContext, + ::rtl::OUString const & url):BackendDb(xContext, url) +{ + +} + +void RegisteredDb::addEntry(::rtl::OUString const & url) +{ + try{ + + const OUString sNameSpace = getDbNSName(); + const OUString sPrefix = getNSPrefix(); + const OUString sEntry = getKeyElementName(); + + Reference<css::xml::dom::XDocument> doc = getDocument(); + Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + +#if OSL_DEBUG_LEVEL > 0 + //There must not be yet an entry with the same url + OUString sExpression( + sPrefix + OUSTR(":") + sEntry + OUSTR("[@url = \"") + url + OUSTR("\"]")); + Reference<css::xml::dom::XNode> _extensionNode = + getXPathAPI()->selectSingleNode(root, sExpression); + OSL_ASSERT(! _extensionNode.is()); +#endif + Reference<css::xml::dom::XElement> helpElement( + doc->createElementNS(sNameSpace, sPrefix + OUSTR(":") + sEntry)); + + helpElement->setAttribute(OUSTR("url"), url); + + Reference<css::xml::dom::XNode> helpNode( + helpElement, UNO_QUERY_THROW); + root->appendChild(helpNode); + + save(); + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +bool RegisteredDb::getEntry(::rtl::OUString const & url) +{ + try + { + const OUString sPrefix = getNSPrefix(); + const OUString sEntry = getKeyElementName(); + const OUString sExpression( + sPrefix + OUSTR(":") + sEntry + OUSTR("[@url = \"") + url + OUSTR("\"]")); + Reference<css::xml::dom::XDocument> doc = getDocument(); + Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + + Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + //find the extension element that is to be removed + Reference<css::xml::dom::XNode> aNode = + xpathApi->selectSingleNode(root, sExpression); + if (!aNode.is()) + { + return false; + } + return true; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + + +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/dp_registry.cxx b/desktop/source/deployment/registry/dp_registry.cxx new file mode 100644 index 000000000000..a90f64b9cb39 --- /dev/null +++ b/desktop/source/deployment/registry/dp_registry.cxx @@ -0,0 +1,560 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_registry.hrc" +#include "dp_misc.h" +#include "dp_resource.h" +#include "dp_interact.h" +#include "dp_ucb.h" +#include "osl/diagnose.h" +#include "rtl/ustrbuf.hxx" +#include "rtl/uri.hxx" +#include "cppuhelper/compbase2.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "comphelper/sequence.hxx" +#include "ucbhelper/content.hxx" +#include "com/sun/star/uno/DeploymentException.hpp" +#include "com/sun/star/lang/DisposedException.hpp" +#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XSingleComponentFactory.hpp" +#include "com/sun/star/lang/XSingleServiceFactory.hpp" +#include "com/sun/star/util/XUpdatable.hpp" +#include "com/sun/star/container/XContentEnumerationAccess.hpp" +#include "com/sun/star/deployment/PackageRegistryBackend.hpp" +#include <hash_map> +#include <set> +#include <hash_set> +#include <memory> + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; + + +namespace dp_registry { + +namespace backend { +namespace bundle { +Reference<deployment::XPackageRegistry> create( + Reference<deployment::XPackageRegistry> const & xRootRegistry, + OUString const & context, OUString const & cachePath, bool readOnly, + Reference<XComponentContext> const & xComponentContext ); +} +} + +namespace { + +typedef ::cppu::WeakComponentImplHelper2< + deployment::XPackageRegistry, util::XUpdatable > t_helper; + +//============================================================================== +class PackageRegistryImpl : private MutexHolder, public t_helper +{ + struct ci_string_hash { + ::std::size_t operator () ( OUString const & str ) const { + return str.toAsciiLowerCase().hashCode(); + } + }; + struct ci_string_equals { + bool operator () ( OUString const & str1, OUString const & str2 ) const{ + return str1.equalsIgnoreAsciiCase( str2 ); + } + }; + typedef ::std::hash_map< + OUString, Reference<deployment::XPackageRegistry>, + ci_string_hash, ci_string_equals > t_string2registry; + typedef ::std::hash_map< + OUString, OUString, + ci_string_hash, ci_string_equals > t_string2string; + typedef ::std::set< + Reference<deployment::XPackageRegistry> > t_registryset; + + t_string2registry m_mediaType2backend; + t_string2string m_filter2mediaType; + t_registryset m_ambiguousBackends; + t_registryset m_allBackends; + ::std::vector< Reference<deployment::XPackageTypeInfo> > m_typesInfos; + + void insertBackend( + Reference<deployment::XPackageRegistry> const & xBackend ); + +protected: + inline void check(); + virtual void SAL_CALL disposing(); + + virtual ~PackageRegistryImpl(); + PackageRegistryImpl() : t_helper( getMutex() ) {} + + +public: + static Reference<deployment::XPackageRegistry> create( + OUString const & context, + OUString const & cachePath, bool readOnly, + Reference<XComponentContext> const & xComponentContext ); + + // XUpdatable + virtual void SAL_CALL update() throw (RuntimeException); + + // XPackageRegistry + virtual Reference<deployment::XPackage> SAL_CALL bindPackage( + OUString const & url, OUString const & mediaType, sal_Bool bRemoved, + OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv ) + throw (deployment::DeploymentException, + deployment::InvalidRemovedParameterException, + CommandFailedException, + lang::IllegalArgumentException, RuntimeException); + virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() throw (RuntimeException); +}; + +//______________________________________________________________________________ +inline void PackageRegistryImpl::check() +{ + ::osl::MutexGuard guard( getMutex() ); + if (rBHelper.bInDispose || rBHelper.bDisposed) { + throw lang::DisposedException( + OUSTR("PackageRegistry instance has already been disposed!"), + static_cast<OWeakObject *>(this) ); + } +} + +//______________________________________________________________________________ +void PackageRegistryImpl::disposing() +{ + // dispose all backends: + t_registryset::const_iterator iPos( m_allBackends.begin() ); + t_registryset::const_iterator const iEnd( m_allBackends.end() ); + for ( ; iPos != iEnd; ++iPos ) { + try_dispose( *iPos ); + } + m_mediaType2backend = t_string2registry(); + m_ambiguousBackends = t_registryset(); + m_allBackends = t_registryset(); + + t_helper::disposing(); +} + +//______________________________________________________________________________ +PackageRegistryImpl::~PackageRegistryImpl() +{ +} + +//______________________________________________________________________________ +OUString normalizeMediaType( OUString const & mediaType ) +{ + ::rtl::OUStringBuffer buf; + sal_Int32 index = 0; + for (;;) { + buf.append( mediaType.getToken( 0, '/', index ).trim() ); + if (index < 0) + break; + buf.append( static_cast< sal_Unicode >('/') ); + } + return buf.makeStringAndClear(); +} + +//______________________________________________________________________________ + +void PackageRegistryImpl::insertBackend( + Reference<deployment::XPackageRegistry> const & xBackend ) +{ + m_allBackends.insert( xBackend ); + typedef ::std::hash_set<OUString, ::rtl::OUStringHash> t_stringset; + t_stringset ambiguousFilters; + + const Sequence< Reference<deployment::XPackageTypeInfo> > packageTypes( + xBackend->getSupportedPackageTypes() ); + for ( sal_Int32 pos = 0; pos < packageTypes.getLength(); ++pos ) + { + Reference<deployment::XPackageTypeInfo> const & xPackageType = + packageTypes[ pos ]; + m_typesInfos.push_back( xPackageType ); + + const OUString mediaType( normalizeMediaType( + xPackageType->getMediaType() ) ); + ::std::pair<t_string2registry::iterator, bool> mb_insertion( + m_mediaType2backend.insert( t_string2registry::value_type( + mediaType, xBackend ) ) ); + if (mb_insertion.second) + { + // add parameterless media-type, too: + sal_Int32 semi = mediaType.indexOf( ';' ); + if (semi >= 0) { + m_mediaType2backend.insert( + t_string2registry::value_type( + mediaType.copy( 0, semi ), xBackend ) ); + } + const OUString fileFilter( xPackageType->getFileFilter() ); + //The package backend shall also be called to determine the mediatype + //(XPackageRegistry.bindPackage) when the URL points to a directory. + const bool bExtension = mediaType.equals(OUSTR("application/vnd.sun.star.package-bundle")); + if (fileFilter.getLength() == 0 || + fileFilter.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("*.*") ) || + fileFilter.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("*") ) || + bExtension) + { + m_ambiguousBackends.insert( xBackend ); + } + else + { + sal_Int32 nIndex = 0; + do { + OUString token( fileFilter.getToken( 0, ';', nIndex ) ); + if (token.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("*.") )) + token = token.copy( 1 ); + if (token.getLength() == 0) + continue; + // mark any further wildcards ambig: + bool ambig = (token.indexOf('*') >= 0 || + token.indexOf('?') >= 0); + if (! ambig) { + ::std::pair<t_string2string::iterator, bool> ins( + m_filter2mediaType.insert( + t_string2string::value_type( + token, mediaType ) ) ); + ambig = !ins.second; + if (ambig) { + // filter has already been in: add previously + // added backend to ambig set + const t_string2registry::const_iterator iFind( + m_mediaType2backend.find( + /* media-type of pr. added backend */ + ins.first->second ) ); + OSL_ASSERT( + iFind != m_mediaType2backend.end() ); + if (iFind != m_mediaType2backend.end()) + m_ambiguousBackends.insert( iFind->second ); + } + } + if (ambig) { + m_ambiguousBackends.insert( xBackend ); + // mark filter to be removed later from filters map: + ambiguousFilters.insert( token ); + } + } + while (nIndex >= 0); + } + } +#if OSL_DEBUG_LEVEL > 0 + else { + ::rtl::OUStringBuffer buf; + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM( + "more than one PackageRegistryBackend for " + "media-type=\"") ); + buf.append( mediaType ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" => ") ); + buf.append( Reference<lang::XServiceInfo>( + xBackend, UNO_QUERY_THROW )-> + getImplementationName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") ); + OSL_ENSURE( 0, ::rtl::OUStringToOString( + buf.makeStringAndClear(), + RTL_TEXTENCODING_UTF8 ) ); + } +#endif + } + + // cut out ambiguous filters: + t_stringset::const_iterator iPos( ambiguousFilters.begin() ); + const t_stringset::const_iterator iEnd( ambiguousFilters.end() ); + for ( ; iPos != iEnd; ++iPos ) { + m_filter2mediaType.erase( *iPos ); + } +} + +//______________________________________________________________________________ +Reference<deployment::XPackageRegistry> PackageRegistryImpl::create( + OUString const & context, + OUString const & cachePath, bool readOnly, + Reference<XComponentContext> const & xComponentContext ) +{ + PackageRegistryImpl * that = new PackageRegistryImpl; + Reference<deployment::XPackageRegistry> xRet(that); + + // auto-detect all registered package registries: + Reference<container::XEnumeration> xEnum( + Reference<container::XContentEnumerationAccess>( + xComponentContext->getServiceManager(), + UNO_QUERY_THROW )->createContentEnumeration( + OUSTR("com.sun.star.deployment.PackageRegistryBackend") ) ); + if (xEnum.is()) + { + while (xEnum->hasMoreElements()) + { + Any element( xEnum->nextElement() ); + Sequence<Any> registryArgs( + cachePath.getLength() == 0 ? 1 : 3 ); + registryArgs[ 0 ] <<= context; + if (cachePath.getLength() > 0) + { + Reference<lang::XServiceInfo> xServiceInfo( + element, UNO_QUERY_THROW ); + OUString registryCachePath( + makeURL( cachePath, + ::rtl::Uri::encode( + xServiceInfo->getImplementationName(), + rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ) ); + registryArgs[ 1 ] <<= registryCachePath; + registryArgs[ 2 ] <<= readOnly; + if (! readOnly) + create_folder( 0, registryCachePath, + Reference<XCommandEnvironment>() ); + } + + Reference<deployment::XPackageRegistry> xBackend; + Reference<lang::XSingleComponentFactory> xFac( element, UNO_QUERY ); + if (xFac.is()) { + xBackend.set( + xFac->createInstanceWithArgumentsAndContext( + registryArgs, xComponentContext ), UNO_QUERY ); + } + else { + Reference<lang::XSingleServiceFactory> xSingleServiceFac( + element, UNO_QUERY_THROW ); + xBackend.set( + xSingleServiceFac->createInstanceWithArguments( + registryArgs ), UNO_QUERY ); + } + if (! xBackend.is()) { + throw DeploymentException( + OUSTR("cannot instantiate PackageRegistryBackend service: ") + + Reference<lang::XServiceInfo>( + element, UNO_QUERY_THROW )->getImplementationName(), + static_cast<OWeakObject *>(that) ); + } + + that->insertBackend( xBackend ); + } + } + + // Insert bundle back-end. + // Always register as last, because we want to add extensions also as folders + // and as a default we accept every folder, which was not recognized by the other + // backends. + Reference<deployment::XPackageRegistry> extensionBackend = + ::dp_registry::backend::bundle::create( + that, context, cachePath, readOnly, xComponentContext); + that->insertBackend(extensionBackend); + + Reference<lang::XServiceInfo> xServiceInfo( + extensionBackend, UNO_QUERY_THROW ); + + OSL_ASSERT(xServiceInfo.is()); + OUString registryCachePath( + makeURL( cachePath, + ::rtl::Uri::encode( + xServiceInfo->getImplementationName(), + rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ) ); + create_folder( 0, registryCachePath, Reference<XCommandEnvironment>()); + + +#if OSL_DEBUG_LEVEL > 1 + // dump tables: + { + t_registryset allBackends; + dp_misc::TRACE("> [dp_registry.cxx] media-type detection:\n\n" ); + for ( t_string2string::const_iterator iPos( + that->m_filter2mediaType.begin() ); + iPos != that->m_filter2mediaType.end(); ++iPos ) + { + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("extension \"") ); + buf.append( iPos->first ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "\" maps to media-type \"") ); + buf.append( iPos->second ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "\" maps to backend ") ); + const Reference<deployment::XPackageRegistry> xBackend( + that->m_mediaType2backend.find( iPos->second )->second ); + allBackends.insert( xBackend ); + buf.append( Reference<lang::XServiceInfo>( + xBackend, UNO_QUERY_THROW ) + ->getImplementationName() ); + dp_misc::writeConsole( buf.makeStringAndClear() + OUSTR("\n")); + } + dp_misc::TRACE( "> [dp_registry.cxx] ambiguous backends:\n\n" ); + for ( t_registryset::const_iterator iPos( + that->m_ambiguousBackends.begin() ); + iPos != that->m_ambiguousBackends.end(); ++iPos ) + { + ::rtl::OUStringBuffer buf; + buf.append( + Reference<lang::XServiceInfo>( + *iPos, UNO_QUERY_THROW )->getImplementationName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") ); + const Sequence< Reference<deployment::XPackageTypeInfo> > types( + (*iPos)->getSupportedPackageTypes() ); + for ( sal_Int32 pos = 0; pos < types.getLength(); ++pos ) { + Reference<deployment::XPackageTypeInfo> const & xInfo = + types[ pos ]; + buf.append( xInfo->getMediaType() ); + const OUString filter( xInfo->getFileFilter() ); + if (filter.getLength() > 0) { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (") ); + buf.append( filter ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(")") ); + } + if (pos < (types.getLength() - 1)) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") ); + } + dp_misc::TRACE(buf.makeStringAndClear() + OUSTR("\n\n")); + } + allBackends.insert( that->m_ambiguousBackends.begin(), + that->m_ambiguousBackends.end() ); + OSL_ASSERT( allBackends == that->m_allBackends ); + } +#endif + + return xRet; +} + +// XUpdatable: broadcast to backends +//______________________________________________________________________________ +void PackageRegistryImpl::update() throw (RuntimeException) +{ + check(); + t_registryset::const_iterator iPos( m_allBackends.begin() ); + const t_registryset::const_iterator iEnd( m_allBackends.end() ); + for ( ; iPos != iEnd; ++iPos ) { + const Reference<util::XUpdatable> xUpdatable( *iPos, UNO_QUERY ); + if (xUpdatable.is()) + xUpdatable->update(); + } +} + +// XPackageRegistry +//______________________________________________________________________________ +Reference<deployment::XPackage> PackageRegistryImpl::bindPackage( + OUString const & url, OUString const & mediaType_, sal_Bool bRemoved, + OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv ) + throw (deployment::DeploymentException, deployment::InvalidRemovedParameterException, + CommandFailedException, + lang::IllegalArgumentException, RuntimeException) +{ + check(); + OUString mediaType(mediaType_); + if (mediaType.getLength() == 0) + { + ::ucbhelper::Content ucbContent; + if (create_ucb_content( + &ucbContent, url, xCmdEnv, false /* no throw */ ) + && !ucbContent.isFolder()) + { + OUString title( ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>() ); + for (;;) + { + const t_string2string::const_iterator iFind( + m_filter2mediaType.find(title) ); + if (iFind != m_filter2mediaType.end()) { + mediaType = iFind->second; + break; + } + sal_Int32 point = title.indexOf( '.', 1 /* consume . */ ); + if (point < 0) + break; + title = title.copy(point); + } + } + } + if (mediaType.getLength() == 0) + { + // try ambiguous backends: + t_registryset::const_iterator iPos( m_ambiguousBackends.begin() ); + const t_registryset::const_iterator iEnd( m_ambiguousBackends.end() ); + for ( ; iPos != iEnd; ++iPos ) + { + try { + return (*iPos)->bindPackage( url, mediaType, bRemoved, + identifier, xCmdEnv ); + } + catch (lang::IllegalArgumentException &) { + } + } + throw lang::IllegalArgumentException( + getResourceString(RID_STR_CANNOT_DETECT_MEDIA_TYPE) + url, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); + } + else + { + // get backend by media-type: + t_string2registry::const_iterator iFind( + m_mediaType2backend.find( normalizeMediaType(mediaType) ) ); + if (iFind == m_mediaType2backend.end()) { + // xxx todo: more sophisticated media-type argument parsing... + sal_Int32 q = mediaType.indexOf( ';' ); + if (q >= 0) { + iFind = m_mediaType2backend.find( + normalizeMediaType( + // cut parameters: + mediaType.copy( 0, q ) ) ); + } + } + if (iFind == m_mediaType2backend.end()) { + throw lang::IllegalArgumentException( + getResourceString(RID_STR_UNSUPPORTED_MEDIA_TYPE) + mediaType, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); + } + return iFind->second->bindPackage( url, mediaType, bRemoved, + identifier, xCmdEnv ); + } +} + +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackageTypeInfo> > +PackageRegistryImpl::getSupportedPackageTypes() throw (RuntimeException) +{ + return comphelper::containerToSequence(m_typesInfos); +} +} // anon namespace + +//============================================================================== +Reference<deployment::XPackageRegistry> SAL_CALL create( + OUString const & context, + OUString const & cachePath, bool readOnly, + Reference<XComponentContext> const & xComponentContext ) +{ + return PackageRegistryImpl::create( + context, cachePath, readOnly, xComponentContext ); +} + +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/dp_registry.src b/desktop/source/deployment/registry/dp_registry.src new file mode 100644 index 000000000000..1658e4bdcca2 --- /dev/null +++ b/desktop/source/deployment/registry/dp_registry.src @@ -0,0 +1,59 @@ +/************************************************************************* + * + * 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 "dp_registry.hrc" + +String RID_STR_REGISTERING_PACKAGE +{ + Text [ en-US ] = "Enabling: "; +}; + +String RID_STR_REVOKING_PACKAGE +{ + Text [ en-US ] = "Disabling: "; +}; + +String RID_STR_CANNOT_DETECT_MEDIA_TYPE +{ + Text [ en-US ] = "Cannot detect media-type: "; +}; + +String RID_STR_UNSUPPORTED_MEDIA_TYPE +{ + Text [ en-US ] = "This media-type is not supported: "; +}; + +String RID_STR_ERROR_WHILE_REGISTERING +{ + Text [ en-US ] = "An error occurred while enabling: "; +}; + +String RID_STR_ERROR_WHILE_REVOKING +{ + Text [ en-US ] = "An error occurred while disabling: "; +}; + diff --git a/desktop/source/deployment/registry/executable/dp_executable.cxx b/desktop/source/deployment/registry/executable/dp_executable.cxx new file mode 100644 index 000000000000..eb03c2246417 --- /dev/null +++ b/desktop/source/deployment/registry/executable/dp_executable.cxx @@ -0,0 +1,333 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_misc.h" +#include "dp_backend.h" +#include "dp_ucb.h" +#include "dp_interact.h" +#include "rtl/string.hxx" +#include "osl/file.hxx" +#include "ucbhelper/content.hxx" +#include "comphelper/servicedecl.hxx" +#include "svl/inettype.hxx" +#include "cppuhelper/implbase1.hxx" +#include "dp_executablebackenddb.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using namespace dp_misc; +using ::rtl::OUString; + +namespace dp_registry { +namespace backend { +namespace executable { +namespace { + +class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend +{ + class ExecutablePackageImpl : public ::dp_registry::backend::Package + { + BackendImpl * getMyBackend() const; + + // Package + virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference<dp_misc::AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference<dp_misc::AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + + bool getFileAttributes(sal_uInt64& out_Attributes); + bool isUrlTargetInExtension(); + public: + inline ExecutablePackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool bRemoved, OUString const & identifier) + : Package( myBackend, url, name, name /* display-name */, + xPackageType, bRemoved, identifier) + {} + }; + friend class ExecutablePackageImpl; + + typedef ::std::hash_map< OUString, Reference<XInterface>, + ::rtl::OUStringHash > t_string2object; + + // PackageRegistryBackend + virtual Reference<deployment::XPackage> bindPackage_( + OUString const & url, OUString const & mediaType, sal_Bool bRemoved, + OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv ); + + void addDataToDb(OUString const & url); + bool isRegisteredInDb(OUString const & url); + void deleteDataFromDb(OUString const & url); + + Reference<deployment::XPackageTypeInfo> m_xExecutableTypeInfo; + std::auto_ptr<ExecutableBackendDb> m_backendDb; +public: + BackendImpl( Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ); + + // XPackageRegistry + virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() throw (RuntimeException); + + using PackageRegistryBackend::disposing; +}; + + +BackendImpl::BackendImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ) + : PackageRegistryBackend( args, xComponentContext ), + m_xExecutableTypeInfo(new Package::TypeInfo( + OUSTR("application/vnd.sun.star.executable"), + OUSTR(""), + OUSTR("Executable"), + RID_IMG_COMPONENT, + RID_IMG_COMPONENT_HC ) ) +{ + if (!transientMode()) + { + OUString dbFile = makeURL(getCachePath(), OUSTR("backenddb.xml")); + m_backendDb.reset( + new ExecutableBackendDb(getComponentContext(), dbFile)); + } +} + +void BackendImpl::addDataToDb(OUString const & url) +{ + if (m_backendDb.get()) + m_backendDb->addEntry(url); +} + +bool BackendImpl::isRegisteredInDb(OUString const & url) +{ + bool ret = false; + if (m_backendDb.get()) + ret = m_backendDb->getEntry(url); + return ret; +} + +void BackendImpl::deleteDataFromDb(OUString const & url) +{ + if (m_backendDb.get()) + m_backendDb->removeEntry(url); +} + +// XPackageRegistry +Sequence< Reference<deployment::XPackageTypeInfo> > +BackendImpl::getSupportedPackageTypes() throw (RuntimeException) +{ + return Sequence<Reference<deployment::XPackageTypeInfo> >( + & m_xExecutableTypeInfo, 1); +} + +// PackageRegistryBackend +Reference<deployment::XPackage> BackendImpl::bindPackage_( + OUString const & url, OUString const & mediaType, sal_Bool bRemoved, + OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv ) +{ + if (mediaType.getLength() == 0) + { + throw lang::IllegalArgumentException( + StrCannotDetectMediaType::get() + url, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); + } + + String type, subType; + INetContentTypeParameterList params; + if (INetContentTypes::parse( mediaType, type, subType, ¶ms )) + { + if (type.EqualsIgnoreCaseAscii("application")) + { + OUString name; + if (!bRemoved) + { + ::ucbhelper::Content ucbContent( url, xCmdEnv ); + name = ucbContent.getPropertyValue( + dp_misc::StrTitle::get() ).get<OUString>(); + } + if (subType.EqualsIgnoreCaseAscii("vnd.sun.star.executable")) + { + return new BackendImpl::ExecutablePackageImpl( + this, url, name, m_xExecutableTypeInfo, bRemoved, + identifier); + } + } + } + return Reference<deployment::XPackage>(); +} + +//############################################################################## + + +// Package +BackendImpl * BackendImpl::ExecutablePackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); + if (NULL == pBackend) + { + //May throw a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<ExecutablePackageImpl *>(this))); + } + return pBackend; +} + +beans::Optional< beans::Ambiguous<sal_Bool> > +BackendImpl::ExecutablePackageImpl::isRegistered_( + ::osl::ResettableMutexGuard &, + ::rtl::Reference<dp_misc::AbortChannel> const &, + Reference<XCommandEnvironment> const & ) +{ + bool registered = getMyBackend()->isRegisteredInDb(getURL()); + return beans::Optional< beans::Ambiguous<sal_Bool> >( + sal_True /* IsPresent */, + beans::Ambiguous<sal_Bool>( + registered, sal_False /* IsAmbiguous */ ) ); +} + +void BackendImpl::ExecutablePackageImpl::processPackage_( + ::osl::ResettableMutexGuard &, + bool doRegisterPackage, + bool /*startup*/, + ::rtl::Reference<dp_misc::AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & /*xCmdEnv*/ ) +{ + checkAborted(abortChannel); + if (doRegisterPackage) + { + if (!isUrlTargetInExtension()) + { + OSL_ASSERT(0); + return; + } + sal_uInt64 attributes = 0; + //Setting the executable attribut does not affect executables on Windows + if (getFileAttributes(attributes)) + { + if(getMyBackend()->m_context.equals(OUSTR("user"))) + attributes |= osl_File_Attribute_OwnExe; + else if (getMyBackend()->m_context.equals(OUSTR("shared"))) + attributes |= (osl_File_Attribute_OwnExe | osl_File_Attribute_GrpExe + | osl_File_Attribute_OthExe); + else if (!getMyBackend()->m_context.equals(OUSTR("bundled"))) + //Bundled extension are required to be in the properly + //installed. That is an executable must have the right flags + OSL_ASSERT(0); + + //This won't have affect on Windows + osl::File::setAttributes( + dp_misc::expandUnoRcUrl(m_url), attributes); + } + getMyBackend()->addDataToDb(getURL()); + } + else + { + getMyBackend()->deleteDataFromDb(getURL()); + } +} + +//We currently cannot check if this XPackage represents a content of a particular extension +//But we can check if we are within $UNO_USER_PACKAGES_CACHE etc. +//Done for security reasons. For example an extension manifest could contain a path to +//an executable outside the extension. +bool BackendImpl::ExecutablePackageImpl::isUrlTargetInExtension() +{ + bool bSuccess = false; + OUString sExtensionDir; + if(getMyBackend()->m_context.equals(OUSTR("user"))) + sExtensionDir = dp_misc::expandUnoRcTerm(OUSTR("$UNO_USER_PACKAGES_CACHE")); + else if (getMyBackend()->m_context.equals(OUSTR("shared"))) + sExtensionDir = dp_misc::expandUnoRcTerm(OUSTR("$UNO_SHARED_PACKAGES_CACHE")); + else if (getMyBackend()->m_context.equals(OUSTR("bundled"))) + sExtensionDir = dp_misc::expandUnoRcTerm(OUSTR("$BUNDLED_EXTENSIONS")); + else + OSL_ASSERT(0); + //remove file ellipses + if (osl::File::E_None == osl::File::getAbsoluteFileURL(OUString(), sExtensionDir, sExtensionDir)) + { + OUString sFile; + if (osl::File::E_None == osl::File::getAbsoluteFileURL( + OUString(), dp_misc::expandUnoRcUrl(m_url), sFile)) + { + if (sal_True == sFile.match(sExtensionDir, 0)) + bSuccess = true; + } + } + return bSuccess; +} + +bool BackendImpl::ExecutablePackageImpl::getFileAttributes(sal_uInt64& out_Attributes) +{ + bool bSuccess = false; + const OUString url(dp_misc::expandUnoRcUrl(m_url)); + osl::DirectoryItem item; + if (osl::FileBase::E_None == osl::DirectoryItem::get(url, item)) + { + osl::FileStatus aStatus(osl_FileStatus_Mask_Attributes); + if( osl::FileBase::E_None == item.getFileStatus(aStatus)) + { + out_Attributes = aStatus.getAttributes(); + bSuccess = true; + } + } + return bSuccess; +} + +//############################################################################## + + +} // anon namespace + +namespace sdecl = comphelper::service_decl; +sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI; +extern sdecl::ServiceDecl const serviceDecl( + serviceBI, + "com.sun.star.comp.deployment.executable.PackageRegistryBackend", + BACKEND_SERVICE_NAME ); + +} // namespace component +} // namespace backend +} // namespace dp_registry + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/executable/dp_executablebackenddb.cxx b/desktop/source/deployment/registry/executable/dp_executablebackenddb.cxx new file mode 100644 index 000000000000..56a964597481 --- /dev/null +++ b/desktop/source/deployment/registry/executable/dp_executablebackenddb.cxx @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "rtl/string.h" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "dp_misc.h" +#include "dp_executablebackenddb.hxx" + + +namespace css = ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +#define EXTENSION_REG_NS "http://openoffice.org/extensionmanager/executable-registry/2010" +#define NS_PREFIX "exe" +#define ROOT_ELEMENT_NAME "executable-backend-db" +#define ENTRY_NAME "executable" + +namespace dp_registry { +namespace backend { +namespace executable { + +ExecutableBackendDb::ExecutableBackendDb( + Reference<XComponentContext> const & xContext, + ::rtl::OUString const & url):RegisteredDb(xContext, url) +{ + +} + +OUString ExecutableBackendDb::getDbNSName() +{ + return OUSTR(EXTENSION_REG_NS); +} + +OUString ExecutableBackendDb::getNSPrefix() +{ + return OUSTR(NS_PREFIX); +} + +OUString ExecutableBackendDb::getRootElementName() +{ + return OUSTR(ROOT_ELEMENT_NAME); +} + +OUString ExecutableBackendDb::getKeyElementName() +{ + return OUSTR(ENTRY_NAME); +} + + +} // namespace executable +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/executable/dp_executablebackenddb.hxx b/desktop/source/deployment/registry/executable/dp_executablebackenddb.hxx new file mode 100644 index 000000000000..425531911933 --- /dev/null +++ b/desktop/source/deployment/registry/executable/dp_executablebackenddb.hxx @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_EXECUTABLEBACKENDDB_HXX +#define INCLUDED_DP_EXECUTABLEBACKENDDB_HXX + +#include "rtl/ustring.hxx" +#include "dp_backenddb.hxx" + +namespace css = ::com::sun::star; + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } +}}} + +namespace dp_registry { +namespace backend { +namespace executable { + +/* The XML file stores the extensions which are currently registered. + They will be removed when they are revoked. + The format looks like this: + +<?xml version="1.0"?> + */ +class ExecutableBackendDb: public dp_registry::backend::RegisteredDb +{ +protected: + virtual ::rtl::OUString getDbNSName(); + + virtual ::rtl::OUString getNSPrefix(); + + virtual ::rtl::OUString getRootElementName(); + + virtual ::rtl::OUString getKeyElementName(); + +public: + + ExecutableBackendDb( css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); + +}; + + + +} +} +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/executable/makefile.mk b/desktop/source/deployment/registry/executable/makefile.mk new file mode 100644 index 000000000000..81b2baa44e5d --- /dev/null +++ b/desktop/source/deployment/registry/executable/makefile.mk @@ -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. +# +#************************************************************************* + +PRJ = ..$/..$/..$/.. + +PRJNAME = desktop +TARGET = deployment_registry_executable +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE : settings.mk + +INCPRE += ..$/..$/inc + +SLOFILES = \ + $(SLO)$/dp_executable.obj \ + $(SLO)$/dp_executablebackenddb.obj + +.INCLUDE : ..$/..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/registry/help/dp_help.cxx b/desktop/source/deployment/registry/help/dp_help.cxx new file mode 100644 index 000000000000..053929c4b16c --- /dev/null +++ b/desktop/source/deployment/registry/help/dp_help.cxx @@ -0,0 +1,660 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_help.hrc" +#include "dp_backend.h" +#include "dp_helpbackenddb.hxx" +#include "dp_ucb.h" +#include "rtl/uri.hxx" +#include "osl/file.hxx" +#include "rtl/bootstrap.hxx" +#include "ucbhelper/content.hxx" +#include "comphelper/servicedecl.hxx" +#include "svl/inettype.hxx" +#include "unotools/pathoptions.hxx" + +#include <l10ntools/compilehelp.hxx> +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> +#include <com/sun/star/util/XMacroExpander.hpp> +#include <com/sun/star/uri/XUriReferenceFactory.hpp> +#include <com/sun/star/uri/XVndSunStarExpandUrl.hpp> +#include <com/sun/star/script/XInvocation.hpp> +#include "boost/optional.hpp" + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; + +namespace dp_registry { +namespace backend { +namespace help { +namespace { + +//============================================================================== +class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend +{ + class PackageImpl : public ::dp_registry::backend::Package + { + BackendImpl * getMyBackend() const; + +// HelpBackendDb::Data m_dbData; + + // Package + virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + + bool extensionContainsCompiledHelp(); + public: + PackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool bRemoved, OUString const & identifier); + + //XPackage + virtual css::beans::Optional< ::rtl::OUString > SAL_CALL getRegistrationDataURL() + throw (deployment::ExtensionRemovedException, css::uno::RuntimeException); + }; + friend class PackageImpl; + + // PackageRegistryBackend + virtual Reference<deployment::XPackage> bindPackage_( + OUString const & url, OUString const & mediaType, + sal_Bool bRemoved, OUString const & identifier, + Reference<XCommandEnvironment> const & xCmdEnv ); + + void implProcessHelp( Reference< deployment::XPackage > xPackage, bool doRegisterPackage, + bool compiledHelp, Reference<ucb::XCommandEnvironment> const & xCmdEnv); + void implCollectXhpFiles( const rtl::OUString& aDir, + std::vector< rtl::OUString >& o_rXhpFileVector ); + + void addDataToDb(OUString const & url, HelpBackendDb::Data const & data); + ::boost::optional<HelpBackendDb::Data> readDataFromDb(OUString const & url); + void deleteDataFromDb(OUString const & url); + + Reference< ucb::XSimpleFileAccess > getFileAccess( void ); + Reference< ucb::XSimpleFileAccess > m_xSFA; + + const Reference<deployment::XPackageTypeInfo> m_xHelpTypeInfo; + Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos; + std::auto_ptr<HelpBackendDb> m_backendDb; + +public: + BackendImpl( Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ); + + // XPackageRegistry + virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() throw (RuntimeException); +}; + +//______________________________________________________________________________ +BackendImpl::BackendImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ) + : PackageRegistryBackend( args, xComponentContext ), + m_xHelpTypeInfo( new Package::TypeInfo( + OUSTR("application/vnd.sun.star.help"), + rtl::OUString(), + getResourceString(RID_STR_HELP), + RID_IMG_HELP, RID_IMG_HELP_HC ) ), + m_typeInfos( 1 ) +{ + m_typeInfos[ 0 ] = m_xHelpTypeInfo; + if (!transientMode()) + { + OUString dbFile = makeURL(getCachePath(), OUSTR("backenddb.xml")); + m_backendDb.reset( + new HelpBackendDb(getComponentContext(), dbFile)); + + //clean up data folders which are no longer used. + //This must not be done in the same process where the help files + //are still registers. Only after revoking and restarting OOo the folders + //can be removed. This works now, because the extension manager is a singleton + //and the backends are only create once per process. + ::std::list<OUString> folders = m_backendDb->getAllDataUrls(); + deleteUnusedFolders(OUString(), folders); + } +} + +// XPackageRegistry +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackageTypeInfo> > +BackendImpl::getSupportedPackageTypes() throw (RuntimeException) +{ + return m_typeInfos; +} + +// PackageRegistryBackend +//______________________________________________________________________________ +Reference<deployment::XPackage> BackendImpl::bindPackage_( + OUString const & url, OUString const & mediaType_, + sal_Bool bRemoved, OUString const & identifier, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + // we don't support auto detection: + if (mediaType_.getLength() == 0) + throw lang::IllegalArgumentException( + StrCannotDetectMediaType::get() + url, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); + + String type, subType; + INetContentTypeParameterList params; + if (INetContentTypes::parse( mediaType_, type, subType, ¶ms )) + { + if (type.EqualsIgnoreCaseAscii("application")) + { + OUString name; + if (!bRemoved) + { + ::ucbhelper::Content ucbContent( url, xCmdEnv ); + name = ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>(); + } + + if (subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.help")) + { + return new PackageImpl( + this, url, name, m_xHelpTypeInfo, bRemoved, + identifier); + } + } + } + throw lang::IllegalArgumentException( + StrUnsupportedMediaType::get() + mediaType_, + static_cast<OWeakObject *>(this), + static_cast<sal_Int16>(-1) ); +} + +void BackendImpl::addDataToDb( + OUString const & url, HelpBackendDb::Data const & data) +{ + if (m_backendDb.get()) + m_backendDb->addEntry(url, data); +} + +::boost::optional<HelpBackendDb::Data> BackendImpl::readDataFromDb( + OUString const & url) +{ + ::boost::optional<HelpBackendDb::Data> data; + if (m_backendDb.get()) + data = m_backendDb->getEntry(url); + return data; +} + +void BackendImpl::deleteDataFromDb(OUString const & url) +{ + if (m_backendDb.get()) + m_backendDb->removeEntry(url); +} + +//############################################################################## +BackendImpl::PackageImpl::PackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool bRemoved, OUString const & identifier) + : Package( myBackend, url, name, name, xPackageType, bRemoved, + identifier) +{ +// if (bRemoved) +// { +// ::boost::optional<HelpBackendDb::Data> opt = +// getMyBackend()->readDataFromDb(url); +// if (opt) +// m_dbData = *opt; +// } +} + +// Package +BackendImpl * BackendImpl::PackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); + if (NULL == pBackend) + { + //May throw a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<PackageImpl *>(this))); + } + return pBackend; +} + + +bool BackendImpl::PackageImpl::extensionContainsCompiledHelp() +{ + bool bCompiled = true; + rtl::OUString aExpandedHelpURL = dp_misc::expandUnoRcUrl(getURL()); + + ::osl::Directory helpFolder(aExpandedHelpURL); + if ( helpFolder.open() == ::osl::File::E_None) + { + //iterate over the contents of the help folder + //We assume that all folders withing the help folder contain language specific + //help files. If just one of them does not contain compiled help then this + //function returns false. + ::osl::DirectoryItem item; + ::osl::File::RC errorNext = ::osl::File::E_None; + while ((errorNext = helpFolder.getNextItem(item)) == ::osl::File::E_None) + { + //No find the language folders + ::osl::FileStatus stat(FileStatusMask_Type | FileStatusMask_FileName |FileStatusMask_FileURL); + if (item.getFileStatus(stat) == ::osl::File::E_None) + { + if (stat.getFileType() != ::osl::FileStatus::Directory) + continue; + + //look if there is the folder help.idxl in the language folder + OUString compUrl(stat.getFileURL() + OUSTR("/help.idxl")); + ::osl::Directory compiledFolder(compUrl); + if (compiledFolder.open() != ::osl::File::E_None) + { + bCompiled = false; + break; + } + } + else + { + //Error + OSL_ASSERT(0); + bCompiled = false; + break; + } + } + if (errorNext != ::osl::File::E_NOENT + && errorNext != ::osl::File::E_None) + { + //Error + OSL_ASSERT(0); + bCompiled = false; + } + } + return bCompiled; +} +//______________________________________________________________________________ +beans::Optional< beans::Ambiguous<sal_Bool> > +BackendImpl::PackageImpl::isRegistered_( + ::osl::ResettableMutexGuard &, + ::rtl::Reference<AbortChannel> const &, + Reference<XCommandEnvironment> const & ) +{ + BackendImpl * that = getMyBackend(); + + bool bReg = false; + if (that->readDataFromDb(getURL())) + bReg = true; + + return beans::Optional< beans::Ambiguous<sal_Bool> >( true, beans::Ambiguous<sal_Bool>( bReg, false ) ); +} + +//______________________________________________________________________________ +void BackendImpl::PackageImpl::processPackage_( + ::osl::ResettableMutexGuard &, + bool doRegisterPackage, + bool /* startup */, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + (void)doRegisterPackage; + (void)abortChannel; + (void)xCmdEnv; + + BackendImpl* that = getMyBackend(); + Reference< deployment::XPackage > xThisPackage( this ); + that->implProcessHelp( xThisPackage, doRegisterPackage, + extensionContainsCompiledHelp(), xCmdEnv); +} + +beans::Optional< OUString > BackendImpl::PackageImpl::getRegistrationDataURL() + throw (deployment::ExtensionRemovedException, + css::uno::RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + + ::boost::optional<HelpBackendDb::Data> data = + getMyBackend()->readDataFromDb(getURL()); + + if (data) + return beans::Optional<OUString>(true, data->dataUrl); + + return beans::Optional<OUString>(true, OUString()); +} + + +//############################################################################## + +static rtl::OUString aSlash( rtl::OUString::createFromAscii( "/" ) ); +static rtl::OUString aHelpStr( rtl::OUString::createFromAscii( "help" ) ); + + +void BackendImpl::implProcessHelp +( Reference< deployment::XPackage > xPackage, bool doRegisterPackage, bool compiledHelp, + Reference<ucb::XCommandEnvironment> const & xCmdEnv) +{ + OSL_ASSERT(xPackage.is()); + if (doRegisterPackage) + { + HelpBackendDb::Data data; + + if (compiledHelp) + { + data.dataUrl = xPackage->getURL(); + } + else + { + const OUString sHelpFolder = createFolder(OUString(), xCmdEnv); + data.dataUrl = sHelpFolder; + + Reference< ucb::XSimpleFileAccess > xSFA = getFileAccess(); + rtl::OUString aHelpURL = xPackage->getURL(); + rtl::OUString aExpandedHelpURL = dp_misc::expandUnoRcUrl( aHelpURL ); + rtl::OUString aName = xPackage->getName(); + if( !xSFA->isFolder( aExpandedHelpURL ) ) + { + rtl::OUString aErrStr = getResourceString( RID_STR_HELPPROCESSING_GENERAL_ERROR ); + aErrStr += rtl::OUString::createFromAscii( "No help folder" ); + OWeakObject* oWeakThis = static_cast<OWeakObject *>(this); + throw deployment::DeploymentException( rtl::OUString(), oWeakThis, + makeAny( uno::Exception( aErrStr, oWeakThis ) ) ); + } + + Reference<XComponentContext> const & xContext = getComponentContext(); + Reference< script::XInvocation > xInvocation; + if( xContext.is() ) + { + try + { + xInvocation = Reference< script::XInvocation >( + xContext->getServiceManager()->createInstanceWithContext( rtl::OUString::createFromAscii( + "com.sun.star.help.HelpIndexer" ), xContext ) , UNO_QUERY ); + } + catch (Exception &) + { + // i98680: Survive missing lucene + } + } + + // Scan languages + Sequence< rtl::OUString > aLanguageFolderSeq = xSFA->getFolderContents( aExpandedHelpURL, true ); + sal_Int32 nLangCount = aLanguageFolderSeq.getLength(); + const rtl::OUString* pSeq = aLanguageFolderSeq.getConstArray(); + for( sal_Int32 iLang = 0 ; iLang < nLangCount ; ++iLang ) + { + rtl::OUString aLangURL = pSeq[iLang]; + if( xSFA->isFolder( aLangURL ) ) + { + std::vector< rtl::OUString > aXhpFileVector; + + // calculate jar file URL + sal_Int32 indexStartSegment = aLangURL.lastIndexOf('/'); + // for example "/en" + OUString langFolderURLSegment( + aLangURL.copy( + indexStartSegment + 1, aLangURL.getLength() - indexStartSegment - 1)); + + //create the folder in the "temporary folder" + ::ucbhelper::Content langFolderContent; + const OUString langFolderDest = makeURL(sHelpFolder, langFolderURLSegment); + const OUString langFolderDestExpanded = ::dp_misc::expandUnoRcUrl(langFolderDest); + ::dp_misc::create_folder( + &langFolderContent, + langFolderDest, xCmdEnv); + + rtl::OUString aJarFile( + makeURL(sHelpFolder, langFolderURLSegment + aSlash + aHelpStr + + OUSTR(".jar"))); + aJarFile = ::dp_misc::expandUnoRcUrl(aJarFile); + + rtl::OUString aEncodedJarFilePath = rtl::Uri::encode( + aJarFile, rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ); + rtl::OUString aDestBasePath = rtl::OUString::createFromAscii( "vnd.sun.star.pkg://" ); + aDestBasePath += aEncodedJarFilePath; + aDestBasePath += rtl::OUString::createFromAscii( "/" ); + + sal_Int32 nLenLangFolderURL = aLangURL.getLength() + 1; + + Sequence< rtl::OUString > aSubLangSeq = xSFA->getFolderContents( aLangURL, true ); + sal_Int32 nSubLangCount = aSubLangSeq.getLength(); + const rtl::OUString* pSubLangSeq = aSubLangSeq.getConstArray(); + for( sal_Int32 iSubLang = 0 ; iSubLang < nSubLangCount ; ++iSubLang ) + { + rtl::OUString aSubFolderURL = pSubLangSeq[iSubLang]; + if( !xSFA->isFolder( aSubFolderURL ) ) + continue; + + implCollectXhpFiles( aSubFolderURL, aXhpFileVector ); + + // Copy to package (later: move?) + rtl::OUString aDestPath = aDestBasePath; + rtl::OUString aPureFolderName = aSubFolderURL.copy( nLenLangFolderURL ); + aDestPath += aPureFolderName; + xSFA->copy( aSubFolderURL, aDestPath ); + } + + // Call compiler + sal_Int32 nXhpFileCount = aXhpFileVector.size(); + rtl::OUString* pXhpFiles = new rtl::OUString[nXhpFileCount]; + for( sal_Int32 iXhp = 0 ; iXhp < nXhpFileCount ; ++iXhp ) + { + rtl::OUString aXhpFile = aXhpFileVector[iXhp]; + rtl::OUString aXhpRelFile = aXhpFile.copy( nLenLangFolderURL ); + pXhpFiles[iXhp] = aXhpRelFile; + } + + rtl::OUString aOfficeHelpPath( SvtPathOptions().GetHelpPath() ); + rtl::OUString aOfficeHelpPathFileURL; + ::osl::File::getFileURLFromSystemPath( aOfficeHelpPath, aOfficeHelpPathFileURL ); + + HelpProcessingErrorInfo aErrorInfo; + bool bSuccess = compileExtensionHelp( + aOfficeHelpPathFileURL, aHelpStr, aLangURL, + nXhpFileCount, pXhpFiles, + langFolderDestExpanded, aErrorInfo ); + + if( bSuccess && xInvocation.is() ) + { + Sequence<uno::Any> aParamsSeq( 6 ); + + aParamsSeq[0] = uno::makeAny( rtl::OUString::createFromAscii( "-lang" ) ); + + rtl::OUString aLang; + sal_Int32 nLastSlash = aLangURL.lastIndexOf( '/' ); + if( nLastSlash != -1 ) + aLang = aLangURL.copy( nLastSlash + 1 ); + else + aLang = rtl::OUString::createFromAscii( "en" ); + aParamsSeq[1] = uno::makeAny( aLang ); + + aParamsSeq[2] = uno::makeAny( rtl::OUString::createFromAscii( "-mod" ) ); + aParamsSeq[3] = uno::makeAny( rtl::OUString::createFromAscii( "help" ) ); + + aParamsSeq[4] = uno::makeAny( rtl::OUString::createFromAscii( "-zipdir" ) ); + rtl::OUString aSystemPath; + osl::FileBase::getSystemPathFromFileURL( + langFolderDestExpanded, aSystemPath ); + aParamsSeq[5] = uno::makeAny( aSystemPath ); + + Sequence< sal_Int16 > aOutParamIndex; + Sequence< uno::Any > aOutParam; + uno::Any aRet = xInvocation->invoke( rtl::OUString::createFromAscii( "createIndex" ), + aParamsSeq, aOutParamIndex, aOutParam ); + } + + if( !bSuccess ) + { + USHORT nErrStrId = 0; + switch( aErrorInfo.m_eErrorClass ) + { + case HELPPROCESSING_GENERAL_ERROR: + case HELPPROCESSING_INTERNAL_ERROR: nErrStrId = RID_STR_HELPPROCESSING_GENERAL_ERROR; break; + case HELPPROCESSING_XMLPARSING_ERROR: nErrStrId = RID_STR_HELPPROCESSING_XMLPARSING_ERROR; break; + default: ; + }; + + rtl::OUString aErrStr; + if( nErrStrId != 0 ) + { + aErrStr = getResourceString( nErrStrId ); + + // Remoce CR/LF + rtl::OUString aErrMsg( aErrorInfo.m_aErrorMsg ); + sal_Unicode nCR = 13, nLF = 10; + sal_Int32 nSearchCR = aErrMsg.indexOf( nCR ); + sal_Int32 nSearchLF = aErrMsg.indexOf( nLF ); + sal_Int32 nCopy; + if( nSearchCR != -1 || nSearchLF != -1 ) + { + if( nSearchCR == -1 ) + nCopy = nSearchLF; + else if( nSearchLF == -1 ) + nCopy = nSearchCR; + else + nCopy = ( nSearchCR < nSearchLF ) ? nSearchCR : nSearchLF; + + aErrMsg = aErrMsg.copy( 0, nCopy ); + } + aErrStr += aErrMsg; + if( nErrStrId == RID_STR_HELPPROCESSING_XMLPARSING_ERROR && aErrorInfo.m_aXMLParsingFile.getLength() ) + { + aErrStr += rtl::OUString::createFromAscii( " in " ); + + rtl::OUString aDecodedFile = rtl::Uri::decode( aErrorInfo.m_aXMLParsingFile, + rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); + aErrStr += aDecodedFile; + if( aErrorInfo.m_nXMLParsingLine != -1 ) + { + aErrStr += rtl::OUString::createFromAscii( ", line " ); + aErrStr += ::rtl::OUString::valueOf( aErrorInfo.m_nXMLParsingLine ); + } + } + } + + OWeakObject* oWeakThis = static_cast<OWeakObject *>(this); + throw deployment::DeploymentException( rtl::OUString(), oWeakThis, + makeAny( uno::Exception( aErrStr, oWeakThis ) ) ); + } + } + } + } + //Writing the data entry replaces writing the flag file. If we got to this + //point the registration was successful. + addDataToDb(xPackage->getURL(), data); + } //if (doRegisterPackage) + else + { + deleteDataFromDb(xPackage->getURL()); + } +} + + +void BackendImpl::implCollectXhpFiles( const rtl::OUString& aDir, + std::vector< rtl::OUString >& o_rXhpFileVector ) +{ + Reference< ucb::XSimpleFileAccess > xSFA = getFileAccess(); + + // Scan xhp files recursively + Sequence< rtl::OUString > aSeq = xSFA->getFolderContents( aDir, true ); + sal_Int32 nCount = aSeq.getLength(); + const rtl::OUString* pSeq = aSeq.getConstArray(); + for( sal_Int32 i = 0 ; i < nCount ; ++i ) + { + rtl::OUString aURL = pSeq[i]; + if( xSFA->isFolder( aURL ) ) + { + implCollectXhpFiles( aURL, o_rXhpFileVector ); + } + else + { + sal_Int32 nLastDot = aURL.lastIndexOf( '.' ); + if( nLastDot != -1 ) + { + rtl::OUString aExt = aURL.copy( nLastDot + 1 ); + if( aExt.equalsIgnoreAsciiCase( rtl::OUString::createFromAscii( "xhp" ) ) ) + o_rXhpFileVector.push_back( aURL ); + } + } + } +} + +Reference< ucb::XSimpleFileAccess > BackendImpl::getFileAccess( void ) +{ + if( !m_xSFA.is() ) + { + Reference<XComponentContext> const & xContext = getComponentContext(); + if( xContext.is() ) + { + m_xSFA = Reference< ucb::XSimpleFileAccess >( + xContext->getServiceManager()->createInstanceWithContext( + rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ), + xContext ), UNO_QUERY ); + } + if( !m_xSFA.is() ) + { + throw RuntimeException( + ::rtl::OUString::createFromAscii( + "dp_registry::backend::help::BackendImpl::getFileAccess(), " + "could not instatiate SimpleFileAccess." ), + Reference< XInterface >() ); + } + } + return m_xSFA; +} + +} // anon namespace + +namespace sdecl = comphelper::service_decl; +sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI; +extern sdecl::ServiceDecl const serviceDecl( + serviceBI, + "com.sun.star.comp.deployment.help.PackageRegistryBackend", + BACKEND_SERVICE_NAME ); + +} // namespace help +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/help/dp_help.hrc b/desktop/source/deployment/registry/help/dp_help.hrc new file mode 100644 index 000000000000..451144813f25 --- /dev/null +++ b/desktop/source/deployment/registry/help/dp_help.hrc @@ -0,0 +1,39 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_HELP_HRC +#define INCLUDED_DP_HELP_HRC + +#include "deployment.hrc" + +#define RID_STR_HELP (RID_DEPLOYMENT_HELP_START+2) + +#define RID_STR_HELPPROCESSING_GENERAL_ERROR (RID_DEPLOYMENT_HELP_START+3) +#define RID_STR_HELPPROCESSING_XMLPARSING_ERROR (RID_DEPLOYMENT_HELP_START+4) + + +#endif diff --git a/desktop/source/deployment/registry/help/dp_help.src b/desktop/source/deployment/registry/help/dp_help.src new file mode 100644 index 000000000000..6cb9b023e60d --- /dev/null +++ b/desktop/source/deployment/registry/help/dp_help.src @@ -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. + * + ************************************************************************/ + +#include "dp_help.hrc" + +String RID_STR_HELP +{ + Text [ en-US ] = "Help"; +}; + +String RID_STR_HELPPROCESSING_GENERAL_ERROR +{ + Text [ en-US ] = "The extension cannot be installed because:\n"; +}; + +String RID_STR_HELPPROCESSING_XMLPARSING_ERROR +{ + Text [ en-US ] = "The extension will not be installed because an error occurred in the Help files:\n"; +}; + diff --git a/desktop/source/deployment/registry/help/dp_helpbackenddb.cxx b/desktop/source/deployment/registry/help/dp_helpbackenddb.cxx new file mode 100644 index 000000000000..92ce961de6d0 --- /dev/null +++ b/desktop/source/deployment/registry/help/dp_helpbackenddb.cxx @@ -0,0 +1,177 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "rtl/string.h" +#include "rtl/bootstrap.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "dp_misc.h" + +#include "dp_helpbackenddb.hxx" + + +namespace css = ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +#define EXTENSION_REG_NS "http://openoffice.org/extensionmanager/help-registry/2010" +#define NS_PREFIX "help" +#define ROOT_ELEMENT_NAME "help-backend-db" +#define KEY_ELEMENT_NAME "help" + +namespace dp_registry { +namespace backend { +namespace help { + +HelpBackendDb::HelpBackendDb( + Reference<XComponentContext> const & xContext, + ::rtl::OUString const & url):BackendDb(xContext, url) +{ + +} + +OUString HelpBackendDb::getDbNSName() +{ + return OUSTR(EXTENSION_REG_NS); +} + +OUString HelpBackendDb::getNSPrefix() +{ + return OUSTR(NS_PREFIX); +} + +OUString HelpBackendDb::getRootElementName() +{ + return OUSTR(ROOT_ELEMENT_NAME); +} + +OUString HelpBackendDb::getKeyElementName() +{ + return OUSTR(KEY_ELEMENT_NAME); +} + + +void HelpBackendDb::addEntry(::rtl::OUString const & url, Data const & data) +{ + try{ + Reference<css::xml::dom::XNode> helpNode + = writeKeyElement(url); + + writeSimpleElement(OUSTR("data-url"), data.dataUrl, helpNode); + save(); + } + catch (css::deployment::DeploymentException& ) + { + throw; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in help backend db: ") + + m_urlDb, 0, exc); + } +} + + +::boost::optional<HelpBackendDb::Data> +HelpBackendDb::getEntry(::rtl::OUString const & url) +{ + try + { + HelpBackendDb::Data retData; + Reference<css::xml::dom::XNode> aNode = getKeyElement(url); + if (aNode.is()) + { + retData.dataUrl = readSimpleElement(OUSTR("data-url"), aNode); + } + else + { + return ::boost::optional<Data>(); + } + return ::boost::optional<Data>(retData); + } + catch (css::deployment::DeploymentException& ) + { + throw; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in help backend db: ") + + m_urlDb, 0, exc); + } +} + +::std::list<OUString> HelpBackendDb::getAllDataUrls() +{ + try + { + ::std::list<OUString> listRet; + Reference<css::xml::dom::XDocument> doc = getDocument(); + Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + + Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + const OUString sPrefix = getNSPrefix(); + OUString sExpression( + sPrefix + OUSTR(":help/") + sPrefix + OUSTR(":data-url/text()")); + Reference<css::xml::dom::XNodeList> nodes = + xpathApi->selectNodeList(root, sExpression); + if (nodes.is()) + { + sal_Int32 length = nodes->getLength(); + for (sal_Int32 i = 0; i < length; i++) + listRet.push_back(nodes->item(i)->getNodeValue()); + } + return listRet; + } + catch (css::deployment::DeploymentException& ) + { + throw; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in help backend db: ") + + m_urlDb, 0, exc); + } +} + + +} // namespace help +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/help/dp_helpbackenddb.hxx b/desktop/source/deployment/registry/help/dp_helpbackenddb.hxx new file mode 100644 index 000000000000..4a2eb8ec5922 --- /dev/null +++ b/desktop/source/deployment/registry/help/dp_helpbackenddb.hxx @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_HELPBACKENDDB_HXX +#define INCLUDED_DP_HELPBACKENDDB_HXX + +#include "rtl/ustring.hxx" +#include <list> +#include "boost/optional.hpp" +#include "dp_backenddb.hxx" + +namespace css = ::com::sun::star; + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } +}}} + +namespace dp_registry { +namespace backend { +namespace help { + +/* The XML file stores the extensions which are currently registered. + They will be removed when they are revoked. + */ +class HelpBackendDb: public dp_registry::backend::BackendDb +{ +protected: + virtual ::rtl::OUString getDbNSName(); + + virtual ::rtl::OUString getNSPrefix(); + + virtual ::rtl::OUString getRootElementName(); + + virtual ::rtl::OUString getKeyElementName(); + +public: + struct Data + { + /* the URL to the folder containing the compiled help files, etc. + */ + ::rtl::OUString dataUrl; + + }; + +public: + + HelpBackendDb( css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); + + void addEntry(::rtl::OUString const & url, Data const & data); + + ::boost::optional<Data> getEntry(::rtl::OUString const & url); + ::std::list< ::rtl::OUString> getAllDataUrls(); + +}; + + + +} +} +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/help/makefile.mk b/desktop/source/deployment/registry/help/makefile.mk new file mode 100644 index 000000000000..d4934f71a46f --- /dev/null +++ b/desktop/source/deployment/registry/help/makefile.mk @@ -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. +# +#************************************************************************* + +PRJ = ..$/..$/..$/.. + +PRJNAME = desktop +TARGET = deployment_registry_help +ENABLE_EXCEPTIONS = TRUE + +INCPRE += ..$/..$/inc + +.INCLUDE : settings.mk + +.IF "$(SYSTEM_DB)" == "YES" +CFLAGS+=-DSYSTEM_DB -I$(DB_INCLUDES) +.ENDIF + +SRS1NAME = $(TARGET) +SRC1FILES = \ + dp_help.src + +SLOFILES = \ + $(SLO)$/dp_help.obj \ + $(SLO)$/dp_helpbackenddb.obj + +.INCLUDE : ..$/..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/registry/inc/dp_backend.h b/desktop/source/deployment/registry/inc/dp_backend.h new file mode 100644 index 000000000000..53de2ef1da24 --- /dev/null +++ b/desktop/source/deployment/registry/inc/dp_backend.h @@ -0,0 +1,381 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_REGISTRY_H +#define INCLUDED_DP_REGISTRY_H + +#include "dp_misc.h" +#include "dp_resource.h" +#include "dp_interact.h" +#include "rtl/ref.hxx" +#include "cppuhelper/weakref.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/compbase1.hxx" +#include "cppuhelper/compbase2.hxx" +#include "tools/inetmime.hxx" +#include "com/sun/star/lang/XEventListener.hpp" +#include "com/sun/star/deployment/XPackageRegistry.hpp" +#include "com/sun/star/deployment/XPackageManager.hpp" +#include "com/sun/star/deployment/InvalidRemovedParameterException.hpp" +#include <memory> +#include <hash_map> +#include <list> +#include "dp_registry.hrc" + +namespace dp_registry +{ +namespace backend +{ + +namespace css = ::com::sun::star; + +class PackageRegistryBackend; + +char const* const BACKEND_SERVICE_NAME = +"com.sun.star.deployment.PackageRegistryBackend"; + +typedef ::cppu::WeakComponentImplHelper1< + css::deployment::XPackage > t_PackageBase; + +//============================================================================== +class Package : protected ::dp_misc::MutexHolder, public t_PackageBase +{ + PackageRegistryBackend * getMyBackend() const; + void processPackage_impl( + bool registerPackage, + bool startup, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ); + +protected: + ::rtl::Reference<PackageRegistryBackend> m_myBackend; + const ::rtl::OUString m_url; + ::rtl::OUString m_name; + ::rtl::OUString m_displayName; + const css::uno::Reference<css::deployment::XPackageTypeInfo> m_xPackageType; + const bool m_bRemoved; + //Only set if m_bRemoved = true; + const ::rtl::OUString m_identifier; + + void check() const; + void fireModified(); + virtual void SAL_CALL disposing(); + + void checkAborted( + ::rtl::Reference< ::dp_misc::AbortChannel > const & abortChannel ); + + // @@@ to be implemented by specific backend: + virtual css::beans::Optional< css::beans::Ambiguous<sal_Bool> > + isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference< ::dp_misc::AbortChannel > const & abortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + = 0; + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference< ::dp_misc::AbortChannel > const & abortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + = 0; + + virtual ~Package(); + Package( ::rtl::Reference<PackageRegistryBackend> const & myBackend, + ::rtl::OUString const & url, + ::rtl::OUString const & name, + ::rtl::OUString const & displayName, + css::uno::Reference<css::deployment::XPackageTypeInfo> const & + xPackageType, + bool bRemoved, + ::rtl::OUString const & identifier); + +public: + + class TypeInfo : + public ::cppu::WeakImplHelper1<css::deployment::XPackageTypeInfo> + { + const ::rtl::OUString m_mediaType; + const ::rtl::OUString m_fileFilter; + const ::rtl::OUString m_shortDescr; + const sal_uInt16 m_smallIcon, m_smallIcon_HC; + public: + virtual ~TypeInfo(); + TypeInfo( ::rtl::OUString const & mediaType, + ::rtl::OUString const & fileFilter, + ::rtl::OUString const & shortDescr, + sal_uInt16 smallIcon, sal_uInt16 smallIcon_HC ) + : m_mediaType(mediaType), m_fileFilter(fileFilter), + m_shortDescr(shortDescr), + m_smallIcon(smallIcon), m_smallIcon_HC(smallIcon_HC) + {} + // XPackageTypeInfo + virtual ::rtl::OUString SAL_CALL getMediaType() + throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getDescription() + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getShortDescription() + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getFileFilter() + throw (css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL getIcon( sal_Bool highContrast, + sal_Bool smallIcon ) + throw (css::uno::RuntimeException); + }; + + // XComponent + virtual void SAL_CALL dispose() throw (css::uno::RuntimeException); + virtual void SAL_CALL addEventListener( + css::uno::Reference<css::lang::XEventListener> const & xListener ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( + css::uno::Reference<css::lang::XEventListener> const & xListener ) + throw (css::uno::RuntimeException); + + // XModifyBroadcaster + virtual void SAL_CALL addModifyListener( + css::uno::Reference<css::util::XModifyListener> const & xListener ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL removeModifyListener( + css::uno::Reference<css::util::XModifyListener> const & xListener ) + throw (css::uno::RuntimeException); + + // XPackage + virtual css::uno::Reference<css::task::XAbortChannel> SAL_CALL + createAbortChannel() throw (css::uno::RuntimeException); + virtual css::beans::Optional< css::beans::Ambiguous<sal_Bool> > + SAL_CALL isRegistered( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::uno::RuntimeException); + + virtual ::sal_Int32 SAL_CALL checkPrerequisites( + const css::uno::Reference< css::task::XAbortChannel >& xAbortChannel, + const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv, + sal_Bool noLicenseChecking) + throw (css::deployment::DeploymentException, + css::deployment::ExtensionRemovedException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::uno::RuntimeException); + + virtual ::sal_Bool SAL_CALL checkDependencies( + const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv ) + throw (css::deployment::DeploymentException, + css::deployment::ExtensionRemovedException, + css::ucb::CommandFailedException, + css::uno::RuntimeException); + + virtual void SAL_CALL registerPackage( + sal_Bool startup, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::deployment::ExtensionRemovedException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, css::uno::RuntimeException); + virtual void SAL_CALL revokePackage( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + virtual sal_Bool SAL_CALL isBundle() + throw (css::uno::RuntimeException); + virtual css::uno::Sequence< css::uno::Reference<css::deployment::XPackage> > + SAL_CALL getBundle( + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getName() + throw (css::uno::RuntimeException); + virtual css::beans::Optional< ::rtl::OUString > SAL_CALL getIdentifier() + throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getVersion() + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getURL() + throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getDisplayName() + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getDescription() + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL + getUpdateInformationURLs() + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual css::beans::StringPair SAL_CALL getPublisherInfo() + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual css::uno::Reference< css::graphic::XGraphic > SAL_CALL + getIcon( sal_Bool bHighContrast ) + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual css::uno::Reference<css::deployment::XPackageTypeInfo> SAL_CALL + getPackageType() throw (css::uno::RuntimeException); + virtual void SAL_CALL exportTo( + ::rtl::OUString const & destFolderURL, + ::rtl::OUString const & newTitle, + sal_Int32 nameClashAction, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::ExtensionRemovedException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getRepositoryName() + throw (css::uno::RuntimeException); + virtual css::beans::Optional< ::rtl::OUString > SAL_CALL getRegistrationDataURL() + throw (css::deployment::ExtensionRemovedException, + css::uno::RuntimeException); + virtual sal_Bool SAL_CALL isRemoved() + throw (css::uno::RuntimeException); + +}; + +typedef ::cppu::WeakComponentImplHelper2< + css::lang::XEventListener, + css::deployment::XPackageRegistry > t_BackendBase; + +//============================================================================== +class PackageRegistryBackend + : protected ::dp_misc::MutexHolder, public t_BackendBase +{ + //The map held originally WeakReferences. The map entries are removed in the disposing + //function, which is called when the XPackages are destructed or they are + //explicitely disposed. The latter happens, for example, when a extension is + //removed (see dp_manager.cxx). However, because of how the help systems work, now + // XPackageManager::getDeployedPackages is called often. This results in a lot + //of bindPackage calls which are costly. Therefore we keep hard references in + //the map now. + typedef ::std::hash_map< + ::rtl::OUString, css::uno::Reference<css::deployment::XPackage>, + ::rtl::OUStringHash > t_string2ref; + t_string2ref m_bound; + +protected: + ::rtl::OUString m_cachePath; + css::uno::Reference<css::uno::XComponentContext> m_xComponentContext; + + ::rtl::OUString m_context; + // currently only for library containers: + enum context { + CONTEXT_UNKNOWN, + CONTEXT_USER, CONTEXT_SHARED,CONTEXT_BUNDLED, CONTEXT_TMP, + CONTEXT_DOCUMENT + } m_eContext; + bool m_readOnly; + + struct StrCannotDetectMediaType : public ::dp_misc::StaticResourceString< + StrCannotDetectMediaType, RID_STR_CANNOT_DETECT_MEDIA_TYPE> {}; + struct StrUnsupportedMediaType : public ::dp_misc::StaticResourceString< + StrUnsupportedMediaType, RID_STR_UNSUPPORTED_MEDIA_TYPE> {}; + + // @@@ to be implemented by specific backend: + virtual css::uno::Reference<css::deployment::XPackage> bindPackage_( + ::rtl::OUString const & url, ::rtl::OUString const & mediaType, + sal_Bool bRemoved, ::rtl::OUString const & identifier, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + = 0; + + void check(); + virtual void SAL_CALL disposing(); + + virtual ~PackageRegistryBackend(); + PackageRegistryBackend( + css::uno::Sequence<css::uno::Any> const & args, + css::uno::Reference<css::uno::XComponentContext> const & xContext ); + + /* creates a folder with a unique name. + If url is empty then it is created in the the backend folder, otherwise + at a location relative to that folder specified by url. + */ + ::rtl::OUString createFolder( + ::rtl::OUString const & relUrl, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + /* deletes folders and files. + + All folder all files which end with ".tmp" or ".tmp_" and which are + not used are deleted. + */ + void deleteUnusedFolders( + ::rtl::OUString const & relUrl, + ::std::list< ::rtl::OUString> const & usedFolders); + /* deletes one folder with a "temporary" name and the corresponding + tmp file, which was used to derive the folder name. + */ + static void deleteTempFolder( + ::rtl::OUString const & folderUrl); + + +public: + struct StrRegisteringPackage : public ::dp_misc::StaticResourceString< + StrRegisteringPackage, RID_STR_REGISTERING_PACKAGE> {}; + struct StrRevokingPackage : public ::dp_misc::StaticResourceString< + StrRevokingPackage, RID_STR_REVOKING_PACKAGE> {}; + + inline css::uno::Reference<css::uno::XComponentContext> const & + getComponentContext() const { return m_xComponentContext; } + + inline ::rtl::OUString const & getCachePath() const { return m_cachePath; } + inline bool transientMode() const { return m_cachePath.getLength() == 0; } + + inline ::rtl::OUString getContext() const {return m_context; } + + // XEventListener + virtual void SAL_CALL disposing( css::lang::EventObject const & evt ) + throw (css::uno::RuntimeException); + + // XPackageRegistry + virtual css::uno::Reference<css::deployment::XPackage> SAL_CALL bindPackage( + ::rtl::OUString const & url, ::rtl::OUString const & mediaType, + sal_Bool bRemoved, ::rtl::OUString const & identifier, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::deployment::InvalidRemovedParameterException, + css::ucb::CommandFailedException, + css::lang::IllegalArgumentException, css::uno::RuntimeException); +}; + +} +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/inc/dp_backenddb.hxx b/desktop/source/deployment/registry/inc/dp_backenddb.hxx new file mode 100644 index 000000000000..11dff5a510d3 --- /dev/null +++ b/desktop/source/deployment/registry/inc/dp_backenddb.hxx @@ -0,0 +1,172 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_BACKENDDB_HXX +#define INCLUDED_DP_BACKENDDB_HXX + +#include "rtl/ustring.hxx" +#include <list> +#include <vector> + +namespace css = ::com::sun::star; + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } + namespace xml { namespace dom { + class XDocument; + class XNode; + }} + namespace xml { namespace xpath { + class XXPathAPI; + }} +}}} + +namespace dp_registry { +namespace backend { + +class BackendDb +{ +private: + + css::uno::Reference<css::xml::dom::XDocument> m_doc; + css::uno::Reference<css::xml::xpath::XXPathAPI> m_xpathApi; + + BackendDb(BackendDb const &); + BackendDb & operator = (BackendDb const &); + +protected: + const css::uno::Reference<css::uno::XComponentContext> m_xContext; + ::rtl::OUString m_urlDb; + +protected: + + /* caller must make sure that only one thread accesses the function + */ + css::uno::Reference<css::xml::dom::XDocument> getDocument(); + + /* the namespace prefix is "reg" (without quotes) + */ + css::uno::Reference<css::xml::xpath::XXPathAPI> getXPathAPI(); + void save(); + void removeElement(::rtl::OUString const & sXPathExpression); + + css::uno::Reference<css::xml::dom::XNode> getKeyElement( + ::rtl::OUString const & url); + + void writeSimpleList( + ::std::list< ::rtl::OUString> const & list, + ::rtl::OUString const & sListTagName, + ::rtl::OUString const & sMemberTagName, + css::uno::Reference<css::xml::dom::XNode> const & xParent); + + void writeVectorOfPair( + ::std::vector< ::std::pair< ::rtl::OUString, ::rtl::OUString > > const & vecPairs, + ::rtl::OUString const & sVectorTagName, + ::rtl::OUString const & sPairTagName, + ::rtl::OUString const & sFirstTagName, + ::rtl::OUString const & sSecondTagName, + css::uno::Reference<css::xml::dom::XNode> const & xParent); + + void writeSimpleElement( + ::rtl::OUString const & sElementName, ::rtl::OUString const & value, + css::uno::Reference<css::xml::dom::XNode> const & xParent); + + css::uno::Reference<css::xml::dom::XNode> writeKeyElement( + ::rtl::OUString const & url); + + ::rtl::OUString readSimpleElement( + ::rtl::OUString const & sElementName, + css::uno::Reference<css::xml::dom::XNode> const & xParent); + + ::std::vector< ::std::pair< ::rtl::OUString, ::rtl::OUString > > + readVectorOfPair( + css::uno::Reference<css::xml::dom::XNode> const & parent, + ::rtl::OUString const & sListTagName, + ::rtl::OUString const & sPairTagName, + ::rtl::OUString const & sFirstTagName, + ::rtl::OUString const & sSecondTagName); + + ::std::list< ::rtl::OUString> readList( + css::uno::Reference<css::xml::dom::XNode> const & parent, + ::rtl::OUString const & sListTagName, + ::rtl::OUString const & sMemberTagName); + + /* returns the values of one particulary child element of all key elements. + */ + ::std::list< ::rtl::OUString> getOneChildFromAllEntries( + ::rtl::OUString const & sElementName); + + + /* returns the namespace which is to be written as xmlns attribute + into the root element. + */ + virtual ::rtl::OUString getDbNSName()=0; + /* return the namespace prefix which is to be registered with the XPath API. + + The prefix can then be used in XPath expressions. + */ + virtual ::rtl::OUString getNSPrefix()=0; + /* returns the name of the root element without any namespace prefix. + */ + virtual ::rtl::OUString getRootElementName()=0; + /* returns the name of xml element for each entry + */ + virtual ::rtl::OUString getKeyElementName()=0; + + + +public: + BackendDb(css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); + virtual ~BackendDb() {}; + + void removeEntry(::rtl::OUString const & url); +}; + +class RegisteredDb: public BackendDb +{ + +public: + RegisteredDb( css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); + virtual ~RegisteredDb() {}; + + + virtual void addEntry(::rtl::OUString const & url); + virtual bool getEntry(::rtl::OUString const & url); + +}; + + +} +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/inc/dp_registry.hrc b/desktop/source/deployment/registry/inc/dp_registry.hrc new file mode 100644 index 000000000000..7f8124b78d1a --- /dev/null +++ b/desktop/source/deployment/registry/inc/dp_registry.hrc @@ -0,0 +1,40 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_REGISTRY_HRC +#define INCLUDED_DP_REGISTRY_HRC + +#include "deployment.hrc" + +#define RID_STR_CANNOT_DETECT_MEDIA_TYPE (RID_DEPLOYMENT_REGISTRY_START+0) +#define RID_STR_UNSUPPORTED_MEDIA_TYPE (RID_DEPLOYMENT_REGISTRY_START+1) +#define RID_STR_ERROR_WHILE_REGISTERING (RID_DEPLOYMENT_REGISTRY_START+2) +#define RID_STR_ERROR_WHILE_REVOKING (RID_DEPLOYMENT_REGISTRY_START+3) +#define RID_STR_REGISTERING_PACKAGE (RID_DEPLOYMENT_REGISTRY_START+4) +#define RID_STR_REVOKING_PACKAGE (RID_DEPLOYMENT_REGISTRY_START+5) + +#endif diff --git a/desktop/source/deployment/registry/makefile.mk b/desktop/source/deployment/registry/makefile.mk new file mode 100644 index 000000000000..e45cec272ca7 --- /dev/null +++ b/desktop/source/deployment/registry/makefile.mk @@ -0,0 +1,49 @@ +#************************************************************************* +# +# 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 = deployment_registry +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE : settings.mk + +SRS1NAME = $(TARGET) +SRC1FILES = \ + dp_registry.src + +INCPRE += inc + +SLOFILES = \ + $(SLO)$/dp_backend.obj \ + $(SLO)$/dp_registry.obj \ + $(SLO)$/dp_backenddb.obj + +.INCLUDE : ..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/registry/package/dp_extbackenddb.cxx b/desktop/source/deployment/registry/package/dp_extbackenddb.cxx new file mode 100644 index 000000000000..c3b0c092c0f7 --- /dev/null +++ b/desktop/source/deployment/registry/package/dp_extbackenddb.cxx @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "rtl/string.h" +#include "rtl/bootstrap.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "dp_misc.h" + +#include "dp_extbackenddb.hxx" + + +namespace css = ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +#define EXTENSION_REG_NS "http://openoffice.org/extensionmanager/extension-registry/2010" +#define NS_PREFIX "ext" +#define ROOT_ELEMENT_NAME "extension-backend-db" +#define KEY_ELEMENT_NAME "extension" + +namespace dp_registry { +namespace backend { +namespace bundle { + +ExtensionBackendDb::ExtensionBackendDb( + Reference<XComponentContext> const & xContext, + ::rtl::OUString const & url):BackendDb(xContext, url) +{ + +} + +OUString ExtensionBackendDb::getDbNSName() +{ + return OUSTR(EXTENSION_REG_NS); +} + +OUString ExtensionBackendDb::getNSPrefix() +{ + return OUSTR(NS_PREFIX); +} + +OUString ExtensionBackendDb::getRootElementName() +{ + return OUSTR(ROOT_ELEMENT_NAME); +} + +OUString ExtensionBackendDb::getKeyElementName() +{ + return OUSTR(KEY_ELEMENT_NAME); +} + +void ExtensionBackendDb::addEntry(::rtl::OUString const & url, Data const & data) +{ + try{ + Reference<css::xml::dom::XNode> extensionNodeNode = writeKeyElement(url); + writeVectorOfPair( + data.items, + OUSTR("extension-items"), + OUSTR("item"), + OUSTR("url"), + OUSTR("media-type"), + extensionNodeNode); + save(); + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +ExtensionBackendDb::Data ExtensionBackendDb::getEntry(::rtl::OUString const & url) +{ + try + { + ExtensionBackendDb::Data retData; + Reference<css::xml::dom::XNode> aNode = getKeyElement(url); + + if (aNode.is()) + { + retData.items = + readVectorOfPair( + aNode, + OUSTR("extension-items"), + OUSTR("item"), + OUSTR("url"), + OUSTR("media-type")); + } + return retData; + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to read data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +} // namespace bundle +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/package/dp_extbackenddb.hxx b/desktop/source/deployment/registry/package/dp_extbackenddb.hxx new file mode 100644 index 000000000000..ac57bd794e03 --- /dev/null +++ b/desktop/source/deployment/registry/package/dp_extbackenddb.hxx @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + + +#if ! defined INCLUDED_DP_EXTBACKENDDB_HXX +#define INCLUDED_DP_EXTBACKENDDB_HXX + +#include "rtl/ustring.hxx" +#include "rtl/string.hxx" +#include <vector> +#include "dp_backenddb.hxx" + +namespace css = ::com::sun::star; + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } + namespace xml { namespace dom { + class XDocument; + class XNode; + }} + namespace xml { namespace xpath { + class XXPathAPI; + }} +}}} + +namespace dp_registry { +namespace backend { +namespace bundle { + +/* The XML file stores the extensions which are currently registered. + They will be removed when they are revoked. + */ +class ExtensionBackendDb: public dp_registry::backend::BackendDb +{ +protected: + virtual ::rtl::OUString getDbNSName(); + virtual ::rtl::OUString getNSPrefix(); + virtual ::rtl::OUString getRootElementName(); + virtual ::rtl::OUString getKeyElementName(); + +public: + struct Data + { + /* every element consists of a pair of the url to the item (jar,rdb, etc) + and the media type + */ + ::std::vector< ::std::pair< ::rtl::OUString, ::rtl::OUString> > items; + typedef ::std::vector< + ::std::pair< ::rtl::OUString, ::rtl::OUString> >::const_iterator ITC_ITEMS; + + }; + +public: + + ExtensionBackendDb( css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); + + void addEntry(::rtl::OUString const & url, Data const & data); + + Data getEntry(::rtl::OUString const & url); + +}; + + + +} +} +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/package/dp_package.cxx b/desktop/source/deployment/registry/package/dp_package.cxx new file mode 100755 index 000000000000..b084d87898f6 --- /dev/null +++ b/desktop/source/deployment/registry/package/dp_package.cxx @@ -0,0 +1,1652 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_package.hrc" +#include "dp_backend.h" +#include "dp_ucb.h" +#include "dp_interact.h" +#include "dp_dependencies.hxx" +#include "dp_platform.hxx" +#include "dp_descriptioninfoset.hxx" +#include "dp_identifier.hxx" +#include "rtl/uri.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "cppuhelper/implbase1.hxx" +#include "ucbhelper/content.hxx" +#include "svl/inettype.hxx" +#include "comphelper/anytostring.hxx" +#include "comphelper/makesequence.hxx" +#include "comphelper/sequence.hxx" +#include "com/sun/star/lang/WrappedTargetException.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/beans/UnknownPropertyException.hpp" +#include "com/sun/star/graphic/XGraphic.hpp" +#include "com/sun/star/graphic/XGraphicProvider.hpp" +#include "com/sun/star/io/XOutputStream.hpp" +#include "com/sun/star/io/XInputStream.hpp" +#include "com/sun/star/task/InteractionClassification.hpp" +#include "com/sun/star/task/XInteractionApprove.hpp" +#include "com/sun/star/ucb/XInteractionReplaceExistingData.hpp" +#include "com/sun/star/ucb/NameClashResolveRequest.hpp" +#include "com/sun/star/ucb/XContentAccess.hpp" +#include "com/sun/star/ucb/NameClash.hpp" +#include "com/sun/star/ucb/UnsupportedCommandException.hpp" +#include "com/sun/star/sdbc/XResultSet.hpp" +#include "com/sun/star/sdbc/XRow.hpp" +#include "com/sun/star/packages/manifest/XManifestReader.hpp" +#include "com/sun/star/packages/manifest/XManifestWriter.hpp" +#include "com/sun/star/deployment/DependencyException.hpp" +#include "com/sun/star/deployment/LicenseException.hpp" +#include "com/sun/star/deployment/PlatformException.hpp" +#include "com/sun/star/deployment/Prerequisites.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "com/sun/star/deployment/XPackageManager.hpp" +#include "boost/optional.hpp" +#include <vector> +#include <stdio.h> + +#include "dp_extbackenddb.hxx" +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace css = ::com::sun::star; + +using ::rtl::OUString; + +namespace dp_registry { +namespace backend { +namespace bundle { +namespace { + +typedef cppu::ImplInheritanceHelper1<PackageRegistryBackend, + lang::XServiceInfo> ImplBaseT; + +//============================================================================== +class BackendImpl : public ImplBaseT +{ + class PackageImpl : public ::dp_registry::backend::Package + { + BackendImpl * getMyBackend() const; + /** constains the old tooltip description for the Extension Manager GUI in OOo v.2.x + We keep it for backward compatibility. + */ + OUString m_oldDescription; + OUString m_url_expanded; + const bool m_legacyBundle; + Sequence< Reference<deployment::XPackage> > m_bundle; + Sequence< Reference<deployment::XPackage> > * m_pBundle; + + ExtensionBackendDb::Data m_dbData; + + Reference<deployment::XPackage> bindBundleItem( + OUString const & url, OUString const & mediaType, + sal_Bool bRemoved, //that is, useing data base information + OUString const & identifier, + Reference<ucb::XCommandEnvironment> const & xCmdEnv, + bool notifyDetectionError = true ); + + typedef ::std::vector< Reference<deployment::XPackage> > t_packagevec; + void scanBundle( + t_packagevec & bundle, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ); + void scanLegacyBundle( + t_packagevec & bundle, + OUString const & url, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv, + bool skip_registration = false ); + ::std::vector<Reference<deployment::XPackage> > getPackagesFromDb( + Reference<ucb::XCommandEnvironment> const & xCmdEnv); + bool checkPlatform( + Reference<ucb::XCommandEnvironment > const & environment); + + bool checkDependencies( + Reference<ucb::XCommandEnvironment > const & + environment, + DescriptionInfoset const & description); + // throws css::uno::RuntimeException, + // css::deployment::DeploymentException + + ::sal_Bool checkLicense( + Reference< ucb::XCommandEnvironment > const & xCmdEnv, + DescriptionInfoset const & description, bool bNoLicenseChecking) + throw (deployment::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + RuntimeException); + // @throws DeploymentException + OUString getTextFromURL( + const Reference< ucb::XCommandEnvironment >& xCmdEnv, + const OUString& licenseUrl); + + DescriptionInfoset getDescriptionInfoset(); + + // Package + virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ); + + virtual void SAL_CALL disposing(); + + + + public: + PackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, + OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool legacyBundle, + bool bRemoved, + OUString const & identifier); + + // XPackage + virtual sal_Bool SAL_CALL isBundle() throw (RuntimeException); + + virtual Sequence< Reference<deployment::XPackage> > SAL_CALL getBundle( + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deployment::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, RuntimeException); + virtual OUString SAL_CALL getDescription() + throw (deployment::ExtensionRemovedException, RuntimeException); + + virtual void SAL_CALL exportTo( + OUString const & destFolderURL, OUString const & newTitle, + sal_Int32 nameClashAction, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deployment::ExtensionRemovedException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + RuntimeException); + + virtual ::sal_Int32 SAL_CALL checkPrerequisites( + const Reference< task::XAbortChannel >& xAbortChannel, + const Reference< ucb::XCommandEnvironment >& xCmdEnv, + ::sal_Bool noLicenseChecking) + throw (deployment::ExtensionRemovedException, + deployment::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + RuntimeException); + + virtual ::sal_Bool SAL_CALL checkDependencies( + const Reference< ucb::XCommandEnvironment >& xCmdEnv ) + throw (deployment::DeploymentException, + deployment::ExtensionRemovedException, + ucb::CommandFailedException, + RuntimeException); + + virtual beans::Optional<OUString> SAL_CALL getIdentifier() + throw (RuntimeException); + + virtual OUString SAL_CALL getVersion() + throw (deployment::ExtensionRemovedException, RuntimeException); + + virtual Sequence<OUString> SAL_CALL getUpdateInformationURLs() + throw (deployment::ExtensionRemovedException, RuntimeException); + + virtual beans::StringPair SAL_CALL getPublisherInfo() + throw (deployment::ExtensionRemovedException, RuntimeException); + + virtual OUString SAL_CALL getDisplayName() + throw (deployment::ExtensionRemovedException, RuntimeException); + + virtual Reference< graphic::XGraphic > SAL_CALL + getIcon( ::sal_Bool bHighContrast ) + throw (deployment::ExtensionRemovedException, + RuntimeException); + }; + friend class PackageImpl; + + Reference<deployment::XPackageRegistry> m_xRootRegistry; + const Reference<deployment::XPackageTypeInfo> m_xBundleTypeInfo; + const Reference<deployment::XPackageTypeInfo> m_xLegacyBundleTypeInfo; + Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos; + + std::auto_ptr<ExtensionBackendDb> m_backendDb; + + void addDataToDb(OUString const & url, ExtensionBackendDb::Data const & data); + ExtensionBackendDb::Data readDataFromDb(OUString const & url); + void deleteDataFromDb(OUString const & url); + + // PackageRegistryBackend + virtual Reference<deployment::XPackage> bindPackage_( + OUString const & url, OUString const & mediaType, + sal_Bool bRemoved, OUString const & identifier, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ); + + virtual void SAL_CALL disposing(); + +public: + BackendImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext, + Reference<deployment::XPackageRegistry> const & xRootRegistry ); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() throw (RuntimeException); + virtual sal_Bool SAL_CALL supportsService( OUString const& name ) + throw (RuntimeException); + virtual Sequence<OUString> SAL_CALL getSupportedServiceNames() + throw (RuntimeException); + + // XPackageRegistry + virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() throw (RuntimeException); + + using ImplBaseT::disposing; +}; + +//Used to find a XPackage with a particular URL +class XPackage_eq : public std::unary_function<Reference<deployment::XPackage>, bool> +{ + OUString m_URL; +public: + explicit XPackage_eq(const OUString & s) : m_URL(s) {} + bool operator() (const Reference<deployment::XPackage> & p) const + { + return m_URL.equals(p->getURL()); + } +}; + +//______________________________________________________________________________ +BackendImpl::BackendImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext, + Reference<deployment::XPackageRegistry> const & xRootRegistry ) + : ImplBaseT( args, xComponentContext ), + m_xRootRegistry( xRootRegistry ), + m_xBundleTypeInfo( new Package::TypeInfo( + OUSTR("application/vnd.sun.star.package-bundle"), + OUSTR("*.oxt;*.uno.pkg"), + getResourceString(RID_STR_PACKAGE_BUNDLE), + RID_IMG_DEF_PACKAGE_BUNDLE, + RID_IMG_DEF_PACKAGE_BUNDLE_HC ) ), + m_xLegacyBundleTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.legacy-package-bundle"), + OUSTR("*.zip"), + m_xBundleTypeInfo->getShortDescription(), + RID_IMG_DEF_PACKAGE_BUNDLE, + RID_IMG_DEF_PACKAGE_BUNDLE_HC ) ), + m_typeInfos(2) +{ + m_typeInfos[ 0 ] = m_xBundleTypeInfo; + m_typeInfos[ 1 ] = m_xLegacyBundleTypeInfo; + + if (!transientMode()) + { + OUString dbFile = makeURL(getCachePath(), getImplementationName()); + dbFile = makeURL(dbFile, OUSTR("backenddb.xml")); + m_backendDb.reset( + new ExtensionBackendDb(getComponentContext(), dbFile)); + } +} + +//______________________________________________________________________________ +void BackendImpl::disposing() +{ + m_xRootRegistry.clear(); + PackageRegistryBackend::disposing(); +} + +// XServiceInfo +OUString BackendImpl::getImplementationName() throw (RuntimeException) +{ + return OUSTR("com.sun.star.comp.deployment.bundle.PackageRegistryBackend"); +} + +sal_Bool BackendImpl::supportsService( OUString const& name ) + throw (RuntimeException) +{ + return getSupportedServiceNames()[0].equals(name); +} + +Sequence<OUString> BackendImpl::getSupportedServiceNames() + throw (RuntimeException) +{ + return comphelper::makeSequence( + OUString::createFromAscii(BACKEND_SERVICE_NAME) ); +} + +// XPackageRegistry +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackageTypeInfo> > +BackendImpl::getSupportedPackageTypes() throw (RuntimeException) +{ + return m_typeInfos; +} + + + +// PackageRegistryBackend +//______________________________________________________________________________ +Reference<deployment::XPackage> BackendImpl::bindPackage_( + OUString const & url, OUString const & mediaType_, + sal_Bool bRemoved, OUString const & identifier, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + OUString mediaType( mediaType_ ); + if (mediaType.getLength() == 0) + { + // detect media-type: + ::ucbhelper::Content ucbContent; + if (create_ucb_content( &ucbContent, url, xCmdEnv )) + { + if (ucbContent.isFolder()) + { + //Every .oxt, uno.pkg file must contain a META-INF folder + ::ucbhelper::Content metaInfContent; + if (create_ucb_content( + &metaInfContent, makeURL( url, OUSTR("META-INF") ), + xCmdEnv, false /* no throw */ )) + { + mediaType = OUSTR("application/vnd.sun.star.package-bundle"); + } + //No support of legacy bundles, because every folder could be one. + } + else + { + const OUString title( ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>() ); + if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".oxt") ) || + title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".uno.pkg") )) + mediaType = OUSTR("application/vnd.sun.star.package-bundle"); + else if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".zip") )) + mediaType = + OUSTR("application/vnd.sun.star.legacy-package-bundle"); + } + } + if (mediaType.getLength() == 0) + throw lang::IllegalArgumentException( + StrCannotDetectMediaType::get() + url, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); + } + + String type, subType; + INetContentTypeParameterList params; + if (INetContentTypes::parse( mediaType, type, subType, ¶ms )) + { + if (type.EqualsIgnoreCaseAscii("application")) + { + + //In case a XPackage is created for a removed extension, we cannot + //obtain the name + OUString name; + if (!bRemoved) + { + ::ucbhelper::Content ucbContent( url, xCmdEnv ); + name = ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>(); + } + if (subType.EqualsIgnoreCaseAscii("vnd.sun.star.package-bundle")) { + return new PackageImpl( + this, url, name, m_xBundleTypeInfo, false, bRemoved, + identifier); + } + else if (subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.legacy-package-bundle")) { + return new PackageImpl( + this, url, name, m_xLegacyBundleTypeInfo, true, bRemoved, + identifier); + } + } + } + throw lang::IllegalArgumentException( + StrUnsupportedMediaType::get() + mediaType, + static_cast<OWeakObject *>(this), + static_cast<sal_Int16>(-1) ); +} + +void BackendImpl::addDataToDb( + OUString const & url, ExtensionBackendDb::Data const & data) +{ + if (m_backendDb.get()) + m_backendDb->addEntry(url, data); +} + +ExtensionBackendDb::Data BackendImpl::readDataFromDb( + OUString const & url) +{ + ExtensionBackendDb::Data data; + if (m_backendDb.get()) + data = m_backendDb->getEntry(url); + return data; +} + +void BackendImpl::deleteDataFromDb(OUString const & url) +{ + if (m_backendDb.get()) + m_backendDb->removeEntry(url); +} + + +//############################################################################## + +BackendImpl::PackageImpl::PackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, + OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool legacyBundle, bool bRemoved, OUString const & identifier) + : Package( myBackend, url, name, name /* display-name */, + xPackageType, bRemoved, identifier), + m_url_expanded( expandUnoRcUrl( url ) ), + m_legacyBundle( legacyBundle ), + m_pBundle( 0 ) +{ + if (bRemoved) + m_dbData = getMyBackend()->readDataFromDb(url); +} + +BackendImpl * BackendImpl::PackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); + if (NULL == pBackend) + { + //May throw a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<PackageImpl *>(this))); + } + return pBackend; +} +//______________________________________________________________________________ +void BackendImpl::PackageImpl::disposing() +{ + sal_Int32 len = m_bundle.getLength(); + Reference<deployment::XPackage> const * p = m_bundle.getConstArray(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + try_dispose( p[ pos ] ); + m_bundle.realloc( 0 ); + + Package::disposing(); +} + +// Package +//______________________________________________________________________________ +beans::Optional< beans::Ambiguous<sal_Bool> > +BackendImpl::PackageImpl::isRegistered_( + ::osl::ResettableMutexGuard &, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + //In case the object was created for a removed extension (m_bRemoved = true) + //but the extension is not registered, then bundle will be empty. Then + //the return value will be Optional<...>.IsPresent= false. Althoug this is + //not true, this does not matter. Then registerPackage or revokePackage + //would never be called for the items. But since the extension is removed + //and not registered anyway, this does not matter. + const Sequence< Reference<deployment::XPackage> > bundle( + getBundle( abortChannel.get(), xCmdEnv ) ); + + bool reg = false; + bool present = false; + bool ambig = false; + for ( sal_Int32 pos = bundle.getLength(); pos--; ) + { + Reference<deployment::XPackage> const & xPackage = bundle[ pos ]; + Reference<task::XAbortChannel> xSubAbortChannel( + xPackage->createAbortChannel() ); + AbortChannel::Chain chain( abortChannel, xSubAbortChannel ); + beans::Optional< beans::Ambiguous<sal_Bool> > option( + xPackage->isRegistered( xSubAbortChannel, xCmdEnv ) ); + + //present = true if at least one bundle item has this value. + //reg = true if all bundle items have an option value (option.IsPresent == 1) + //and all have value of true (option.Value.Value == true) + //If not, then the bundle has the status of not registered and ambiguous. + if (option.IsPresent) + { + beans::Ambiguous<sal_Bool> const & status = option.Value; + if (present) + { + //we never come here in the first iteration + if (reg != (status.Value != sal_False)) { + + ambig = true; + reg = false; + break; + } + } + else + { + //we always come here in the first iteration + reg = status.Value; + present = true; + } + } + } + return beans::Optional< beans::Ambiguous<sal_Bool> >( + present, beans::Ambiguous<sal_Bool>(reg, ambig) ); +} + +OUString BackendImpl::PackageImpl::getTextFromURL( + const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv, + const OUString& licenseUrl) +{ + try + { + ::ucbhelper::Content descContent(licenseUrl, xCmdEnv); + ::rtl::ByteSequence seq = dp_misc::readFile(descContent); + return OUString( reinterpret_cast<sal_Char const *>( + seq.getConstArray()), seq.getLength(), RTL_TEXTENCODING_UTF8); + } + catch (css::uno::Exception&) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Could not read file ") + licenseUrl, 0, exc); + } + +} + +DescriptionInfoset BackendImpl::PackageImpl::getDescriptionInfoset() +{ + return dp_misc::getDescriptionInfoset(m_url_expanded); +} + +bool BackendImpl::PackageImpl::checkPlatform( + css::uno::Reference< css::ucb::XCommandEnvironment > const & environment) +{ + bool ret = false; + DescriptionInfoset info(getDescriptionInfoset()); + Sequence<OUString> platforms(info.getSupportedPlaforms()); + if (hasValidPlatform(platforms)) + { + ret = true; + } + else + { + ret = false; + rtl::OUString msg( + RTL_CONSTASCII_USTRINGPARAM("unsupported platform")); + Any e( + css::deployment::PlatformException( + msg, static_cast<OWeakObject *>(this), this)); + if (!interactContinuation( + e, cppu::UnoType< css::task::XInteractionApprove >::get(), + environment, NULL, NULL)) + { + throw css::deployment::DeploymentException( + msg, static_cast<OWeakObject *>(this), e); + } + } + return ret; +} + + +bool BackendImpl::PackageImpl::checkDependencies( + css::uno::Reference< css::ucb::XCommandEnvironment > const & environment, + DescriptionInfoset const & description) +{ + css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > + unsatisfied(dp_misc::Dependencies::check(description)); + + if (unsatisfied.getLength() == 0) { + return true; + } else { + rtl::OUString msg( + RTL_CONSTASCII_USTRINGPARAM("unsatisfied dependencies")); + Any e( + css::deployment::DependencyException( + msg, static_cast<OWeakObject *>(this), unsatisfied)); + if (!interactContinuation( + e, cppu::UnoType< css::task::XInteractionApprove >::get(), + environment, NULL, NULL)) + { + throw css::deployment::DeploymentException( + msg, static_cast<OWeakObject *>(this), e); + } + return false; + } +} + +::sal_Bool BackendImpl::PackageImpl::checkLicense( + css::uno::Reference< css::ucb::XCommandEnvironment > const & xCmdEnv, + DescriptionInfoset const & info, bool alreadyInstalled) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::uno::RuntimeException) +{ + try + { + ::boost::optional<SimpleLicenseAttributes> simplLicAttr + = info.getSimpleLicenseAttributes(); + if (! simplLicAttr) + return true; + OUString sLic = info.getLocalizedLicenseURL(); + //If we do not get a localized licence then there is an error in the description.xml + //This should be handled by using a validating parser. Therefore we assume that no + //license is available. + if (sLic.getLength() == 0) + throw css::deployment::DeploymentException( + OUSTR("Could not obtain path to license. Possible error in description.xml"), 0, Any()); + OUString sHref = m_url_expanded + OUSTR("/") + sLic; + OUString sLicense = getTextFromURL(xCmdEnv, sHref); + ////determine who has to agree to the license + //check correct value for attribute + if ( ! (simplLicAttr->acceptBy.equals(OUSTR("user")) || simplLicAttr->acceptBy.equals(OUSTR("admin")))) + throw css::deployment::DeploymentException( + OUSTR("Could not obtain attribute simple-lincense@accept-by or it has no valid value"), 0, Any()); + + + //Only use interaction if there is no version of this extension already installed + //and the suppress-on-update flag is not set for the new extension + // alreadyInstalled | bSuppressOnUpdate | show license + //---------------------------------------- + // 0 | 0 | 1 + // 0 | 1 | 1 + // 1 | 0 | 1 + // 1 | 1 | 0 + + if ( !(alreadyInstalled && simplLicAttr->suppressOnUpdate)) + { + css::deployment::LicenseException licExc( + OUString(), 0, getDisplayName(), sLicense, + simplLicAttr->acceptBy); + bool approve = false; + bool abort = false; + if (! interactContinuation( + Any(licExc), task::XInteractionApprove::static_type(), xCmdEnv, &approve, &abort )) + throw css::deployment::DeploymentException( + OUSTR("Could not interact with user."), 0, Any()); + + if (approve == true) + return true; + else + return false; + //throw css::deployment::DeploymentException( + // OUSTR("Extension Manager: User declined the license."), + // static_cast<OWeakObject*>(this), + // Any( css::deployment::LicenseException(OUSTR("User declined the license."), 0, m_name, sLicense))); + } + return true; + } catch (css::ucb::CommandFailedException&) { + throw; + } catch (css::ucb::CommandAbortedException&) { + throw; + } catch (css::deployment::DeploymentException&) { + throw; + } catch (css::uno::RuntimeException&) { + throw; + } catch (css::uno::Exception&) { + Any anyExc = cppu::getCaughtException(); + throw css::deployment::DeploymentException(OUSTR("Unexpected exception"), 0, anyExc); + } +} + +::sal_Int32 BackendImpl::PackageImpl::checkPrerequisites( + const css::uno::Reference< css::task::XAbortChannel >&, + const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv, + sal_Bool alreadyInstalled) + throw (css::deployment::DeploymentException, + css::deployment::ExtensionRemovedException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::uno::RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + DescriptionInfoset info = getDescriptionInfoset(); + if (!info.hasDescription()) + return 0; + + //always return LICENSE as long as the user did not accept the license + //so that XExtensonManager::checkPrerequisitesAndEnable will again + //check the license + if (!checkPlatform(xCmdEnv)) + return deployment::Prerequisites::PLATFORM | + deployment::Prerequisites::LICENSE; + else if(!checkDependencies(xCmdEnv, info)) + return deployment::Prerequisites::DEPENDENCIES | + deployment::Prerequisites::LICENSE; + else if(!checkLicense(xCmdEnv, info, alreadyInstalled)) + return deployment::Prerequisites::LICENSE; + else + return 0; +} + +::sal_Bool BackendImpl::PackageImpl::checkDependencies( + const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv ) + throw (deployment::DeploymentException, + deployment::ExtensionRemovedException, + ucb::CommandFailedException, + RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + DescriptionInfoset info = getDescriptionInfoset(); + if (!info.hasDescription()) + return sal_True; + + return checkDependencies(xCmdEnv, info); +} + +beans::Optional<OUString> BackendImpl::PackageImpl::getIdentifier() + throw (RuntimeException) +{ + OUString identifier; + if (m_bRemoved) + identifier = m_identifier; + else + identifier = dp_misc::generateIdentifier( + getDescriptionInfoset().getIdentifier(), m_name); + + return beans::Optional<OUString>( + true, identifier); +} + +OUString BackendImpl::PackageImpl::getVersion() + throw (deployment::ExtensionRemovedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return getDescriptionInfoset().getVersion(); +} + +Sequence<OUString> BackendImpl::PackageImpl::getUpdateInformationURLs() + throw (deployment::ExtensionRemovedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + return getDescriptionInfoset().getUpdateInformationUrls(); +} + +beans::StringPair BackendImpl::PackageImpl::getPublisherInfo() + throw (deployment::ExtensionRemovedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + ::std::pair< OUString, OUString > aInfo = getDescriptionInfoset().getLocalizedPublisherNameAndURL(); + beans::StringPair aStrPair( aInfo.first, aInfo.second ); + return aStrPair; +} + +//______________________________________________________________________________ +uno::Reference< graphic::XGraphic > BackendImpl::PackageImpl::getIcon( sal_Bool bHighContrast ) + throw (deployment::ExtensionRemovedException, RuntimeException ) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + + uno::Reference< graphic::XGraphic > xGraphic; + + OUString aIconURL = getDescriptionInfoset().getIconURL( bHighContrast ); + if ( aIconURL.getLength() ) + { + OUString aFullIconURL = m_url_expanded + OUSTR("/") + aIconURL; + + uno::Reference< XComponentContext > xContext( getMyBackend()->getComponentContext() ); + uno::Reference< graphic::XGraphicProvider > xGraphProvider( + xContext->getServiceManager()->createInstanceWithContext( OUSTR( "com.sun.star.graphic.GraphicProvider" ), xContext ), + uno::UNO_QUERY ); + + if ( xGraphProvider.is() ) + { + uno::Sequence< beans::PropertyValue > aMediaProps( 1 ); + aMediaProps[0].Name = OUSTR( "URL" ); + aMediaProps[0].Value <<= aFullIconURL; + + xGraphic = xGraphProvider->queryGraphic( aMediaProps ); + } + } + + return xGraphic; +} + +//______________________________________________________________________________ +void BackendImpl::PackageImpl::processPackage_( + ::osl::ResettableMutexGuard &, + bool doRegisterPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + const Sequence< Reference<deployment::XPackage> > bundle( + getBundle( abortChannel.get(), xCmdEnv ) ); + + if (doRegisterPackage) + { + ExtensionBackendDb::Data data; + const sal_Int32 len = bundle.getLength(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + checkAborted(abortChannel); + Reference<deployment::XPackage> const & xPackage = bundle[ pos ]; + Reference<task::XAbortChannel> xSubAbortChannel( + xPackage->createAbortChannel() ); + AbortChannel::Chain chain( abortChannel, xSubAbortChannel ); + try { + xPackage->registerPackage( startup, xSubAbortChannel, xCmdEnv ); + } + catch (Exception &) + { + //We even try a rollback if the user cancelled the action (CommandAbortedException) + //in order to prevent invalid database entries. + Any exc( ::cppu::getCaughtException() ); + // try to handle exception, notify: + bool approve = false, abort = false; + if (! interactContinuation( + Any( lang::WrappedTargetException( + OUSTR("bundle item registration error!"), + static_cast<OWeakObject *>(this), exc ) ), + task::XInteractionApprove::static_type(), xCmdEnv, + &approve, &abort )) { + OSL_ASSERT( !approve && !abort ); + if (m_legacyBundle) // default for legacy packages: ignore + continue; + // no selection at all, so rethrow; + // no C++ rethrow after getCaughtException(), + // see cppuhelper/exc_hlp.hxx: + ::cppu::throwException(exc); + } + if (approve && !abort) // ignore error, just continue + continue; + + { + ProgressLevel progress( + xCmdEnv, OUSTR("rollback...") ); + // try rollback + for ( ; pos--; ) + { + try { + bundle[ pos ]->revokePackage( + xSubAbortChannel, xCmdEnv ); + } + catch (Exception &) + { + OSL_ENSURE( 0, ::rtl::OUStringToOString( + ::comphelper::anyToString( + ::cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 ).getStr() ); + // ignore any errors of rollback + } + } + progress.update( OUSTR("rollback finished.") ); + } + + deployment::DeploymentException dpExc; + if (exc >>= dpExc) { + throw ucb::CommandFailedException( + dpExc.Message, dpExc.Context, dpExc.Cause ); + } + else { + // rethrow CommandFailedException + ::cppu::throwException(exc); + } + } + data.items.push_back( + ::std::make_pair(xPackage->getURL(), + xPackage->getPackageType()->getMediaType())); + } + getMyBackend()->addDataToDb(getURL(), data); + } + else + { + // revoke in reverse order: + for ( sal_Int32 pos = bundle.getLength(); pos--; ) + { + checkAborted(abortChannel); + Reference<deployment::XPackage> const & xPackage = bundle[ pos ]; + Reference<task::XAbortChannel> xSubAbortChannel( + xPackage->createAbortChannel() ); + AbortChannel::Chain chain( abortChannel, xSubAbortChannel ); + try { + bundle[ pos ]->revokePackage( xSubAbortChannel, xCmdEnv ); + } + catch (RuntimeException &) { + throw; + } + catch (ucb::CommandAbortedException &) { + throw; + } + catch (Exception &) { + // CommandFailedException, DeploymentException: + Any exc( ::cppu::getCaughtException() ); + // try to handle exception, notify: + bool approve = false, abort = false; + if (! interactContinuation( + Any( lang::WrappedTargetException( + OUSTR("bundle item revocation error!"), + static_cast<OWeakObject *>(this), exc ) ), + task::XInteractionApprove::static_type(), xCmdEnv, + &approve, &abort )) { + OSL_ASSERT( !approve && !abort ); + if (m_legacyBundle) // default for legacy packages: ignore + continue; + // no selection at all, so rethrow + // no C++ rethrow after getCaughtException(), + // see cppuhelper/exc_hlp.hxx: + ::cppu::throwException(exc); + } + // ignore errors when revoking, although abort may have been + // selected + } + } + getMyBackend()->deleteDataFromDb(getURL()); + } +} + +//______________________________________________________________________________ +OUString BackendImpl::PackageImpl::getDescription() + throw (deployment::ExtensionRemovedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + + const OUString sRelativeURL(getDescriptionInfoset().getLocalizedDescriptionURL()); + OUString sDescription; + if (sRelativeURL.getLength()) + { + OUString sURL = m_url_expanded + OUSTR("/") + sRelativeURL; + + try + { + sDescription = getTextFromURL( css::uno::Reference< css::ucb::XCommandEnvironment >(), sURL ); + } + catch ( css::deployment::DeploymentException& ) + { + OSL_ENSURE( 0, ::rtl::OUStringToOString( ::comphelper::anyToString( ::cppu::getCaughtException() ), RTL_TEXTENCODING_UTF8 ).getStr() ); + } + } + + if (sDescription.getLength()) + return sDescription; + return m_oldDescription; +} + +//______________________________________________________________________________ +void BackendImpl::PackageImpl::exportTo( + OUString const & destFolderURL, OUString const & newTitle, + sal_Int32 nameClashAction, Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (ucb::CommandFailedException, + deployment::ExtensionRemovedException, + ucb::CommandAbortedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + + ::ucbhelper::Content sourceContent( m_url_expanded, xCmdEnv ); + OUString title(newTitle); + if (title.getLength() == 0) + sourceContent.getPropertyValue( StrTitle::get() ) >>= title; + OUString destURL( makeURL( destFolderURL, ::rtl::Uri::encode( + title, rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ) ); + + if (nameClashAction == ucb::NameClash::ASK) + { + if (create_ucb_content( + 0, destURL, xCmdEnv, false /* no throw */ )) { + bool replace = false, abort = false; + if (! interactContinuation( + Any( ucb::NameClashResolveRequest( + OUSTR("file already exists: ") + title, + static_cast<OWeakObject *>(this), + task::InteractionClassification_QUERY, + destFolderURL, title, OUString() ) ), + ucb::XInteractionReplaceExistingData::static_type(), xCmdEnv, + &replace, &abort ) || !replace) { + return; + } + } + } + else if (nameClashAction != ucb::NameClash::OVERWRITE) { + throw ucb::CommandFailedException( + OUSTR("unsupported nameClashAction!"), + static_cast<OWeakObject *>(this), Any() ); + } + erase_path( destURL, xCmdEnv ); + + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.zip://") ); + buf.append( ::rtl::Uri::encode( destURL, + rtl_UriCharClassRegName, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + buf.append( static_cast<sal_Unicode>('/') ); + OUString destFolder( buf.makeStringAndClear() ); + + ::ucbhelper::Content destFolderContent( destFolder, xCmdEnv ); + { + // transfer every item of folder into zip: + Reference<sdbc::XResultSet> xResultSet( + sourceContent.createCursor( + Sequence<OUString>(), + ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS ) ); + ProgressLevel progress( xCmdEnv, OUString() ); + while (xResultSet->next()) + { + ::ucbhelper::Content subContent( + Reference<ucb::XContentAccess>( + xResultSet, UNO_QUERY_THROW )->queryContent(), xCmdEnv ); + if (! destFolderContent.transferContent( + subContent, ::ucbhelper::InsertOperation_COPY, + OUString(), ucb::NameClash::OVERWRITE )) + throw RuntimeException( OUSTR("UCB transferContent() failed!"), + static_cast<OWeakObject *>(this) ); + progress.update( Any() ); // animating progress bar + } + } + + // assure META-INF folder: + ::ucbhelper::Content metainfFolderContent; + create_folder( &metainfFolderContent, + makeURL( destFolderContent.getURL(), OUSTR("META-INF") ), + xCmdEnv ); + + if (m_legacyBundle) + { + // easy to migrate legacy bundles to new format: + // just export them once using a .oxt name! + // set detected media-types of any bundle item: + + // collect all manifest entries: + Sequence< Reference<deployment::XPackage> > bundle; + try { + bundle = getBundle( Reference<task::XAbortChannel>(), xCmdEnv ); + } + // xxx todo: think about exception specs: + catch (deployment::DeploymentException &) { + OSL_ENSURE( 0, ::rtl::OUStringToOString( + ::comphelper::anyToString( + ::cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 ).getStr() ); + } + catch (lang::IllegalArgumentException & exc) { + (void) exc; + OSL_ENSURE( 0, ::rtl::OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + } + + ::std::vector< Sequence<beans::PropertyValue> > manifest; + manifest.reserve( bundle.getLength() ); + sal_Int32 baseURLlen = m_url_expanded.getLength(); + Reference<deployment::XPackage> const *pbundle = bundle.getConstArray(); + const OUString strMediaType = OUSTR("MediaType"); + const OUString strFullPath = OUSTR("FullPath"); + const OUString strIsFolder = OUSTR("IsFolder"); + for ( sal_Int32 pos = bundle.getLength(); pos--; ) + { + Reference<deployment::XPackage> const & xPackage = pbundle[ pos ]; + OUString url_( expandUnoRcUrl( xPackage->getURL() ) ); + OSL_ASSERT( url_.getLength() >= baseURLlen ); + OUString fullPath; + if (url_.getLength() > baseURLlen) + fullPath = url_.copy( baseURLlen + 1 ); + ::ucbhelper::Content ucbContent( url_, xCmdEnv ); + if (ucbContent.getPropertyValue(strIsFolder).get<bool>()) + fullPath += OUSTR("/"); + Sequence<beans::PropertyValue> attribs( 2 ); + beans::PropertyValue * pattribs = attribs.getArray(); + pattribs[ 0 ].Name = strFullPath; + pattribs[ 0 ].Value <<= fullPath; + pattribs[ 1 ].Name = strMediaType; + const Reference<deployment::XPackageTypeInfo> xPackageType( + xPackage->getPackageType() ); + OUString mediaType; + OSL_ASSERT( xPackageType.is() ); + if (xPackageType.is()) + mediaType = xPackageType->getMediaType(); + else + mediaType = OUSTR("unknown"); + pattribs[ 1 ].Value <<= mediaType; + manifest.push_back( attribs ); + } + + // write into pipe: + Reference<XComponentContext> xContext( + getMyBackend()->getComponentContext() ); + Reference<packages::manifest::XManifestWriter> xManifestWriter( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.packages.manifest.ManifestWriter"), + xContext ), UNO_QUERY_THROW ); + Reference<io::XOutputStream> xPipe( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.io.Pipe"), xContext ), UNO_QUERY_THROW ); + xManifestWriter->writeManifestSequence( + xPipe, comphelper::containerToSequence(manifest) ); + + // write buffered pipe data to content: + ::ucbhelper::Content manifestContent( + makeURL( metainfFolderContent.getURL(), OUSTR("manifest.xml") ), + xCmdEnv ); + manifestContent.writeStream( + Reference<io::XInputStream>( xPipe, UNO_QUERY_THROW ), + true /* replace existing */ ); + } + else + { + // overwrite manifest.xml: + ::ucbhelper::Content manifestContent; + if ( ! create_ucb_content( + &manifestContent, + makeURL( m_url_expanded, OUSTR("META-INF/manifest.xml") ), + xCmdEnv, false ) ) + { + OSL_ENSURE( 0, "### missing META-INF/manifest.xml file!" ); + return; + } + + if (! metainfFolderContent.transferContent( + manifestContent, ::ucbhelper::InsertOperation_COPY, + OUString(), ucb::NameClash::OVERWRITE )) + throw RuntimeException( OUSTR("UCB transferContent() failed!"), + static_cast<OWeakObject *>(this) ); + } + + // xxx todo: maybe obsolete in the future + try { + destFolderContent.executeCommand( OUSTR("flush"), Any() ); + } + catch (ucb::UnsupportedCommandException &) { + } +} + +//______________________________________________________________________________ +sal_Bool BackendImpl::PackageImpl::isBundle() throw (RuntimeException) +{ + return true; +} + +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackage> > BackendImpl::PackageImpl::getBundle( + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deployment::DeploymentException, + ucb::CommandFailedException, ucb::CommandAbortedException, + lang::IllegalArgumentException, RuntimeException) +{ + Sequence< Reference<deployment::XPackage> > * pBundle = m_pBundle; + if (pBundle == 0) + { + t_packagevec bundle; + if (m_bRemoved) + { + bundle = getPackagesFromDb(xCmdEnv); + } + else + { + try { + if (m_legacyBundle) + { + // .zip legacy packages allow script.xlb, dialog.xlb in bundle + // root folder: + OUString mediaType; + // probe for script.xlb: + if (create_ucb_content( + 0, makeURL( m_url_expanded, OUSTR("script.xlb") ), + xCmdEnv, false /* no throw */ )) { + mediaType = OUSTR("application/vnd.sun.star.basic-library"); + } + // probe for dialog.xlb: + else if (create_ucb_content( + 0, makeURL( m_url_expanded, OUSTR("dialog.xlb") ), + xCmdEnv, false /* no throw */ )) + mediaType = OUSTR("application/vnd.sun.star." + "dialog-library"); + + if (mediaType.getLength() > 0) { + const Reference<deployment::XPackage> xPackage( + bindBundleItem( getURL(), mediaType, false, OUString(), + xCmdEnv ) ); + if (xPackage.is()) + bundle.push_back( xPackage ); + // continue scanning: + } + scanLegacyBundle( bundle, getURL(), + AbortChannel::get(xAbortChannel), xCmdEnv ); + } + else + { + // .oxt: + scanBundle( bundle, AbortChannel::get(xAbortChannel), xCmdEnv ); + } + + } + catch (RuntimeException &) { + throw; + } + catch (ucb::CommandFailedException &) { + throw; + } + catch (ucb::CommandAbortedException &) { + throw; + } + catch (deployment::DeploymentException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + throw deployment::DeploymentException( + OUSTR("error scanning bundle: ") + getURL(), + static_cast<OWeakObject *>(this), exc ); + } + } + + // sort: schema before config data, typelibs before components: + Sequence< Reference<deployment::XPackage> > ret( bundle.size() ); + Reference<deployment::XPackage> * pret = ret.getArray(); + sal_Int32 lower_end = 0; + sal_Int32 upper_end = ret.getLength(); + t_packagevec::const_iterator iPos( bundle.begin() ); + t_packagevec::const_iterator const iEnd( bundle.end() ); + for ( ; iPos != iEnd; ++iPos ) + { + const Reference<deployment::XPackageTypeInfo> xPackageType( + (*iPos)->getPackageType() ); + OSL_ASSERT( xPackageType.is() ); + if (xPackageType.is()) { + const OUString mediaType( xPackageType->getMediaType() ); + String type, subType; + INetContentTypeParameterList params; + if (INetContentTypes::parse( + mediaType, type, subType, ¶ms ) && + type.EqualsIgnoreCaseAscii("application") && + (subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.uno-component") || + subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.configuration-data"))) + { + --upper_end; + pret[ upper_end ] = *iPos; + continue; + } + } + pret[ lower_end ] = *iPos; + ++lower_end; + } + OSL_ASSERT( lower_end == upper_end ); + + const ::osl::MutexGuard guard( getMutex() ); + pBundle = m_pBundle; + if (pBundle == 0) { + m_bundle = ret; + pBundle = &m_bundle; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + m_pBundle = pBundle; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + return *pBundle; +} + +inline bool isBundle_( OUString const & mediaType ) +{ + // xxx todo: additional parsing? + return mediaType.getLength() > 0 && + (mediaType.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/vnd.sun.star.package-bundle") ) || + mediaType.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/vnd.sun.star.legacy-package-bundle") )); +} + +//______________________________________________________________________________ +Reference<deployment::XPackage> BackendImpl::PackageImpl::bindBundleItem( + OUString const & url, OUString const & mediaType, + sal_Bool bRemoved, OUString const & identifier, + Reference<ucb::XCommandEnvironment> const & xCmdEnv, + bool notifyDetectionError ) +{ + // ignore any nested bundles: + if (isBundle_(mediaType)) + return Reference<deployment::XPackage>(); + + Reference<deployment::XPackage>xPackage; + try { + xPackage.set( getMyBackend()->m_xRootRegistry->bindPackage( + url, mediaType, bRemoved, identifier, xCmdEnv ) ); + OSL_ASSERT( xPackage.is() ); + } + catch (RuntimeException &) { + throw; + } + catch (ucb::CommandFailedException &) { + // ignore already handled error + } + catch (Exception &) { + const Any exc( ::cppu::getCaughtException() ); + if (notifyDetectionError || + !exc.isExtractableTo( + ::getCppuType( reinterpret_cast< + lang::IllegalArgumentException const *>(0) ) )) + { + interactContinuation( + Any( lang::WrappedTargetException( + OUSTR("bundle item error!"), + static_cast<OWeakObject *>(this), exc ) ), + task::XInteractionApprove::static_type(), xCmdEnv, 0, 0 ); + } + } + + if (xPackage.is()) { + const Reference<deployment::XPackageTypeInfo> xPackageType( + xPackage->getPackageType() ); + OSL_ASSERT( xPackageType.is() ); + // ignore any nested bundles: + if (xPackageType.is() && isBundle_( xPackageType->getMediaType() )) + xPackage.clear(); + } + return xPackage; +} + +//______________________________________________________________________________ +void BackendImpl::PackageImpl::scanBundle( + t_packagevec & bundle, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + OSL_ASSERT( !m_legacyBundle ); + + ::ucbhelper::Content manifestContent; + if (! create_ucb_content( + &manifestContent, + makeURL( m_url_expanded, OUSTR("META-INF/manifest.xml") ), + xCmdEnv, false /* no throw */ )) + { + OSL_ENSURE( 0, "### missing META-INF/manifest.xml file!" ); + return; + } + + + const lang::Locale officeLocale = getOfficeLocale(); + OUString descrFile; + lang::Locale descrFileLocale; + + const Reference<XComponentContext> xContext( + getMyBackend()->getComponentContext() ); + Reference<packages::manifest::XManifestReader> xManifestReader( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.packages.manifest.ManifestReader"), + xContext ), UNO_QUERY_THROW ); + const Sequence< Sequence<beans::PropertyValue> > manifestSeq( + xManifestReader->readManifestSequence( manifestContent.openStream() ) ); + const OUString packageRootURL( getURL() ); + for ( sal_Int32 pos = manifestSeq.getLength(); pos--; ) + { + OUString fullPath, mediaType; + Sequence<beans::PropertyValue> const & attribs = manifestSeq[ pos ]; + for ( sal_Int32 i = attribs.getLength(); i--; ) + { + if (fullPath.getLength() > 0 && mediaType.getLength() > 0) + break; + if (attribs[i].Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("FullPath") )) + attribs[i].Value >>= fullPath; + else if (attribs[i].Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("MediaType") )) + attribs[i].Value >>= mediaType; + } + + if (fullPath.getLength() == 0 || mediaType.getLength() == 0 || + mediaType.equalsAsciiL( // opt: exclude common text/xml + RTL_CONSTASCII_STRINGPARAM("text/xml") )) + continue; + + String type, subType; + INetContentTypeParameterList params; + if (! INetContentTypes::parse( mediaType, type, subType, ¶ms )) + continue; + + INetContentTypeParameter const * param = params.find( + ByteString("platform") ); + if (param != 0 && !platform_fits( param->m_sValue )) + continue; + const OUString url( makeURL( packageRootURL, fullPath ) ); + + // check for bundle description: + if (type.EqualsIgnoreCaseAscii("application") && + subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.package-bundle-description")) + { + // check locale: + param = params.find( ByteString("locale") ); + if (param == 0) { + if (descrFile.getLength() == 0) + descrFile = url; + } + else { + // match best locale: + lang::Locale locale( toLocale(param->m_sValue) ); + if (locale.Language == officeLocale.Language) + { + if (descrFileLocale.Country == officeLocale.Country + && locale.Country != officeLocale.Country) + continue; + if (descrFileLocale.Variant == officeLocale.Variant + && locale.Variant != officeLocale.Variant) + continue; + descrFile = url; + descrFileLocale = locale; + } + } + continue; + } + + checkAborted( abortChannel ); + + //We make sure that we only create one XPackage for a particular URL. + //Sometime programmers insert the same URL several times in the manifest + //which may lead to DisposedExceptions. + if (bundle.end() == std::find_if(bundle.begin(), bundle.end(), XPackage_eq(url))) + { + const Reference<deployment::XPackage> xPackage( + bindBundleItem( url, mediaType, false, OUString(), xCmdEnv ) ); + if (xPackage.is()) + bundle.push_back( xPackage ); + } + else + { + fprintf(stderr, "manifest.xml contains a duplicate entry!\n"); + } + } + + if (descrFile.getLength() > 0) + { + ::ucbhelper::Content descrFileContent; + if (create_ucb_content( &descrFileContent, descrFile, + xCmdEnv, false /* no throw */ )) + { + // patch description: + ::rtl::ByteSequence bytes( readFile( descrFileContent ) ); + ::rtl::OUStringBuffer buf; + if ( bytes.getLength() ) + { + buf.append( OUString( reinterpret_cast<sal_Char const *>( + bytes.getConstArray() ), + bytes.getLength(), RTL_TEXTENCODING_UTF8 ) ); + } + else + { + buf.append( Package::getDescription() ); + } + m_oldDescription = buf.makeStringAndClear(); + } + } +} + +//______________________________________________________________________________ +void BackendImpl::PackageImpl::scanLegacyBundle( + t_packagevec & bundle, + OUString const & url, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv, + bool skip_registration ) +{ + ::ucbhelper::Content ucbContent( url, xCmdEnv ); + + // check for platform pathes: + const OUString title( ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>() ); + if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM(".plt") ) && + !platform_fits( title.copy( 0, title.getLength() - 4 ) )) { + return; + } + if (title.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM("skip_registration") )) + skip_registration = true; + + OUString ar [] = { StrTitle::get(), OUSTR("IsFolder") }; + Reference<sdbc::XResultSet> xResultSet( + ucbContent.createCursor( + Sequence<OUString>( ar, ARLEN(ar) ), + ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS ) ); + while (xResultSet->next()) + { + checkAborted( abortChannel ); + + const Reference<sdbc::XRow> xRow( xResultSet, UNO_QUERY_THROW ); + const OUString title_enc( ::rtl::Uri::encode( + xRow->getString( 1 /* Title */ ), + rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + const OUString path( makeURL( url, title_enc ) ); + + OUString mediaType; + const Reference<deployment::XPackage> xPackage( + bindBundleItem( path, OUString() /* detect */, false, OUString(), + xCmdEnv, false /* ignore detection errors */ ) ); + if (xPackage.is()) { + const Reference<deployment::XPackageTypeInfo> xPackageType( + xPackage->getPackageType() ); + OSL_ASSERT( xPackageType.is() ); + if (xPackageType.is()) + mediaType = xPackageType->getMediaType(); + + if (skip_registration && + // xxx todo: additional parsing? + mediaType.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/vnd.sun.star.uno-component") )) + continue; + + bundle.push_back( xPackage ); + } + + if (mediaType.getLength() == 0 || + // script.xlb, dialog.xlb can be met everywhere: + mediaType.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/vnd.sun.star.basic-library") ) || + mediaType.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/vnd.sun.star.dialog-library") )) + { + if (xRow->getBoolean( 2 /* IsFolder */ )) { // recurse into folder: + scanLegacyBundle( + bundle, path, abortChannel, xCmdEnv, skip_registration ); + } + } + } +} + +OUString BackendImpl::PackageImpl::getDisplayName() + throw (deployment::ExtensionRemovedException, RuntimeException) +{ + if (m_bRemoved) + throw deployment::ExtensionRemovedException(); + + OUString sName = getDescriptionInfoset().getLocalizedDisplayName(); + if (sName.getLength() == 0) + return m_displayName; + else + return sName; +} + +::std::vector<Reference<deployment::XPackage> > +BackendImpl::PackageImpl::getPackagesFromDb( + Reference<ucb::XCommandEnvironment> const & xCmdEnv) +{ + ::std::vector<Reference<deployment::XPackage> > retVector; + + typedef ::std::vector< ::std::pair<OUString, OUString> >::const_iterator ITC; + for (ITC i = m_dbData.items.begin(); i != m_dbData.items.end(); i++) + { + Reference<deployment::XPackage> xExtension = + bindBundleItem(i->first, i->second, true, m_identifier, xCmdEnv); + OSL_ASSERT(xExtension.is()); + if (xExtension.is()) + retVector.push_back(xExtension); + } + + return retVector; +} + +} // anon namespace + +//============================================================================== +Reference<deployment::XPackageRegistry> create( + Reference<deployment::XPackageRegistry> const & xRootRegistry, + OUString const & context, OUString const & cachePath, bool readOnly, + Reference<XComponentContext> const & xComponentContext ) +{ + Sequence<Any> args( + cachePath.getLength() == 0 ? 1 : 3 ); + args[ 0 ] <<= context; + if (cachePath.getLength() > 0) { + args[ 1 ] <<= cachePath; + args[ 2 ] <<= readOnly; + } + return new BackendImpl( args, xComponentContext, xRootRegistry ); +} + +} // namespace bundle +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/package/dp_package.hrc b/desktop/source/deployment/registry/package/dp_package.hrc new file mode 100644 index 000000000000..0b258a58cdf3 --- /dev/null +++ b/desktop/source/deployment/registry/package/dp_package.hrc @@ -0,0 +1,35 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_PACKAGE_HRC +#define INCLUDED_DP_PACKAGE_HRC + +#include "deployment.hrc" + +#define RID_STR_PACKAGE_BUNDLE (RID_DEPLOYMENT_BUNDLE_START+10) + +#endif diff --git a/desktop/source/deployment/registry/package/dp_package.src b/desktop/source/deployment/registry/package/dp_package.src new file mode 100644 index 000000000000..056a17cb0618 --- /dev/null +++ b/desktop/source/deployment/registry/package/dp_package.src @@ -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. + * + ************************************************************************/ + +#include "dp_package.hrc" + +String RID_STR_PACKAGE_BUNDLE +{ + Text [ en-US ] = "Extension"; +}; + diff --git a/desktop/source/deployment/registry/package/makefile.mk b/desktop/source/deployment/registry/package/makefile.mk new file mode 100644 index 000000000000..203ce176d289 --- /dev/null +++ b/desktop/source/deployment/registry/package/makefile.mk @@ -0,0 +1,48 @@ +#************************************************************************* +# +# 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 = deployment_registry_package +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE : settings.mk + +SRS1NAME = $(TARGET) +SRC1FILES = \ + dp_package.src + +INCPRE += ..$/..$/inc + +SLOFILES = \ + $(SLO)$/dp_package.obj \ + $(SLO)$/dp_extbackenddb.obj + +.INCLUDE : ..$/..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/registry/script/dp_lib_container.cxx b/desktop/source/deployment/registry/script/dp_lib_container.cxx new file mode 100644 index 000000000000..4dc71b7fd9e3 --- /dev/null +++ b/desktop/source/deployment/registry/script/dp_lib_container.cxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_script.hrc" +#include "dp_resource.h" +#include "dp_xml.h" +#include "dp_lib_container.h" +#include "ucbhelper/content.hxx" + + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; + +namespace dp_registry { +namespace backend { +namespace script { + +namespace { +struct StrCannotDetermineLibName : public StaticResourceString< + StrCannotDetermineLibName, RID_STR_CANNOT_DETERMINE_LIBNAME> {}; +} + +//______________________________________________________________________________ +OUString LibraryContainer::get_libname( + OUString const & url, + Reference<XCommandEnvironment> const & xCmdEnv, + Reference<XComponentContext> const & xContext ) +{ + ::xmlscript::LibDescriptor import; + ::ucbhelper::Content ucb_content( url, xCmdEnv ); + xml_parse( ::xmlscript::importLibrary( import ), ucb_content, xContext ); + + if (import.aName.getLength() == 0) { + throw Exception( StrCannotDetermineLibName::get(), + Reference<XInterface>() ); + } + return import.aName; +} + +} +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/script/dp_lib_container.h b/desktop/source/deployment/registry/script/dp_lib_container.h new file mode 100644 index 000000000000..b0f29c1e80f3 --- /dev/null +++ b/desktop/source/deployment/registry/script/dp_lib_container.h @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_LIB_CONTAINER_H +#define INCLUDED_DP_LIB_CONTAINER_H + +#include "rtl/ustring.hxx" +#include "xmlscript/xmllib_imexp.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" + + +namespace css = ::com::sun::star; + +namespace dp_registry { +namespace backend { +namespace script { + +//============================================================================== +class LibraryContainer +{ +public: + static ::rtl::OUString get_libname( + ::rtl::OUString const & url, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + css::uno::Reference<css::uno::XComponentContext> const & xContext ); +}; + +} +} +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/script/dp_script.cxx b/desktop/source/deployment/registry/script/dp_script.cxx new file mode 100644 index 000000000000..45fb378f1c5d --- /dev/null +++ b/desktop/source/deployment/registry/script/dp_script.cxx @@ -0,0 +1,501 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_script.hrc" +#include "dp_lib_container.h" +#include "dp_backend.h" +#include "dp_ucb.h" +#include "rtl/uri.hxx" +#include "ucbhelper/content.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "cppuhelper/implbase1.hxx" +#include "comphelper/servicedecl.hxx" +#include "svl/inettype.hxx" +#include "com/sun/star/util/XUpdatable.hpp" +#include "com/sun/star/script/XLibraryContainer3.hpp" +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> +#include <com/sun/star/util/XMacroExpander.hpp> +#include <com/sun/star/uri/XUriReferenceFactory.hpp> +#include <memory> +#include "dp_scriptbackenddb.hxx" + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; +namespace css = ::com::sun::star; + +namespace dp_registry { +namespace backend { +namespace script { +namespace { + +typedef ::cppu::ImplInheritanceHelper1< + ::dp_registry::backend::PackageRegistryBackend, util::XUpdatable > t_helper; + +//============================================================================== +class BackendImpl : public t_helper +{ + class PackageImpl : public ::dp_registry::backend::Package + { + BackendImpl * getMyBackend() const; + + const OUString m_scriptURL; + const OUString m_dialogURL; + OUString m_dialogName; + + // Package + virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + + public: + PackageImpl( + ::rtl::Reference<BackendImpl> const & myBackend, + OUString const & url, + Reference<XCommandEnvironment> const &xCmdEnv, + OUString const & scriptURL, OUString const & dialogURL, + bool bRemoved, OUString const & identifier); + }; + friend class PackageImpl; + + // PackageRegistryBackend + virtual Reference<deployment::XPackage> bindPackage_( + OUString const & url, OUString const & mediaType, + sal_Bool bRemoved, OUString const & identifier, + Reference<XCommandEnvironment> const & xCmdEnv ); + + void addDataToDb(OUString const & url); + void deleteDataFromDb(OUString const & url); + bool isRegisteredInDb(OUString const & url); + + + +// Reference< ucb::XSimpleFileAccess > getFileAccess( void ); +// Reference< ucb::XSimpleFileAccess > m_xSFA; + + const Reference<deployment::XPackageTypeInfo> m_xBasicLibTypeInfo; + const Reference<deployment::XPackageTypeInfo> m_xDialogLibTypeInfo; + Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos; + std::auto_ptr<ScriptBackendDb> m_backendDb; +public: + BackendImpl( Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ); + + // XUpdatable + virtual void SAL_CALL update() throw (RuntimeException); + + // XPackageRegistry + virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() throw (RuntimeException); +}; + +//______________________________________________________________________________ +BackendImpl::PackageImpl::PackageImpl( + ::rtl::Reference<BackendImpl> const & myBackend, + OUString const & url, + Reference<XCommandEnvironment> const &xCmdEnv, + OUString const & scriptURL, OUString const & dialogURL, bool bRemoved, + OUString const & identifier) + : Package( myBackend.get(), url, + OUString(), OUString(), // will be late-initialized + scriptURL.getLength() > 0 ? myBackend->m_xBasicLibTypeInfo + : myBackend->m_xDialogLibTypeInfo, bRemoved, identifier), + m_scriptURL( scriptURL ), + m_dialogURL( dialogURL ) +{ + // name, displayName: + if (dialogURL.getLength() > 0) { + m_dialogName = LibraryContainer::get_libname( + dialogURL, xCmdEnv, myBackend->getComponentContext() ); + } + if (scriptURL.getLength() > 0) { + m_name = LibraryContainer::get_libname( + scriptURL, xCmdEnv, myBackend->getComponentContext() ); + } + else + m_name = m_dialogName; + m_displayName = m_name; +} + +//______________________________________________________________________________ +BackendImpl::BackendImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ) + : t_helper( args, xComponentContext ), + m_xBasicLibTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.basic-library"), + OUString() /* no file filter */, + getResourceString(RID_STR_BASIC_LIB), + RID_IMG_SCRIPTLIB, RID_IMG_SCRIPTLIB_HC ) ), + m_xDialogLibTypeInfo( new Package::TypeInfo( + OUSTR("application/" + "vnd.sun.star.dialog-library"), + OUString() /* no file filter */, + getResourceString(RID_STR_DIALOG_LIB), + RID_IMG_DIALOGLIB, RID_IMG_DIALOGLIB_HC ) ), + m_typeInfos( 2 ) +{ + m_typeInfos[ 0 ] = m_xBasicLibTypeInfo; + m_typeInfos[ 1 ] = m_xDialogLibTypeInfo; + + OSL_ASSERT( ! transientMode() ); + + if (!transientMode()) + { + OUString dbFile = makeURL(getCachePath(), OUSTR("backenddb.xml")); + m_backendDb.reset( + new ScriptBackendDb(getComponentContext(), dbFile)); + } + +} +void BackendImpl::addDataToDb(OUString const & url) +{ + if (m_backendDb.get()) + m_backendDb->addEntry(url); +} + +bool BackendImpl::isRegisteredInDb(OUString const & url) +{ + bool registered = false; + if (m_backendDb.get()) + registered = m_backendDb->getEntry(url); + return registered; +} + +void BackendImpl::deleteDataFromDb(OUString const & url) +{ + if (m_backendDb.get()) + m_backendDb->removeEntry(url); +} + +// XUpdatable +//______________________________________________________________________________ +void BackendImpl::update() throw (RuntimeException) +{ + // Nothing to do here after fixing i70283!? +} + +// XPackageRegistry +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackageTypeInfo> > +BackendImpl::getSupportedPackageTypes() throw (RuntimeException) +{ + return m_typeInfos; +} + +// PackageRegistryBackend +//______________________________________________________________________________ +Reference<deployment::XPackage> BackendImpl::bindPackage_( + OUString const & url, OUString const & mediaType_, + sal_Bool bRemoved, OUString const & identifier, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + OUString mediaType( mediaType_ ); + if (mediaType.getLength() == 0) + { + // detect media-type: + ::ucbhelper::Content ucbContent; + if (create_ucb_content( &ucbContent, url, xCmdEnv ) && + ucbContent.isFolder()) + { + // probe for script.xlb: + if (create_ucb_content( + 0, makeURL( url, OUSTR("script.xlb") ), + xCmdEnv, false /* no throw */ )) + mediaType = OUSTR("application/vnd.sun.star.basic-library"); + // probe for dialog.xlb: + else if (create_ucb_content( + 0, makeURL( url, OUSTR("dialog.xlb") ), + xCmdEnv, false /* no throw */ )) + mediaType = OUSTR("application/vnd.sun.star.dialog-library"); + } + if (mediaType.getLength() == 0) + throw lang::IllegalArgumentException( + StrCannotDetectMediaType::get() + url, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); + } + + String type, subType; + INetContentTypeParameterList params; + if (INetContentTypes::parse( mediaType, type, subType, ¶ms )) + { + if (type.EqualsIgnoreCaseAscii("application")) + { + OUString dialogURL( makeURL( url, OUSTR("dialog.xlb") ) ); + if (! create_ucb_content( + 0, dialogURL, xCmdEnv, false /* no throw */ )) { + dialogURL = OUString(); + } + + if (subType.EqualsIgnoreCaseAscii("vnd.sun.star.basic-library")) + { + OUString scriptURL( makeURL( url, OUSTR("script.xlb"))); + if (! create_ucb_content( + 0, scriptURL, xCmdEnv, false /* no throw */ )) { + scriptURL = OUString(); + } + + return new PackageImpl( + this, url, xCmdEnv, scriptURL, + dialogURL, bRemoved, identifier); + } + else if (subType.EqualsIgnoreCaseAscii( + "vnd.sun.star.dialog-library")) { + return new PackageImpl( + this, url, xCmdEnv, + OUString() /* no script lib */, + dialogURL, + bRemoved, identifier); + } + } + } + throw lang::IllegalArgumentException( + StrUnsupportedMediaType::get() + mediaType, + static_cast<OWeakObject *>(this), + static_cast<sal_Int16>(-1) ); +} + +//############################################################################## + +// Package +BackendImpl * BackendImpl::PackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); + if (NULL == pBackend) + { + //May throw a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<PackageImpl *>(this))); + } + return pBackend; +} +//______________________________________________________________________________ +beans::Optional< beans::Ambiguous<sal_Bool> > +BackendImpl::PackageImpl::isRegistered_( + ::osl::ResettableMutexGuard &, + ::rtl::Reference<AbortChannel> const &, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + (void)xCmdEnv; + + BackendImpl * that = getMyBackend(); + Reference< deployment::XPackage > xThisPackage( this ); + + bool registered = that->isRegisteredInDb(getURL()); + return beans::Optional< beans::Ambiguous<sal_Bool> >( + true /* IsPresent */, + beans::Ambiguous<sal_Bool>( registered, false /* IsAmbiguous */ ) ); +} + +//______________________________________________________________________________ +void BackendImpl::PackageImpl::processPackage_( + ::osl::ResettableMutexGuard &, + bool doRegisterPackage, + bool startup, + ::rtl::Reference<AbortChannel> const &, + Reference<XCommandEnvironment> const & xCmdEnv ) +{ + (void)xCmdEnv; + + BackendImpl * that = getMyBackend(); + + Reference< deployment::XPackage > xThisPackage( this ); + Reference<XComponentContext> const & xComponentContext = that->getComponentContext(); + + bool bScript = (m_scriptURL.getLength() > 0); + Reference<css::script::XLibraryContainer3> xScriptLibs; + + bool bDialog = (m_dialogURL.getLength() > 0); + Reference<css::script::XLibraryContainer3> xDialogLibs; + + bool bRunning = office_is_running(); + if( bRunning ) + { + if( bScript ) + { + xScriptLibs.set( + xComponentContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.script.ApplicationScriptLibraryContainer"), + xComponentContext ), UNO_QUERY_THROW ); + } + + if( bDialog ) + { + xDialogLibs.set( + xComponentContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.script.ApplicationDialogLibraryContainer"), + xComponentContext ), UNO_QUERY_THROW ); + } + } + bool bRegistered = getMyBackend()->isRegisteredInDb(getURL()); + if( !doRegisterPackage ) + { + //We cannot just call removeLibrary(name) because this could remove a + //script which was added by an extension in a different repository. For + //example, extension foo is contained in the bundled repository and then + //the user adds it it to the user repository. The extension manager will + //then register the new script and revoke the script from the bundled + //extension. removeLibrary(name) would now remove the script from the + //user repository. That is, the script of the newly added user extension does + //not work anymore. Therefore we must check if the currently active + //script comes in fact from the currently processed extension. + + if (bRegistered) + { + //we also prevent and live deployment at startup + if (!isRemoved() && !startup) + { + if (bScript && xScriptLibs.is() && xScriptLibs->hasByName(m_name)) + { + const OUString sScriptUrl = xScriptLibs->getOriginalLibraryLinkURL(m_name); + if (sScriptUrl.equals(m_scriptURL)) + xScriptLibs->removeLibrary(m_name); + } + + if (bDialog && xDialogLibs.is() && xDialogLibs->hasByName(m_dialogName)) + { + const OUString sDialogUrl = xDialogLibs->getOriginalLibraryLinkURL(m_dialogName); + if (sDialogUrl.equals(m_dialogURL)) + xDialogLibs->removeLibrary(m_dialogName); + } + } + getMyBackend()->deleteDataFromDb(getURL()); + return; + } + } + if (bRegistered) + return; // Already registered + + // Update LibraryContainer + bool bScriptSuccess = false; + const bool bReadOnly = false; + + bool bDialogSuccess = false; + if (!startup) + { + //If there is a bundled extension, and the user installes the same extension + //then the script from the bundled extension must be removed. If this does not work + //then live deployment does not work for scripts. + if (bScript && xScriptLibs.is()) + { + bool bCanAdd = true; + if (xScriptLibs->hasByName(m_name)) + { + const OUString sOriginalUrl = xScriptLibs->getOriginalLibraryLinkURL(m_name); + //We assume here that library names in extensions are unique, which may not be the case + //ToDo: If the script exist in another extension, then both extensions must have the + //same id + if (sOriginalUrl.match(OUSTR("vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE")) + || sOriginalUrl.match(OUSTR("vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE")) + || sOriginalUrl.match(OUSTR("vnd.sun.star.expand:$BUNDLED_EXTENSIONS"))) + { + xScriptLibs->removeLibrary(m_name); + bCanAdd = true; + } + else + { + bCanAdd = false; + } + } + + if (bCanAdd) + { + xScriptLibs->createLibraryLink( m_name, m_scriptURL, bReadOnly ); + bScriptSuccess = xScriptLibs->hasByName( m_name ); + } + } + + + if (bDialog && xDialogLibs.is()) + { + bool bCanAdd = true; + if (xDialogLibs->hasByName(m_dialogName)) + { + const OUString sOriginalUrl = xDialogLibs->getOriginalLibraryLinkURL(m_dialogName); + //We assume here that library names in extensions are unique, which may not be the case + //ToDo: If the script exist in another extension, then both extensions must have the + //same id + if (sOriginalUrl.match(OUSTR("vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE")) + || sOriginalUrl.match(OUSTR("vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE")) + || sOriginalUrl.match(OUSTR("vnd.sun.star.expand:$BUNDLED_EXTENSIONS"))) + { + xDialogLibs->removeLibrary(m_dialogName); + bCanAdd = true; + } + else + { + bCanAdd = false; + } + } + + if (bCanAdd) + { + xDialogLibs->createLibraryLink( m_dialogName, m_dialogURL, bReadOnly ); + bDialogSuccess = xDialogLibs->hasByName(m_dialogName); + } + } + } + bool bSuccess = bScript || bDialog; // Something must have happened + if( bRunning && !startup) + if( (bScript && !bScriptSuccess) || (bDialog && !bDialogSuccess) ) + bSuccess = false; + + if (bSuccess) + getMyBackend()->addDataToDb(getURL()); +} + +} // anon namespace + +namespace sdecl = comphelper::service_decl; +sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI; +extern sdecl::ServiceDecl const serviceDecl( + serviceBI, + "com.sun.star.comp.deployment.script.PackageRegistryBackend", + BACKEND_SERVICE_NAME ); + +} // namespace script +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/script/dp_script.hrc b/desktop/source/deployment/registry/script/dp_script.hrc new file mode 100644 index 000000000000..f5b52f1b1f31 --- /dev/null +++ b/desktop/source/deployment/registry/script/dp_script.hrc @@ -0,0 +1,39 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_SCRIPT_HRC +#define INCLUDED_DP_SCRIPT_HRC + +#include "deployment.hrc" + +#define RID_STR_BASIC_LIB (RID_DEPLOYMENT_SCRIPT_START+10) +#define RID_STR_DIALOG_LIB (RID_DEPLOYMENT_SCRIPT_START+11) + +#define RID_STR_LIBNAME_ALREADY_EXISTS (RID_DEPLOYMENT_SCRIPT_START+15) +#define RID_STR_CANNOT_DETERMINE_LIBNAME (RID_DEPLOYMENT_SCRIPT_START+16) + +#endif diff --git a/desktop/source/deployment/registry/script/dp_script.src b/desktop/source/deployment/registry/script/dp_script.src new file mode 100644 index 000000000000..21e0cfdcc9f8 --- /dev/null +++ b/desktop/source/deployment/registry/script/dp_script.src @@ -0,0 +1,49 @@ +/************************************************************************* + * + * 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 "dp_script.hrc" + +String RID_STR_BASIC_LIB +{ + Text [ en-US ] = "%PRODUCTNAME Basic Library"; +}; + +String RID_STR_DIALOG_LIB +{ + Text [ en-US ] = "Dialog Library"; +}; + +String RID_STR_CANNOT_DETERMINE_LIBNAME +{ + Text [ en-US ] = "The library name could not be determined."; +}; + +String RID_STR_LIBNAME_ALREADY_EXISTS +{ + Text [ en-US ] = "This library name already exists. Please choose a different name."; +}; + diff --git a/desktop/source/deployment/registry/script/dp_scriptbackenddb.cxx b/desktop/source/deployment/registry/script/dp_scriptbackenddb.cxx new file mode 100644 index 000000000000..436ea3ce5f29 --- /dev/null +++ b/desktop/source/deployment/registry/script/dp_scriptbackenddb.cxx @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "rtl/string.h" +#include "cppuhelper/exc_hlp.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/dom/XDocument.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "dp_misc.h" +#include "dp_scriptbackenddb.hxx" + + +namespace css = ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +#define EXTENSION_REG_NS "http://openoffice.org/extensionmanager/script-registry/2010" +#define NS_PREFIX "script" +#define ROOT_ELEMENT_NAME "script-backend-db" +#define KEY_ELEMENT_NAME "script" + +namespace dp_registry { +namespace backend { +namespace script { + +ScriptBackendDb::ScriptBackendDb( + Reference<XComponentContext> const & xContext, + ::rtl::OUString const & url):RegisteredDb(xContext, url) +{ + +} + +OUString ScriptBackendDb::getDbNSName() +{ + return OUSTR(EXTENSION_REG_NS); +} + +OUString ScriptBackendDb::getNSPrefix() +{ + return OUSTR(NS_PREFIX); +} + +OUString ScriptBackendDb::getRootElementName() +{ + return OUSTR(ROOT_ELEMENT_NAME); +} + +OUString ScriptBackendDb::getKeyElementName() +{ + return OUSTR(KEY_ELEMENT_NAME); +} + + + +} // namespace executable +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/script/dp_scriptbackenddb.hxx b/desktop/source/deployment/registry/script/dp_scriptbackenddb.hxx new file mode 100644 index 000000000000..63015ab1e46c --- /dev/null +++ b/desktop/source/deployment/registry/script/dp_scriptbackenddb.hxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_SCRIPTBACKENDDB_HXX +#define INCLUDED_DP_SCRIPTBACKENDDB_HXX + +#include "rtl/ustring.hxx" +#include "dp_backenddb.hxx" +#include "boost/optional.hpp" +namespace css = ::com::sun::star; + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } +}}} + +namespace dp_registry { +namespace backend { +namespace script { + +/* The XML file stores the extensions which are currently registered. + They will be removed when they are revoked. + */ +class ScriptBackendDb: public dp_registry::backend::RegisteredDb +{ +protected: + virtual ::rtl::OUString getDbNSName(); + + virtual ::rtl::OUString getNSPrefix(); + + virtual ::rtl::OUString getRootElementName(); + + virtual ::rtl::OUString getKeyElementName(); + + +public: + + ScriptBackendDb( css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); +}; + + + +} +} +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/script/makefile.mk b/desktop/source/deployment/registry/script/makefile.mk new file mode 100644 index 000000000000..708def358021 --- /dev/null +++ b/desktop/source/deployment/registry/script/makefile.mk @@ -0,0 +1,49 @@ +#************************************************************************* +# +# 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 = deployment_registry_script +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE : settings.mk + +SRS1NAME = $(TARGET) +SRC1FILES = \ + dp_script.src + +INCPRE += ..$/..$/inc + +SLOFILES = \ + $(SLO)$/dp_script.obj \ + $(SLO)$/dp_lib_container.obj \ + $(SLO)$/dp_scriptbackenddb.obj + +.INCLUDE : ..$/..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/registry/sfwk/dp_parceldesc.cxx b/desktop/source/deployment/registry/sfwk/dp_parceldesc.cxx new file mode 100644 index 000000000000..9d66e80f7114 --- /dev/null +++ b/desktop/source/deployment/registry/sfwk/dp_parceldesc.cxx @@ -0,0 +1,132 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_misc.h" +#include "dp_parceldesc.hxx" + + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +using ::rtl::OUString; + +namespace css = ::com::sun::star; +namespace dp_registry +{ +namespace backend +{ +namespace sfwk +{ + + +// XDocumentHandler +void SAL_CALL +ParcelDescDocHandler::startDocument() +throw ( xml::sax::SAXException, RuntimeException ) +{ + m_bIsParsed = false; +} + +void SAL_CALL +ParcelDescDocHandler::endDocument() +throw ( xml::sax::SAXException, RuntimeException ) +{ + m_bIsParsed = true; +} + +void SAL_CALL +ParcelDescDocHandler::characters( const OUString & ) + throw ( xml::sax::SAXException, RuntimeException ) +{ +} + +void SAL_CALL +ParcelDescDocHandler::ignorableWhitespace( const OUString & ) + throw ( xml::sax::SAXException, RuntimeException ) +{ +} + +void SAL_CALL +ParcelDescDocHandler::processingInstruction( + const OUString &, const OUString & ) + throw ( xml::sax::SAXException, RuntimeException ) +{ +} + +void SAL_CALL +ParcelDescDocHandler::setDocumentLocator( + const Reference< xml::sax::XLocator >& ) + throw ( xml::sax::SAXException, RuntimeException ) +{ +} + +void SAL_CALL +ParcelDescDocHandler::startElement( const OUString& aName, + const Reference< xml::sax::XAttributeList > & xAttribs ) + throw ( xml::sax::SAXException, + RuntimeException ) +{ + + dp_misc::TRACE(OUSTR("ParcelDescDocHandler::startElement() for ") + + aName + OUSTR("\n")); + if ( !skipIndex ) + { + if ( aName.equals( OUString::createFromAscii( "parcel" ) ) ) + { + m_sLang = xAttribs->getValueByName( OUString::createFromAscii( "language" ) ); + } + ++skipIndex; + } + else + { + dp_misc::TRACE(OUSTR("ParcelDescDocHandler::startElement() skipping for ") + + aName + OUSTR("\n")); + } + +} + +void SAL_CALL ParcelDescDocHandler::endElement( const OUString & aName ) + throw ( xml::sax::SAXException, RuntimeException ) +{ + if ( skipIndex ) + { + --skipIndex; + dp_misc::TRACE(OUSTR("ParcelDescDocHandler::endElement() skipping for ") + + aName + OUSTR("\n")); + } +} + + +} +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/sfwk/dp_parceldesc.hxx b/desktop/source/deployment/registry/sfwk/dp_parceldesc.hxx new file mode 100644 index 000000000000..6d2dc52006e3 --- /dev/null +++ b/desktop/source/deployment/registry/sfwk/dp_parceldesc.hxx @@ -0,0 +1,92 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 <cppuhelper/implbase1.hxx> + +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <com/sun/star/xml/sax/SAXException.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> + +#include <com/sun/star/lang/NoSupportException.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +namespace css = ::com::sun::star; +namespace dp_registry +{ +namespace backend +{ +namespace sfwk +{ + +typedef ::cppu::WeakImplHelper1< css::xml::sax::XDocumentHandler > t_DocHandlerImpl; + +class ParcelDescDocHandler : public t_DocHandlerImpl +{ +private: + bool m_bIsParsed; + ::rtl::OUString m_sLang; + sal_Int32 skipIndex; +public: + ParcelDescDocHandler():m_bIsParsed( false ), skipIndex( 0 ){} + ::rtl::OUString getParcelLanguage() { return m_sLang; } + bool isParsed() { return m_bIsParsed; } + // XDocumentHandler + virtual void SAL_CALL startDocument() + throw ( css::xml::sax::SAXException, css::uno::RuntimeException ); + + virtual void SAL_CALL endDocument() + throw ( css::xml::sax::SAXException, css::uno::RuntimeException ); + + virtual void SAL_CALL startElement( const ::rtl::OUString& aName, + const css::uno::Reference< css::xml::sax::XAttributeList > & xAttribs ) + throw ( css::xml::sax::SAXException, + css::uno::RuntimeException ); + + virtual void SAL_CALL endElement( const ::rtl::OUString & aName ) + throw ( css::xml::sax::SAXException, css::uno::RuntimeException ); + + virtual void SAL_CALL characters( const ::rtl::OUString & aChars ) + throw ( css::xml::sax::SAXException, css::uno::RuntimeException ); + + virtual void SAL_CALL ignorableWhitespace( const ::rtl::OUString & aWhitespaces ) + throw ( css::xml::sax::SAXException, css::uno::RuntimeException ); + + virtual void SAL_CALL processingInstruction( + const ::rtl::OUString & aTarget, const ::rtl::OUString & aData ) + throw ( css::xml::sax::SAXException, css::uno::RuntimeException ); + + virtual void SAL_CALL setDocumentLocator( + const css::uno::Reference< css::xml::sax::XLocator >& xLocator ) + throw ( css::xml::sax::SAXException, css::uno::RuntimeException ); +}; +} +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/sfwk/dp_sfwk.cxx b/desktop/source/deployment/registry/sfwk/dp_sfwk.cxx new file mode 100644 index 000000000000..0e8dc29d53c4 --- /dev/null +++ b/desktop/source/deployment/registry/sfwk/dp_sfwk.cxx @@ -0,0 +1,410 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_sfwk.hrc" +#include "dp_backend.h" +#include "dp_ucb.h" +#include "dp_parceldesc.hxx" +#include "rtl/uri.hxx" +#include "ucbhelper/content.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "comphelper/servicedecl.hxx" +#include "svl/inettype.hxx" +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/script/provider/XScriptProviderFactory.hpp> +#include <memory> + + +using namespace ::dp_misc; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::script; + +using ::rtl::OUString; +namespace css = ::com::sun::star; + +namespace dp_registry +{ +namespace backend +{ +namespace sfwk +{ + +//============================================================================== +class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend +{ + class PackageImpl : public ::dp_registry::backend::Package + { + BackendImpl * getMyBackend() const; + + Reference< container::XNameContainer > m_xNameCntrPkgHandler; + OUString m_descr; + + void initPackageHandler(); + + // Package + virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_( + ::osl::ResettableMutexGuard & guard, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + virtual void processPackage_( + ::osl::ResettableMutexGuard & guard, + bool registerPackage, + bool startup, + ::rtl::Reference<AbortChannel> const & abortChannel, + Reference<XCommandEnvironment> const & xCmdEnv ); + + public: + PackageImpl( + ::rtl::Reference<BackendImpl> const & myBackend, + OUString const & url, OUString const & libType, bool bRemoved, + OUString const & identifier); + // XPackage + virtual OUString SAL_CALL getDescription() throw (RuntimeException); + }; + friend class PackageImpl; + + // PackageRegistryBackend + virtual Reference<deployment::XPackage> bindPackage_( + OUString const & url, OUString const & mediaType, + sal_Bool bRemoved, OUString const & identifier, + Reference<XCommandEnvironment> const & xCmdEnv ); + + const Reference<deployment::XPackageTypeInfo> m_xTypeInfo; + +public: + BackendImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ); + + // XPackageRegistry + virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes() throw (RuntimeException); +}; + +BackendImpl * BackendImpl::PackageImpl::getMyBackend() const +{ + BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); + if (NULL == pBackend) + { + //May throw a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<PackageImpl *>(this))); + } + return pBackend; +} +//______________________________________________________________________________ +OUString BackendImpl::PackageImpl::getDescription() throw (RuntimeException) +{ + if (m_descr.getLength() == 0) + return Package::getDescription(); + else + return m_descr; +} + +//______________________________________________________________________________ +BackendImpl::PackageImpl::PackageImpl( + ::rtl::Reference<BackendImpl> const & myBackend, + OUString const & url, OUString const & libType, bool bRemoved, + OUString const & identifier) + : Package( myBackend.get(), url, OUString(), OUString(), + myBackend->m_xTypeInfo, bRemoved, identifier), + m_descr(libType) +{ + initPackageHandler(); + + sal_Int32 segmEnd = url.getLength(); + if (url.getLength() > 0 && url[ url.getLength() - 1 ] == '/') + --segmEnd; + sal_Int32 segmStart = (url.lastIndexOf( '/', segmEnd ) + 1); + if (segmStart < 0) + segmStart = 0; + // name and display name default the same: + m_displayName = ::rtl::Uri::decode( + url.copy( segmStart, segmEnd - segmStart ), + rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); + m_name = m_displayName; + + dp_misc::TRACE(OUSTR("PakageImpl displayName is ") + m_displayName); +} + +//______________________________________________________________________________ +BackendImpl::BackendImpl( + Sequence<Any> const & args, + Reference<XComponentContext> const & xComponentContext ) + : PackageRegistryBackend( args, xComponentContext ), + m_xTypeInfo( new Package::TypeInfo( + OUSTR("application/vnd.sun.star.framework-script"), + OUString() /* no file filter */, + OUSTR("Scripting Framework Script Library"), + RID_IMG_SCRIPTLIB, RID_IMG_SCRIPTLIB_HC ) ) +{ + if (! transientMode()) + { +/* + if (office_is_running()) + { + Reference<XComponentContext> xContext( getComponentContext() ); + m_xScriptLibs.set( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star." + "script.ApplicationScriptLibraryContainer"), + xContext ), UNO_QUERY_THROW ); + m_xDialogLibs.set( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star." + "script.ApplicationDialogLibraryContainer"), + xContext ), UNO_QUERY_THROW ); + } + else + { + OUString basic_path( + m_eContext == CONTEXT_USER + ? OUSTR("vnd.sun.star.expand:${$BRAND_BASE_DIR/program/" + SAL_CONFIGFILE("bootstrap") + ":UserInstallation}/user/basic") + : OUSTR("vnd.sun.star.expand:${$BRAND_BASE_DIR/program/" + SAL_CONFIGFILE("bootstrap") + ":BaseInstallation}/share/basic") ); + m_basic_script_libs.reset( + new LibraryContainer( + makeURL( basic_path, OUSTR("script.xlc") ), + getMutex(), + getComponentContext() ) ); + m_dialog_libs.reset( + new LibraryContainer( + makeURL( basic_path, OUSTR("dialog.xlc") ), + getMutex(), + getComponentContext() ) ); + } +*/ + } +} + +// XPackageRegistry +//______________________________________________________________________________ +Sequence< Reference<deployment::XPackageTypeInfo> > +BackendImpl::getSupportedPackageTypes() throw (RuntimeException) +{ + return Sequence< Reference<deployment::XPackageTypeInfo> >(&m_xTypeInfo, 1); +} + +// PackageRegistryBackend +//______________________________________________________________________________ +Reference<deployment::XPackage> BackendImpl::bindPackage_( + OUString const & url, OUString const & mediaType_, sal_Bool bRemoved, + OUString const & identifier, Reference<XCommandEnvironment> const & xCmdEnv ) +{ + OUString mediaType( mediaType_ ); + if (mediaType.getLength() == 0) + { + // detect media-type: + ::ucbhelper::Content ucbContent; + if (create_ucb_content( &ucbContent, url, xCmdEnv ) && + ucbContent.isFolder()) + { + // probe for parcel-descriptor.xml: + if (create_ucb_content( + 0, makeURL( url, OUSTR("parcel-descriptor.xml") ), + xCmdEnv, false /* no throw */ )) + { + mediaType = OUSTR("application/vnd.sun.star.framework-script"); + } + } + if (mediaType.getLength() == 0) + throw lang::IllegalArgumentException( + StrCannotDetectMediaType::get() + url, + static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); + } + + String type, subType; + INetContentTypeParameterList params; + if (INetContentTypes::parse( mediaType, type, subType, ¶ms )) + { + if (type.EqualsIgnoreCaseAscii("application")) + { + if (subType.EqualsIgnoreCaseAscii("vnd.sun.star.framework-script")) + { + OUString lang = OUString::createFromAscii("Script"); + OUString sParcelDescURL = makeURL( + url, OUSTR("parcel-descriptor.xml") ); + + ::ucbhelper::Content ucb_content; + + if (create_ucb_content( &ucb_content, sParcelDescURL, + xCmdEnv, false /* no throw */ )) + { + ParcelDescDocHandler* pHandler = + new ParcelDescDocHandler(); + Reference< xml::sax::XDocumentHandler > + xDocHandler = pHandler; + + Reference<XComponentContext> + xContext( getComponentContext() ); + + Reference< xml::sax::XParser > xParser( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.xml.sax.Parser"), xContext ), + UNO_QUERY_THROW ); + + xParser->setDocumentHandler( xDocHandler ); + xml::sax::InputSource source; + source.aInputStream = ucb_content.openStream(); + source.sSystemId = ucb_content.getURL(); + xParser->parseStream( source ); + + if ( pHandler->isParsed() ) + { + lang = pHandler->getParcelLanguage(); + } + } + + OUString sfwkLibType = getResourceString( RID_STR_SFWK_LIB ); + // replace %MACRONAME placeholder with language name + OUString MACRONAME( OUSTR("%MACROLANG" ) ); + sal_Int32 startOfReplace = sfwkLibType.indexOf( MACRONAME ); + sal_Int32 charsToReplace = MACRONAME.getLength(); + sfwkLibType = sfwkLibType.replaceAt( startOfReplace, charsToReplace, lang ); + dp_misc::TRACE("******************************\n"); + dp_misc::TRACE(OUSTR(" BackEnd detected lang = ") + lang + OUSTR("\n")); + dp_misc::TRACE(OUSTR(" for url ") + sParcelDescURL + OUSTR("\n") ); + dp_misc::TRACE("******************************\n"); + return new PackageImpl( this, url, sfwkLibType, bRemoved, identifier); + } + } + } + throw lang::IllegalArgumentException( + StrUnsupportedMediaType::get() + mediaType, + static_cast<OWeakObject *>(this), + static_cast<sal_Int16>(-1) ); +} + +//############################################################################## + +void BackendImpl::PackageImpl:: initPackageHandler() +{ + if (m_xNameCntrPkgHandler.is()) + return; + + BackendImpl * that = getMyBackend(); + Any aContext; + + if ( that->m_eContext == CONTEXT_USER ) + { + aContext <<= OUSTR("user"); + } + else if ( that->m_eContext == CONTEXT_SHARED ) + { + aContext <<= OUSTR("share"); + } + else if ( that->m_eContext == CONTEXT_BUNDLED ) + { + aContext <<= OUSTR("bundled"); + } + else + { + OSL_ASSERT( 0 ); + // NOT supported at the momemtn // TODO + } + + Reference< provider::XScriptProviderFactory > xFac( + that->getComponentContext()->getValueByName( + OUSTR( "/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory") ), UNO_QUERY ); + + if ( xFac.is() ) + { + Reference< container::XNameContainer > xName( xFac->createScriptProvider( aContext ), UNO_QUERY ); + if ( xName.is() ) + { + m_xNameCntrPkgHandler.set( xName ); + } + } + // TODO what happens if above fails?? +} + +// Package +//______________________________________________________________________________ +beans::Optional< beans::Ambiguous<sal_Bool> > +BackendImpl::PackageImpl::isRegistered_( + ::osl::ResettableMutexGuard &, + ::rtl::Reference<AbortChannel> const &, + Reference<XCommandEnvironment> const & ) +{ + return beans::Optional< beans::Ambiguous<sal_Bool> >( + true /* IsPresent */, + beans::Ambiguous<sal_Bool>( + m_xNameCntrPkgHandler.is() && m_xNameCntrPkgHandler->hasByName( + m_url ), + false /* IsAmbiguous */ ) ); +} + +//______________________________________________________________________________ +void BackendImpl::PackageImpl::processPackage_( + ::osl::ResettableMutexGuard &, + bool doRegisterPackage, + bool /* startup */, + ::rtl::Reference<AbortChannel> const &, + Reference<XCommandEnvironment> const & ) +{ + if ( !m_xNameCntrPkgHandler.is() ) + { + dp_misc::TRACE("no package handler!!!!\n"); + throw RuntimeException( OUSTR("No package Handler " ), + Reference< XInterface >() ); + } + + if (doRegisterPackage) + { + // will throw if it fails + m_xNameCntrPkgHandler->insertByName( m_url, makeAny( Reference< XPackage >(this) ) ); + + } + else // revokePackage() + { + m_xNameCntrPkgHandler->removeByName( m_url ); + } +} + +namespace sdecl = comphelper::service_decl; +sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI; +extern sdecl::ServiceDecl const serviceDecl( + serviceBI, + "com.sun.star.comp.deployment.sfwk.PackageRegistryBackend", + BACKEND_SERVICE_NAME ); + +} // namespace sfwk +} // namespace backend +} // namespace dp_registry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/registry/sfwk/dp_sfwk.hrc b/desktop/source/deployment/registry/sfwk/dp_sfwk.hrc new file mode 100644 index 000000000000..ed164251cc23 --- /dev/null +++ b/desktop/source/deployment/registry/sfwk/dp_sfwk.hrc @@ -0,0 +1,35 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_SFWK_HRC +#define INCLUDED_DP_SFWK_HRC + +#include "deployment.hrc" + +#define RID_STR_SFWK_LIB (RID_DEPLOYMENT_SCRIPT_START+20) + +#endif diff --git a/desktop/source/deployment/registry/sfwk/dp_sfwk.src b/desktop/source/deployment/registry/sfwk/dp_sfwk.src new file mode 100644 index 000000000000..32a507240123 --- /dev/null +++ b/desktop/source/deployment/registry/sfwk/dp_sfwk.src @@ -0,0 +1,35 @@ +/************************************************************************* + * + * 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 "dp_sfwk.hrc" + +String RID_STR_SFWK_LIB +{ + Text [ en-US ] = "%MACROLANG Library"; +}; + + diff --git a/desktop/source/deployment/registry/sfwk/makefile.mk b/desktop/source/deployment/registry/sfwk/makefile.mk new file mode 100644 index 000000000000..a052296d5c21 --- /dev/null +++ b/desktop/source/deployment/registry/sfwk/makefile.mk @@ -0,0 +1,48 @@ +#************************************************************************* +# +# 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 = deployment_registry_sfwk +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE : settings.mk +SRS1NAME = $(TARGET) + +SRC1FILES = \ + dp_sfwk.src + +INCPRE += ..$/..$/inc + +SLOFILES = \ + $(SLO)$/dp_parceldesc.obj \ + $(SLO)$/dp_sfwk.obj + +.INCLUDE : ..$/..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/target.pmk b/desktop/source/deployment/target.pmk new file mode 100644 index 000000000000..82b41766b253 --- /dev/null +++ b/desktop/source/deployment/target.pmk @@ -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. +# +#************************************************************************* + +.IF "$(debug)" != "" + +# MSVC: no inlining +.IF "$(COM)" == "MSC" +CFLAGS += /Ob0 +.ENDIF + +.ENDIF + diff --git a/desktop/source/deployment/unopkg/makefile.mk b/desktop/source/deployment/unopkg/makefile.mk new file mode 100644 index 000000000000..06b39cd2d04e --- /dev/null +++ b/desktop/source/deployment/unopkg/makefile.mk @@ -0,0 +1,48 @@ +#************************************************************************* +# +# 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 = deployment_unopkg +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE : settings.mk + +.IF "$(SYSTEM_DB)" == "YES" +CFLAGS+=-DSYSTEM_DB -I$(DB_INCLUDES) +.ENDIF + +SRS1NAME = $(TARGET) +SRC1FILES = \ + unopkg.src + +SLOFILES = + +.INCLUDE : ..$/target.pmk +.INCLUDE : target.mk + diff --git a/desktop/source/deployment/unopkg/unopkg.src b/desktop/source/deployment/unopkg/unopkg.src new file mode 100644 index 000000000000..b40b505af291 --- /dev/null +++ b/desktop/source/deployment/unopkg/unopkg.src @@ -0,0 +1,84 @@ +/************************************************************************* + * + * 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 "deployment.hrc" + + +String RID_STR_UNOPKG_ACCEPT_LIC_1 +{ + Text [ en-US ] = "Extension Software License Agreement of $NAME:"; +}; + +String RID_STR_UNOPKG_ACCEPT_LIC_2 +{ + Text [ en-US ] = "Read the complete License Agreement displayed above. " + "Accept the License Agreement by typing \"yes\" on the console " + "then press the Return key. Type \"no\" to decline and to abort the " + "extension setup."; +}; + +String RID_STR_UNOPKG_ACCEPT_LIC_3 +{ + Text [ en-US ] = "[Enter \"yes\" or \"no\"]:"; +}; + +String RID_STR_UNOPKG_ACCEPT_LIC_4 +{ + Text [ en-US ] = "Your input was not correct. Please enter \"yes\" or \"no\":"; +}; + +String RID_STR_UNOPKG_ACCEPT_LIC_YES +{ + Text [ en-US ] = "YES"; +}; + +String RID_STR_UNOPKG_ACCEPT_LIC_Y +{ + Text [ en-US ] = "Y"; +}; + +String RID_STR_UNOPKG_ACCEPT_LIC_NO +{ + Text [ en-US ] = "NO"; +}; + +String RID_STR_UNOPKG_ACCEPT_LIC_N +{ + Text [ en-US ] = "N"; +}; + +String RID_STR_CONCURRENTINSTANCE +{ + Text [ en-US ] = "unopkg cannot be started. The lock file indicates it as already running. " + "If this does not apply, delete the lock file at:"; +}; + +String RID_STR_UNOPKG_ERROR +{ + Text [ en-US ] = "ERROR: "; +}; + diff --git a/desktop/source/inc/exithelper.hxx b/desktop/source/inc/exithelper.hxx new file mode 100644 index 000000000000..441cc06a1baa --- /dev/null +++ b/desktop/source/inc/exithelper.hxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_EXITHELPER_HXX_ +#define _DESKTOP_EXITHELPER_HXX_ + +namespace desktop +{ + +//============================================================================= +/** @short provide helper functions to handle a abnormal exit + and contain a list of all "well known" exit codes. + */ +class ExitHelper +{ + //------------------------------------------------------------------------- + // const + public: + + //--------------------------------------------------------------------- + /** @short list of all well known exit codes. + + @descr Its not allowed to use exit codes hard coded + inside office. All places must use these list to + be synchron. + */ + enum EExitCodes + { + /// e.g. used to force showing of the command line help + E_NO_ERROR = 0, + /// pipe was detected - second office must terminate itself + E_SECOND_OFFICE = 1, + /// an uno exception was catched during startup + E_FATAL_ERROR = 333, // Only the low 8 bits are significant 333 % 256 = 77 + /// user force automatic restart after crash + E_CRASH_WITH_RESTART = 79, + /// the office restarts itself + E_NORMAL_RESTART = 81 + }; +}; + +} // namespace desktop + +#endif // #ifndef _DESKTOP_EXITHELPER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/inc/helpid.hrc b/desktop/source/inc/helpid.hrc new file mode 100644 index 000000000000..2435467f7639 --- /dev/null +++ b/desktop/source/inc/helpid.hrc @@ -0,0 +1,78 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#if ! defined INCLUDED_DESKTOP_HELPID_HRC +#define INCLUDED_DESKTOP_HELPID_HRC + +#include "svl/solar.hrc" + +#define HID_GLOBAL_FALLBACK 0xFFFFFFFF + +#define HID_PACKAGE_MANAGER (HID_DESKTOP_START + 0) +#define HID_PACKAGE_MANAGER_TREELISTBOX (HID_DESKTOP_START + 1) +#define HID_PACKAGE_MANAGER_PROGRESS (HID_DESKTOP_START + 2) +#define HID_PACKAGE_MANAGER_PROGRESS_CANCEL (HID_DESKTOP_START + 3) +#define HID_PACKAGE_MANAGER_MENU_ITEM (HID_DESKTOP_START + 4) + +#define HID_FIRSTSTART_DIALOG (HID_DESKTOP_START + 5) +#define HID_FIRSTSTART_WELCOME (HID_DESKTOP_START + 6) +#define HID_FIRSTSTART_LICENSE (HID_DESKTOP_START + 7) +#define HID_FIRSTSTART_MIGRATION (HID_DESKTOP_START + 8) +#define HID_FIRSTSTART_REGISTRATION (HID_DESKTOP_START + 9) +#define HID_FIRSTSTART_USER (HID_DESKTOP_START + 10) +#define HID_FIRSTSTART_PREV (HID_DESKTOP_START + 11) +#define HID_FIRSTSTART_NEXT (HID_DESKTOP_START + 12) +#define HID_FIRSTSTART_CANCEL (HID_DESKTOP_START + 13) +#define HID_FIRSTSTART_FINISH (HID_DESKTOP_START + 14) +#define UID_FIRSTSTART_HELP (HID_DESKTOP_START + 15) +#define UID_BTN_LICENSE_ACCEPT (HID_DESKTOP_START + 16) +#define HID_FIRSTSTART_UPDATE_CHECK (HID_DESKTOP_START + 17) +#define HID_DEPLOYMENT_GUI_UPDATE (HID_DESKTOP_START + 18) +#define HID_DEPLOYMENT_GUI_UPDATEINSTALL (HID_DESKTOP_START + 19) +#define HID_DEPLOYMENT_GUI_UPDATE_PUBLISHER (HID_DESKTOP_START + 20) +#define HID_DEPLOYMENT_GUI_UPDATE_RELEASENOTES (HID_DESKTOP_START + 21) +#define HID_DEPLOYMENT_GUI_UPDATE_AVAILABLE_UPDATES (HID_DESKTOP_START + 22) + +#define HID_EXTENSION_MANAGER_LISTBOX (HID_DESKTOP_START + 23) +#define HID_EXTENSION_MANAGER_LISTBOX_OPTIONS (HID_DESKTOP_START + 24) +#define HID_EXTENSION_MANAGER_LISTBOX_ENABLE (HID_DESKTOP_START + 25) +#define HID_EXTENSION_MANAGER_LISTBOX_DISABLE (HID_DESKTOP_START + 26) +#define HID_EXTENSION_MANAGER_LISTBOX_REMOVE (HID_DESKTOP_START + 27) + +#define HID_EXTENSION_DEPENDENCIES (HID_DESKTOP_START + 28) + +#define HID_PACKAGE_MANAGER_UPD_REQ (HID_DESKTOP_START + 29) + +#define ACT_DESKTOP_HID_END HID_PACKAGE_MANAGER_UPD_REQ + +// check bounds: +#if ACT_DESKTOP_HID_END > HID_DESKTOP_END +#error Resource overflow in #line, #file +#endif + +#endif + diff --git a/desktop/source/migration/cfgfilter.cxx b/desktop/source/migration/cfgfilter.cxx new file mode 100644 index 000000000000..2e5a20e708c6 --- /dev/null +++ b/desktop/source/migration/cfgfilter.cxx @@ -0,0 +1,336 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "cfgfilter.hxx" + +#include <com/sun/star/beans/NamedValue.hpp> +#include <unotools/textsearch.hxx> + +using namespace rtl; +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::configuration::backend; + +namespace desktop { + +CConfigFilter::CConfigFilter(const strings_v* include, const strings_v* exclude) + : m_pvInclude(include) + , m_pvExclude(exclude) +{ +} + +void SAL_CALL CConfigFilter::initialize(const Sequence< Any >& seqArgs) + throw (Exception) +{ + NamedValue nv; + for (sal_Int32 i=0; i < seqArgs.getLength(); i++) + { + if (seqArgs[i] >>= nv) + { + if (nv.Name.equalsAscii("Source")) + nv.Value >>= m_xSourceLayer; + if (nv.Name.equalsAscii("ComponentName")) + nv.Value >>= m_aCurrentComponent; + } + } + if (m_aCurrentComponent.getLength() == 0) + m_aCurrentComponent = OUString::createFromAscii("unknown.component"); + + if (!m_xSourceLayer.is()) { + throw Exception(); + } + +} + + +void CConfigFilter::pushElement(rtl::OUString aName, sal_Bool bUse) +{ + OUString aPath; + if (!m_elementStack.empty()) { + aPath = m_elementStack.top().path; // or use base path + aPath += OUString::createFromAscii("/"); + } + aPath += aName; + + // create element + element elem; + elem.name = aName; + elem.path = aPath; + elem.use = bUse; + m_elementStack.push(elem); +} + +sal_Bool CConfigFilter::checkCurrentElement() +{ + return m_elementStack.top().use; +} + +sal_Bool CConfigFilter::checkElement(rtl::OUString aName) +{ + + sal_Bool bResult = sal_False; + + // get full pathname for element + OUString aFullPath; + if (!m_elementStack.empty()) + aFullPath = m_elementStack.top().path + OUString::createFromAscii("/"); + + aFullPath += aName; + + // check whether any include patterns patch this path + for (strings_v::const_iterator i_in = m_pvInclude->begin(); + i_in != m_pvInclude->end(); i_in++) + { + // pattern is beginning of path + // or path is a begiing for pattern + if (i_in->match(aFullPath.copy(0, i_in->getLength()>aFullPath.getLength() + ? aFullPath.getLength() : i_in->getLength()), 0)) + { + bResult = sal_True; + break; // one match is enough + } + } + // if match is found, check for exclusion + if (bResult) + { + for (strings_v::const_iterator i_ex = m_pvExclude->begin(); + i_ex != m_pvExclude->end(); i_ex++) + { + if (aFullPath.match(*i_ex, 0)) // pattern is beginning of path + { + bResult = sal_False; + break; // one is enough... + } + } + } + return bResult; +} + +void CConfigFilter::popElement() +{ + m_elementStack.pop(); +} + + +void SAL_CALL CConfigFilter::readData( + const Reference< configuration::backend::XLayerHandler >& layerHandler) + throw ( + com::sun::star::lang::NullPointerException, lang::WrappedTargetException, + com::sun::star::configuration::backend::MalformedDataException) +{ + // when readData is called, the submitted handler will be stored + // in m_xLayerHandler. we will then submit ourself as a handler to + // the SourceLayer in m_xSourceLayer. + // when the source calls our handler functions we will use the patterns that + // where given in the ctor to decide whther they should be relaied to the caller + + if (m_xSourceLayer.is() && layerHandler.is()) + { + m_xLayerHandler = layerHandler; + m_xSourceLayer->readData(Reference<XLayerHandler>(static_cast< XLayerHandler* >(this))); + } else + { + throw NullPointerException(); + } +} + +// XLayerHandler +void SAL_CALL CConfigFilter::startLayer() + throw(::com::sun::star::lang::WrappedTargetException) +{ + m_xLayerHandler->startLayer(); +} + +void SAL_CALL CConfigFilter::endLayer() + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ) +{ + m_xLayerHandler->endLayer(); +} + +void SAL_CALL CConfigFilter::overrideNode( + const OUString& aName, + sal_Int16 aAttributes, + sal_Bool bClear) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ) +{ + if (checkElement(aName)) + { + m_xLayerHandler->overrideNode(aName, aAttributes, bClear); + pushElement(aName); + } + else + pushElement(aName, sal_False); +} + +void SAL_CALL CConfigFilter::addOrReplaceNode( + const OUString& aName, + sal_Int16 aAttributes) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ) +{ + if (checkElement(aName)) + { + m_xLayerHandler->addOrReplaceNode(aName, aAttributes); + pushElement(aName); + } + else + pushElement(aName, sal_False); +} + +void SAL_CALL CConfigFilter::addOrReplaceNodeFromTemplate( + const OUString& aName, + const com::sun::star::configuration::backend::TemplateIdentifier& aTemplate, + sal_Int16 aAttributes ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ) +{ + if (checkElement(aName)) + { + m_xLayerHandler->addOrReplaceNodeFromTemplate(aName, aTemplate, aAttributes); + pushElement(aName); + } + else + pushElement(aName, sal_False); +} + +void SAL_CALL CConfigFilter::endNode() + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ) +{ + if (checkCurrentElement()) + { + m_xLayerHandler->endNode(); + } + popElement(); +} + +void SAL_CALL CConfigFilter::dropNode( + const OUString& aName ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ) +{ + // does not get pushed + if (checkElement(aName)) + { + m_xLayerHandler->dropNode(aName); + } +} + +void SAL_CALL CConfigFilter::overrideProperty( + const OUString& aName, + sal_Int16 aAttributes, + const Type& aType, + sal_Bool bClear ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ) +{ + if (checkElement(aName)){ + m_xLayerHandler->overrideProperty(aName, aAttributes, aType, bClear); + pushElement(aName); + } + else + pushElement(aName, sal_False); +} + +void SAL_CALL CConfigFilter::setPropertyValue( + const Any& aValue ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ) +{ + if (checkCurrentElement()) + m_xLayerHandler->setPropertyValue(aValue); +} + +void SAL_CALL CConfigFilter::setPropertyValueForLocale( + const Any& aValue, + const OUString& aLocale ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ) +{ + if (checkCurrentElement()) + m_xLayerHandler->setPropertyValueForLocale(aValue, aLocale); +} + +void SAL_CALL CConfigFilter::endProperty() + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ) +{ + if (checkCurrentElement()) + { + m_xLayerHandler->endProperty(); + } + popElement(); + +} + +void SAL_CALL CConfigFilter::addProperty( + const rtl::OUString& aName, + sal_Int16 aAttributes, + const Type& aType ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ) +{ + if (checkElement(aName)) + m_xLayerHandler->addProperty(aName, aAttributes, aType); +} + +void SAL_CALL CConfigFilter::addPropertyWithValue( + const rtl::OUString& aName, + sal_Int16 aAttributes, + const Any& aValue ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ) +{ + // add property with value doesn't push the property + if (checkElement(aName)) + m_xLayerHandler->addPropertyWithValue(aName, aAttributes, aValue); + +} + +} // namespace desktop + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/cfgfilter.hxx b/desktop/source/migration/cfgfilter.hxx new file mode 100644 index 000000000000..cec890354e5e --- /dev/null +++ b/desktop/source/migration/cfgfilter.hxx @@ -0,0 +1,175 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#ifndef _DESKTOP_CFGFILTER_HXX_ +#define _DESKTOP_CFGFILTER_HXX_ + +#include <stack> + +#include <sal/types.h> +#include <rtl/ustring.hxx> + +#include <cppuhelper/implbase2.hxx> +#include <cppuhelper/implbase3.hxx> + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Type.hxx> + +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/configuration/backend/XLayer.hpp> +#include <com/sun/star/configuration/backend/XLayerHandler.hpp> +#include <com/sun/star/configuration/backend/TemplateIdentifier.hpp> + + +#include "migration_impl.hxx" + +#define NS_CSS com::sun::star +#define NS_UNO com::sun::star::uno + + +namespace desktop { + +struct element +{ + rtl::OUString name; + rtl::OUString path; + sal_Bool use; + +}; + +typedef std::stack< element > element_stack; + +// XInitialization: +// -> Source : XLayer +// XLayer +// XLayerHandler +class CConfigFilter : public cppu::WeakImplHelper3< + NS_CSS::configuration::backend::XLayer, + NS_CSS::configuration::backend::XLayerHandler, + NS_CSS::lang::XInitialization> +{ + +private: + NS_UNO::Reference< NS_CSS::configuration::backend::XLayerHandler > m_xLayerHandler; + NS_UNO::Reference< NS_CSS::configuration::backend::XLayer > m_xSourceLayer; + + rtl::OUString m_aCurrentComponent; + + const strings_v *m_pvInclude; + const strings_v *m_pvExclude; + + element_stack m_elementStack; + + void pushElement(rtl::OUString aName, sal_Bool bUse = sal_True); + void popElement(); + sal_Bool checkElement(rtl::OUString aName); + sal_Bool checkCurrentElement(); + +public: + CConfigFilter(const strings_v* include, const strings_v* exclude); + + // XInitialization + virtual void SAL_CALL initialize(const NS_UNO::Sequence< NS_UNO::Any >& seqArgs) + throw (NS_UNO::Exception); + + // XLayer + virtual void SAL_CALL readData( + const NS_UNO::Reference< NS_CSS::configuration::backend::XLayerHandler >& layerHandler) + throw (NS_CSS::lang::NullPointerException, NS_CSS::lang::WrappedTargetException, + NS_CSS::configuration::backend::MalformedDataException); + + // XLayerHandler + virtual void SAL_CALL startLayer() + throw(::com::sun::star::lang::WrappedTargetException); + + virtual void SAL_CALL endLayer() + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL overrideNode( + const rtl::OUString& aName, + sal_Int16 aAttributes, + sal_Bool bClear) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL addOrReplaceNode( + const rtl::OUString& aName, + sal_Int16 aAttributes) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL addOrReplaceNodeFromTemplate( + const rtl::OUString& aName, + const NS_CSS::configuration::backend::TemplateIdentifier& aTemplate, + sal_Int16 aAttributes ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL endNode() + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL dropNode( + const rtl::OUString& aName ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL overrideProperty( + const rtl::OUString& aName, + sal_Int16 aAttributes, + const NS_UNO::Type& aType, + sal_Bool bClear ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL setPropertyValue( + const NS_UNO::Any& aValue ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL setPropertyValueForLocale( + const NS_UNO::Any& aValue, + const rtl::OUString& aLocale ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL endProperty() + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL addProperty( + const rtl::OUString& aName, + sal_Int16 aAttributes, + const NS_UNO::Type& aType ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL addPropertyWithValue( + const rtl::OUString& aName, + sal_Int16 aAttributes, + const NS_UNO::Any& aValue ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + +}; + +} // namespace desktop +#undef NS_CSS +#undef NS_UNO + +#endif + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/makefile.mk b/desktop/source/migration/makefile.mk new file mode 100644 index 000000000000..2624fcda5a3e --- /dev/null +++ b/desktop/source/migration/makefile.mk @@ -0,0 +1,53 @@ +#************************************************************************* +# +# 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=mig +AUTOSEG=true +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +RSCEXTINC=..$/app + +# hacky - is no define +CDEFS+=-I..$/app +CDEFS+=-I$(PRJ)/inc + +SLOFILES = \ + $(SLO)$/migration.obj \ + $(SLO)$/cfgfilter.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/desktop/source/migration/migration.cxx b/desktop/source/migration/migration.cxx new file mode 100644 index 000000000000..e66d1269ea63 --- /dev/null +++ b/desktop/source/migration/migration.cxx @@ -0,0 +1,1368 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 <map> +#include <new> +#include <set> + +#include "migration.hxx" +#include "migration_impl.hxx" +#include "cfgfilter.hxx" + +#include <unotools/textsearch.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/sequence.hxx> +#include <unotools/bootstrap.hxx> +#include <rtl/bootstrap.hxx> +#include <rtl/uri.hxx> +#include <tools/config.hxx> +#include <i18npool/lang.h> +#include <tools/urlobj.hxx> +#include <osl/file.hxx> +#include <osl/mutex.hxx> +#include <ucbhelper/content.hxx> +#include <osl/security.hxx> +#include <unotools/configmgr.hxx> + +#include <com/sun/star/configuration/Update.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/task/XJob.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/util/XRefreshable.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> +#include <com/sun/star/util/XStringSubstitution.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/ui/XUIConfiguration.hpp> +#include <com/sun/star/ui/XUIConfigurationStorage.hpp> +#include <com/sun/star/ui/XUIConfigurationPersistence.hpp> + +using namespace rtl; +using namespace osl; +using namespace std; +using namespace com::sun::star::task; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::util; +using namespace com::sun::star::container; +using com::sun::star::uno::Exception; +using namespace com::sun::star; + +namespace desktop { + +static const ::rtl::OUString ITEM_DESCRIPTOR_COMMANDURL(RTL_CONSTASCII_USTRINGPARAM("CommandURL")); +static const ::rtl::OUString ITEM_DESCRIPTOR_CONTAINER(RTL_CONSTASCII_USTRINGPARAM("ItemDescriptorContainer")); +static const ::rtl::OUString ITEM_DESCRIPTOR_LABEL(RTL_CONSTASCII_USTRINGPARAM("Label")); + +static const ::rtl::OUString MENU_SEPERATOR(RTL_CONSTASCII_USTRINGPARAM(" | ")); +static const ::rtl::OUString MENU_SUBMENU(RTL_CONSTASCII_USTRINGPARAM("...")); +static const ::rtl::OUString MIGRATION_STAMP_NAME(RTL_CONSTASCII_USTRINGPARAM("/MIGRATED")); + +::rtl::OUString retrieveLabelFromCommand(const ::rtl::OUString& sCommand, const ::rtl::OUString& sModuleIdentifier) +{ + ::rtl::OUString sLabel; + + uno::Reference< container::XNameAccess > xUICommands; + uno::Reference< container::XNameAccess > xNameAccess( ::comphelper::getProcessServiceFactory()->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.UICommandDescription")) ), uno::UNO_QUERY ); + if ( xNameAccess.is() ) + { + uno::Any a = xNameAccess->getByName( sModuleIdentifier ); + a >>= xUICommands; + } + if (xUICommands.is()) + { + if ( sCommand.getLength() > 0 ) + { + rtl::OUString aStr; + ::uno::Sequence< beans::PropertyValue > aPropSeq; + try + { + uno::Any a( xUICommands->getByName( sCommand )); + if ( a >>= aPropSeq ) + { + for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ ) + { + if ( aPropSeq[i].Name.equalsAscii( "Label" )) + { + aPropSeq[i].Value >>= aStr; + break; + } + } + } + + sLabel = aStr; + } + + catch(container::NoSuchElementException&) + { + sLabel = sCommand; + sal_Int32 nIndex = sLabel.indexOf(':'); + if (nIndex>=0 && nIndex <= sLabel.getLength()-1) + sLabel = sLabel.copy(nIndex+1); + } + + } + } + + return sLabel; +} + +::rtl::OUString stripHotKey( const ::rtl::OUString& str ) +{ + sal_Int32 index = str.indexOf( '~' ); + if ( index == -1 ) + { + return str; + } + else + { + return str.replaceAt( index, 1, ::rtl::OUString() ); + } +} + +::rtl::OUString mapModuleShortNameToIdentifier(const ::rtl::OUString& sShortName) +{ + ::rtl::OUString sIdentifier; + + if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StartModule")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.StartModule")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("swriter")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextDocument")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("scalc")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.SpreadsheetDocument")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sdraw")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.DrawingDocument")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("simpress")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.PresentationDocument")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("smath")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.formula.FormulaProperties")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("schart")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.chart2.ChartDocument")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BasicIDE")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.BasicIDE")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("dbapp")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sdb.OfficeDatabaseDocument")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sglobal")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.GlobalDocument")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sweb")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.WebDocument")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("swxform")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xforms.XMLFormDocument")); + + else if (sShortName.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("sbibliography")))) + sIdentifier = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Bibliography")); + + return sIdentifier; +} + +bool MigrationImpl::alreadyMigrated() +{ + rtl::OUString aStr = m_aInfo.userdata + MIGRATION_STAMP_NAME; + File aFile(aStr); + // create migration stamp, and/or check its existence + bool bRet = aFile.open (osl_File_OpenFlag_Write | osl_File_OpenFlag_Create | osl_File_OpenFlag_NoLock) == FileBase::E_EXIST; + OSL_TRACE( "File '%s' exists? %d\n", + rtl::OUStringToOString(aStr, RTL_TEXTENCODING_ASCII_US).getStr(), + bRet ); + return bRet; +} + +bool MigrationImpl::initializeMigration() +{ + bool bRet = false; + + if (!checkMigrationCompleted()) { + readAvailableMigrations(m_vMigrationsAvailable); + sal_Int32 nIndex = findPreferedMigrationProcess(m_vMigrationsAvailable); + // m_aInfo is now set to the preferred migration source + if ( nIndex >= 0 ) { + if (alreadyMigrated()) + return false; + m_vrMigrations = readMigrationSteps(m_vMigrationsAvailable[nIndex].name); + } + + bRet = m_aInfo.userdata.getLength() > 0; + } + + OSL_TRACE( "Migration %s\n", bRet ? "needed" : "not required" ); + + return bRet; +} + +void Migration::migrateSettingsIfNecessary() +{ + MigrationImpl aImpl( comphelper::getProcessServiceFactory() ); + + if (! aImpl.initializeMigration() ) + return; + + sal_Bool bResult = sal_False; + try { + bResult = aImpl.doMigration(); + } catch (Exception& e) + { + OString aMsg("doMigration() exception: "); + aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US); + OSL_ENSURE(sal_False, aMsg.getStr()); + } + OSL_ENSURE(bResult, "Migration has not been successfull"); +} + +MigrationImpl::MigrationImpl(const uno::Reference< XMultiServiceFactory >& xFactory) + : m_vrVersions(new strings_v) + , m_xFactory(xFactory) +{ +} + +MigrationImpl::~MigrationImpl() +{ +} + +// The main entry point for migrating settings +sal_Bool MigrationImpl::doMigration() +{ + // compile file list for migration + m_vrFileList = compileFileList(); + + sal_Bool result = sal_False; + try + { + NewVersionUIInfo aNewVersionUIInfo; + ::std::vector< MigrationModuleInfo > vModulesInfo = dectectUIChangesForAllModules(); + aNewVersionUIInfo.init(vModulesInfo); + + copyFiles(); + + const ::rtl::OUString sMenubarResourceURL(RTL_CONSTASCII_USTRINGPARAM("private:resource/menubar/menubar")); + const ::rtl::OUString sToolbarResourcePre(RTL_CONSTASCII_USTRINGPARAM("private:resource/toolbar/")); + for (sal_uInt32 i=0; i<vModulesInfo.size(); ++i) + { + ::rtl::OUString sModuleIdentifier = mapModuleShortNameToIdentifier(vModulesInfo[i].sModuleShortName); + if (sModuleIdentifier.getLength()==0) + continue; + + uno::Sequence< uno::Any > lArgs(2); + ::rtl::OUString aOldCfgDataPath = m_aInfo.userdata + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/user/config/soffice.cfg/modules/")); + lArgs[0] <<= aOldCfgDataPath + vModulesInfo[i].sModuleShortName; + lArgs[1] <<= embed::ElementModes::READ; + + uno::Reference< lang::XSingleServiceFactory > xStorageFactory(m_xFactory->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.FileSystemStorageFactory"))), uno::UNO_QUERY); + uno::Reference< embed::XStorage > xModules; + + xModules = uno::Reference< embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), uno::UNO_QUERY); + uno::Reference< ui::XUIConfigurationManager > xOldCfgManager( m_xFactory->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.UIConfigurationManager"))), uno::UNO_QUERY ); + uno::Reference< ui::XUIConfigurationStorage > xOldCfgStorage( xOldCfgManager, uno::UNO_QUERY ); + uno::Reference< ui::XUIConfigurationPersistence > xOldCfgPersistence( xOldCfgManager, uno::UNO_QUERY ); + + if ( xOldCfgStorage.is() && xOldCfgPersistence.is() && xModules.is() ) + { + xOldCfgStorage->setStorage( xModules ); + xOldCfgPersistence->reload(); + } + + uno::Reference< ui::XUIConfigurationManager > xCfgManager = aNewVersionUIInfo.getConfigManager(vModulesInfo[i].sModuleShortName); + + if (vModulesInfo[i].bHasMenubar) + { + uno::Reference< container::XIndexContainer > xOldVersionMenuSettings = uno::Reference< container::XIndexContainer >(xOldCfgManager->getSettings(sMenubarResourceURL, sal_True), uno::UNO_QUERY); + uno::Reference< container::XIndexContainer > xNewVersionMenuSettings = aNewVersionUIInfo.getNewMenubarSettings(vModulesInfo[i].sModuleShortName); + ::rtl::OUString sParent; + compareOldAndNewConfig(sParent, xOldVersionMenuSettings, xNewVersionMenuSettings, sMenubarResourceURL); + mergeOldToNewVersion(xCfgManager, xNewVersionMenuSettings, sModuleIdentifier, sMenubarResourceURL); + } + + sal_Int32 nToolbars = vModulesInfo[i].m_vToolbars.size(); + if (nToolbars >0) + { + for (sal_Int32 j=0; j<nToolbars; ++j) + { + ::rtl::OUString sToolbarName = vModulesInfo[i].m_vToolbars[j]; + ::rtl::OUString sToolbarResourceURL = sToolbarResourcePre + sToolbarName; + + uno::Reference< container::XIndexContainer > xOldVersionToolbarSettings = uno::Reference< container::XIndexContainer >(xOldCfgManager->getSettings(sToolbarResourceURL, sal_True), uno::UNO_QUERY); + uno::Reference< container::XIndexContainer > xNewVersionToolbarSettings = aNewVersionUIInfo.getNewToolbarSettings(vModulesInfo[i].sModuleShortName, sToolbarName); + ::rtl::OUString sParent; + compareOldAndNewConfig(sParent, xOldVersionToolbarSettings, xNewVersionToolbarSettings, sToolbarResourceURL); + mergeOldToNewVersion(xCfgManager, xNewVersionToolbarSettings, sModuleIdentifier, sToolbarResourceURL); + } + } + + m_aOldVersionItemsHashMap.clear(); + m_aNewVersionItemsHashMap.clear(); + } + + // execute the migration items from Setup.xcu + copyConfig(); + + // execute custom migration services from Setup.xcu + // and refresh the cache + runServices(); + refresh(); + + result = sal_True; + } catch (...) + { + OString aMsg("An unexpected exception was thrown during migration"); + aMsg += "\nOldVersion: " + OUStringToOString(m_aInfo.productname, RTL_TEXTENCODING_ASCII_US); + aMsg += "\nDataPath : " + OUStringToOString(m_aInfo.userdata, RTL_TEXTENCODING_ASCII_US); + OSL_ENSURE(sal_False, aMsg.getStr()); + } + + // prevent running the migration multiple times + setMigrationCompleted(); + return result; +} + +void MigrationImpl::refresh() +{ + uno::Reference< XRefreshable > xRefresh(m_xFactory->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationProvider"))), uno::UNO_QUERY); + if (xRefresh.is()) + xRefresh->refresh(); + else + OSL_ENSURE(sal_False, "could not get XRefresh interface from default config provider. No refresh done."); + +} + +void MigrationImpl::setMigrationCompleted() +{ + try { + uno::Reference< XPropertySet > aPropertySet(getConfigAccess("org.openoffice.Setup/Office", true), uno::UNO_QUERY_THROW); + aPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("MigrationCompleted")), uno::makeAny(sal_True)); + uno::Reference< XChangesBatch >(aPropertySet, uno::UNO_QUERY_THROW)->commitChanges(); + } catch (...) { + // fail silently + } +} + +bool MigrationImpl::checkMigrationCompleted() +{ + sal_Bool bMigrationCompleted = sal_False; + try { + uno::Reference< XPropertySet > aPropertySet( + getConfigAccess("org.openoffice.Setup/Office"), uno::UNO_QUERY_THROW); + aPropertySet->getPropertyValue( + OUString(RTL_CONSTASCII_USTRINGPARAM("MigrationCompleted"))) >>= bMigrationCompleted; + + if( !bMigrationCompleted && getenv("SAL_DISABLE_USERMIGRATION" ) ) + { + // migration prevented - fake it's success + setMigrationCompleted(); + bMigrationCompleted = sal_True; + } + } catch (Exception&) { + // just return false... + } + OSL_TRACE( "Migration %s", bMigrationCompleted ? "already completed" : "not done" ); + + return bMigrationCompleted; +} + +static void insertSorted(migrations_available& rAvailableMigrations, supported_migration& aSupportedMigration) +{ + bool bInserted( false ); + migrations_available::iterator pIter = rAvailableMigrations.begin(); + while ( !bInserted && pIter != rAvailableMigrations.end()) + { + if ( pIter->nPriority < aSupportedMigration.nPriority ) + { + rAvailableMigrations.insert(pIter, aSupportedMigration ); + bInserted = true; + break; // i111193: insert invalidates iterator! + } + ++pIter; + } + if ( !bInserted ) + rAvailableMigrations.push_back( aSupportedMigration ); +} + +bool MigrationImpl::readAvailableMigrations(migrations_available& rAvailableMigrations) +{ + // get supported version names + uno::Reference< XNameAccess > aMigrationAccess(getConfigAccess("org.openoffice.Setup/Migration/SupportedVersions"), uno::UNO_QUERY_THROW); + uno::Sequence< OUString > seqSupportedVersions = aMigrationAccess->getElementNames(); + + const OUString aVersionIdentifiers( RTL_CONSTASCII_USTRINGPARAM( "VersionIdentifiers" )); + const OUString aPriorityIdentifier( RTL_CONSTASCII_USTRINGPARAM( "Priority" )); + + for (sal_Int32 i=0; i<seqSupportedVersions.getLength(); i++) + { + sal_Int32 nPriority( 0 ); + uno::Sequence< OUString > seqVersions; + uno::Reference< XNameAccess > xMigrationData( aMigrationAccess->getByName(seqSupportedVersions[i]), uno::UNO_QUERY_THROW ); + xMigrationData->getByName( aVersionIdentifiers ) >>= seqVersions; + xMigrationData->getByName( aPriorityIdentifier ) >>= nPriority; + + supported_migration aSupportedMigration; + aSupportedMigration.name = seqSupportedVersions[i]; + aSupportedMigration.nPriority = nPriority; + for (sal_Int32 j=0; j<seqVersions.getLength(); j++) + aSupportedMigration.supported_versions.push_back(seqVersions[j].trim()); + insertSorted( rAvailableMigrations, aSupportedMigration ); + OSL_TRACE( " available migration '%s'\n", + rtl::OUStringToOString( aSupportedMigration.name, RTL_TEXTENCODING_ASCII_US ).getStr() ); + } + + return true; +} + +migrations_vr MigrationImpl::readMigrationSteps(const ::rtl::OUString& rMigrationName) +{ + // get migration access + uno::Reference< XNameAccess > aMigrationAccess(getConfigAccess("org.openoffice.Setup/Migration/SupportedVersions"), uno::UNO_QUERY_THROW); + uno::Reference< XNameAccess > xMigrationData( aMigrationAccess->getByName(rMigrationName), uno::UNO_QUERY_THROW ); + + // get migration description from from org.openoffice.Setup/Migration + // and build vector of migration steps + OUString aMigrationSteps( RTL_CONSTASCII_USTRINGPARAM( "MigrationSteps" )); + uno::Reference< XNameAccess > theNameAccess(xMigrationData->getByName(aMigrationSteps), uno::UNO_QUERY_THROW); + uno::Sequence< OUString > seqMigrations = theNameAccess->getElementNames(); + uno::Reference< XNameAccess > tmpAccess; + uno::Reference< XNameAccess > tmpAccess2; + uno::Sequence< OUString > tmpSeq; + migrations_vr vrMigrations(new migrations_v); + for (sal_Int32 i = 0; i < seqMigrations.getLength(); i++) + { + // get current migration step + theNameAccess->getByName(seqMigrations[i]) >>= tmpAccess; + // tmpStepPtr = new migration_step(); + migration_step tmpStep; + tmpStep.name = seqMigrations[i]; + + // read included files from current step description + ::rtl::OUString aSeqEntry; + if (tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("IncludedFiles"))) >>= tmpSeq) + { + for (sal_Int32 j=0; j<tmpSeq.getLength(); j++) + { + aSeqEntry = tmpSeq[j]; + tmpStep.includeFiles.push_back(aSeqEntry); + } + } + + // exluded files... + if (tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("ExcludedFiles"))) >>= tmpSeq) + { + for (sal_Int32 j=0; j<tmpSeq.getLength(); j++) + tmpStep.excludeFiles.push_back(tmpSeq[j]); + } + + // included nodes... + if (tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("IncludedNodes"))) >>= tmpSeq) + { + for (sal_Int32 j=0; j<tmpSeq.getLength(); j++) + tmpStep.includeConfig.push_back(tmpSeq[j]); + } + + // excluded nodes... + if (tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("ExcludedNodes"))) >>= tmpSeq) + { + for (sal_Int32 j=0; j<tmpSeq.getLength(); j++) + tmpStep.excludeConfig.push_back(tmpSeq[j]); + } + + // included extensions... + if (tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("IncludedExtensions"))) >>= tmpSeq) + { + for (sal_Int32 j=0; j<tmpSeq.getLength(); j++) + tmpStep.includeExtensions.push_back(tmpSeq[j]); + } + + // excluded extensions... + if (tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("ExcludedExtensions"))) >>= tmpSeq) + { + for (sal_Int32 j=0; j<tmpSeq.getLength(); j++) + { + aSeqEntry = tmpSeq[j]; + tmpStep.excludeExtensions.push_back(aSeqEntry); + } + } + + // generic service + tmpAccess->getByName(OUString(RTL_CONSTASCII_USTRINGPARAM("MigrationService"))) >>= tmpStep.service; + + vrMigrations->push_back(tmpStep); + } + return vrMigrations; +} + +static FileBase::RC _checkAndCreateDirectory(INetURLObject& dirURL) +{ + FileBase::RC result = Directory::create(dirURL.GetMainURL(INetURLObject::DECODE_TO_IURI)); + if (result == FileBase::E_NOENT) + { + INetURLObject baseURL(dirURL); + baseURL.removeSegment(); + _checkAndCreateDirectory(baseURL); + return Directory::create(dirURL.GetMainURL(INetURLObject::DECODE_TO_IURI)); + } else + return result; +} + +install_info MigrationImpl::findInstallation(const strings_v& rVersions) +{ + rtl::OUString aProductName; + uno::Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME ); + aRet >>= aProductName; + aProductName = aProductName.toAsciiLowerCase(); + + install_info aInfo; + strings_v::const_iterator i_ver = rVersions.begin(); + uno::Reference < util::XStringSubstitution > xSubst( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.PathSubstitution"))), uno::UNO_QUERY ); + while (i_ver != rVersions.end()) + { + ::rtl::OUString aVersion, aProfileName; + sal_Int32 nSeparatorIndex = (*i_ver).indexOf('='); + if ( nSeparatorIndex != -1 ) + { + aVersion = (*i_ver).copy( 0, nSeparatorIndex ); + aProfileName = (*i_ver).copy( nSeparatorIndex+1 ); + } + + if ( aVersion.getLength() && aProfileName.getLength() && + ( !aInfo.userdata.getLength() || !aProfileName.toAsciiLowerCase().compareTo( aProductName, aProductName.getLength() ) ) + ) + { + ::rtl::OUString aUserInst; + osl::Security().getConfigDir( aUserInst ); + if ( aUserInst.getLength() && aUserInst[ aUserInst.getLength()-1 ] != '/' ) + aUserInst += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")); +#if defined UNX && ! defined MACOSX + // tribute to whoever had the "great" idea to use different names on Windows and Unix + aUserInst += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".")); +#endif + aUserInst += aProfileName; + try + { + INetURLObject aObj(aUserInst); + ::ucbhelper::Content aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ucb::XCommandEnvironment > () ); + aCnt.isDocument(); + aInfo.userdata = aObj.GetMainURL( INetURLObject::NO_DECODE ); + aInfo.productname = aVersion; + } + catch( uno::Exception& ){} + } + ++i_ver; + } + + return aInfo; +} + +sal_Int32 MigrationImpl::findPreferedMigrationProcess(const migrations_available& rAvailableMigrations) +{ + sal_Int32 nIndex( -1 ); + sal_Int32 i( 0 ); + + migrations_available::const_iterator rIter = rAvailableMigrations.begin(); + while ( rIter != rAvailableMigrations.end() ) + { + install_info aInstallInfo = findInstallation(rIter->supported_versions); + if (aInstallInfo.productname.getLength() > 0 ) + { + m_aInfo = aInstallInfo; + nIndex = i; + break; + } + ++i; + ++rIter; + } + + OSL_TRACE( " preferred migration is from product '%s'\n", + rtl::OUStringToOString( m_aInfo.productname, RTL_TEXTENCODING_ASCII_US ).getStr() ); + OSL_TRACE( " and settings directory '%s'\n", + rtl::OUStringToOString( m_aInfo.userdata, RTL_TEXTENCODING_ASCII_US ).getStr() ); + + return nIndex; +} + +strings_vr MigrationImpl::applyPatterns(const strings_v& vSet, const strings_v& vPatterns) const +{ + using namespace utl; + strings_vr vrResult(new strings_v); + strings_v::const_iterator i_set; + strings_v::const_iterator i_pat = vPatterns.begin(); + while (i_pat != vPatterns.end()) + { + // find matches for this pattern in input set + // and copy them to the result + SearchParam param(*i_pat, SearchParam::SRCH_REGEXP); + TextSearch ts(param, LANGUAGE_DONTKNOW); + i_set = vSet.begin(); + xub_StrLen start = 0; + xub_StrLen end = 0; + while (i_set != vSet.end()) + { + end = (xub_StrLen)(i_set->getLength()); + if (ts.SearchFrwrd(*i_set, &start, &end)) + vrResult->push_back(*i_set); + i_set++; + } + i_pat++; + } + return vrResult; +} + +strings_vr MigrationImpl::getAllFiles(const OUString& baseURL) const +{ + using namespace osl; + strings_vr vrResult(new strings_v); + + // get sub dirs + Directory dir(baseURL); + if (dir.open() == FileBase::E_None) + { + strings_v vSubDirs; + strings_vr vrSubResult; + + // work through directory contents... + DirectoryItem item; + FileStatus fs(FileStatusMask_Type | FileStatusMask_FileURL); + while (dir.getNextItem(item) == FileBase::E_None) + { + if (item.getFileStatus(fs) == FileBase::E_None) + { + if (fs.getFileType() == FileStatus::Directory) + vSubDirs.push_back(fs.getFileURL()); + else + vrResult->push_back(fs.getFileURL()); + } + } + + // recurse subfolders + strings_v::const_iterator i = vSubDirs.begin(); + while (i != vSubDirs.end()) + { + vrSubResult = getAllFiles(*i); + vrResult->insert(vrResult->end(), vrSubResult->begin(), vrSubResult->end()); + i++; + } + } + return vrResult; +} + +strings_vr MigrationImpl::compileFileList() +{ + + strings_vr vrResult(new strings_v); + strings_vr vrInclude; + strings_vr vrExclude; + strings_vr vrTemp; + +#ifdef SAL_OS2 + if (m_aInfo.userdata.getLength() == 0) + return vrResult; +#endif + + // get a list of all files: + strings_vr vrFiles = getAllFiles(m_aInfo.userdata); + + // get a file list result for each migration step + migrations_v::const_iterator i_migr = m_vrMigrations->begin(); + while (i_migr != m_vrMigrations->end()) + { + vrInclude = applyPatterns(*vrFiles, i_migr->includeFiles); + vrExclude = applyPatterns(*vrFiles, i_migr->excludeFiles); + subtract(*vrInclude, *vrExclude); + vrResult->insert(vrResult->end(), vrInclude->begin(), vrInclude->end()); + i_migr++; + } + return vrResult; +} + +namespace { + +struct componentParts { + std::set< rtl::OUString > includedPaths; + std::set< rtl::OUString > excludedPaths; +}; + +typedef std::map< rtl::OUString, componentParts > Components; + +bool getComponent(rtl::OUString const & path, rtl::OUString * component) { + OSL_ASSERT(component != 0); + if (path.getLength() == 0 || path[0] != '/') { + OSL_TRACE( + ("configuration migration in/exclude path %s ignored (does not" + " start with slash)"), + rtl::OUStringToOString(path, RTL_TEXTENCODING_UTF8).getStr()); + return false; + } + sal_Int32 i = path.indexOf('/', 1); + *component = i < 0 ? path.copy(1) : path.copy(1, i - 1); + return true; +} + +uno::Sequence< rtl::OUString > setToSeq(std::set< rtl::OUString > const & set) { + std::set< rtl::OUString >::size_type n = set.size(); + if (n > SAL_MAX_INT32) { + throw std::bad_alloc(); + } + uno::Sequence< rtl::OUString > seq(static_cast< sal_Int32 >(n)); + sal_Int32 i = 0; + for (std::set< rtl::OUString >::const_iterator j(set.begin()); + j != set.end(); ++j) + { + seq[i++] = *j; + } + return seq; +} + +} + +void MigrationImpl::copyConfig() { + Components comps; + for (migrations_v::const_iterator i(m_vrMigrations->begin()); + i != m_vrMigrations->end(); ++i) + { + for (strings_v::const_iterator j(i->includeConfig.begin()); + j != i->includeConfig.end(); ++j) + { + rtl::OUString comp; + if (getComponent(*j, &comp)) { + comps[comp].includedPaths.insert(*j); + } + } + for (strings_v::const_iterator j(i->excludeConfig.begin()); + j != i->excludeConfig.end(); ++j) + { + rtl::OUString comp; + if (getComponent(*j, &comp)) { + comps[comp].excludedPaths.insert(*j); + } + } + } + for (Components::const_iterator i(comps.begin()); i != comps.end(); ++i) { + if (!i->second.includedPaths.empty()) { + rtl::OUStringBuffer buf(m_aInfo.userdata); + buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("/user/registry/data")); + sal_Int32 n = 0; + do { + rtl::OUString seg(i->first.getToken(0, '.', n)); + rtl::OUString enc( + rtl::Uri::encode( + seg, rtl_UriCharClassPchar, rtl_UriEncodeStrict, + RTL_TEXTENCODING_UTF8)); + if (enc.getLength() == 0 && seg.getLength() != 0) { + OSL_TRACE( + ("configuration migration component %s ignored (cannot" + " be encoded as file path)"), + rtl::OUStringToOString( + i->first, RTL_TEXTENCODING_UTF8).getStr()); + goto next; + } + buf.append(sal_Unicode('/')); + buf.append(enc); + } while (n >= 0); + buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(".xcu")); + configuration::Update::get( + comphelper::getProcessComponentContext())-> + insertModificationXcuFile( + buf.makeStringAndClear(), setToSeq(i->second.includedPaths), + setToSeq(i->second.excludedPaths)); + } else { + OSL_TRACE( + ("configuration migration component %s ignored (only excludes," + " no includes)"), + rtl::OUStringToOString( + i->first, RTL_TEXTENCODING_UTF8).getStr()); + } + next:; + } +} + +// removes elements of vector 2 in vector 1 +void MigrationImpl::subtract(strings_v& va, const strings_v& vb_c) const +{ + strings_v vb(vb_c); + // ensure uniqueness of entries + sort(va.begin(), va.end()); + sort(vb.begin(), vb.end()); + unique(va.begin(), va.end()); + unique(vb.begin(), vb.end()); + + strings_v::const_iterator i_ex = vb.begin(); + strings_v::iterator i_in; + strings_v::iterator i_next; + while (i_ex != vb.end()) + { + i_in = va.begin(); + while (i_in != va.end()) + { + if ( *i_in == *i_ex) + { + i_next = i_in+1; + va.erase(i_in); + i_in = i_next; + // we can only find one match since we + // ensured uniquness of the entries. ergo: + break; + } + else + i_in++; + } + i_ex++; + } +} + +uno::Reference< XNameAccess > MigrationImpl::getConfigAccess(const sal_Char* pPath, sal_Bool bUpdate) +{ + uno::Reference< XNameAccess > xNameAccess; + try{ + OUString sConfigSrvc(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationProvider")); + OUString sAccessSrvc; + if (bUpdate) + sAccessSrvc = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationUpdateAccess")); + else + sAccessSrvc = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationAccess")); + + OUString sConfigURL = OUString::createFromAscii(pPath); + + // get configuration provider + uno::Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory(); + uno::Reference< XMultiServiceFactory > theConfigProvider = uno::Reference< XMultiServiceFactory > ( + theMSF->createInstance( sConfigSrvc ),uno::UNO_QUERY_THROW ); + + // access the provider + uno::Sequence< uno::Any > theArgs(1); + theArgs[ 0 ] <<= sConfigURL; + xNameAccess = uno::Reference< XNameAccess > ( + theConfigProvider->createInstanceWithArguments( + sAccessSrvc, theArgs ), uno::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; +} + +void MigrationImpl::copyFiles() +{ + strings_v::const_iterator i_file = m_vrFileList->begin(); + OUString localName; + OUString destName; + OUString userInstall; + utl::Bootstrap::PathStatus aStatus; + aStatus = utl::Bootstrap::locateUserInstallation(userInstall); + if (aStatus == utl::Bootstrap::PATH_EXISTS) + { + while (i_file != m_vrFileList->end()) + { + // remove installation prefix from file + localName = i_file->copy(m_aInfo.userdata.getLength()); + destName = userInstall + localName; + INetURLObject aURL(destName); + // check whether destination directory exists + aURL.removeSegment(); + _checkAndCreateDirectory(aURL); + FileBase::RC copyResult = File::copy(*i_file, destName); + if (copyResult != FileBase::E_None) + { + OString msg("Cannot copy "); + msg += OUStringToOString(*i_file, RTL_TEXTENCODING_UTF8) + " to " + + OUStringToOString(destName, RTL_TEXTENCODING_UTF8); + OSL_ENSURE(sal_False, msg.getStr()); + } + i_file++; + } + } + else + { + OSL_ENSURE(sal_False, "copyFiles: UserInstall does not exist"); + } +} + +void MigrationImpl::runServices() +{ + // Build argument array + uno::Sequence< uno::Any > seqArguments(3); + seqArguments[0] = uno::makeAny(NamedValue( + OUString(RTL_CONSTASCII_USTRINGPARAM("Productname")), + uno::makeAny(m_aInfo.productname))); + seqArguments[1] = uno::makeAny(NamedValue( + OUString(RTL_CONSTASCII_USTRINGPARAM("UserData")), + uno::makeAny(m_aInfo.userdata))); + + + // create an instance of every migration service + // and execute the migration job + uno::Reference< XJob > xMigrationJob; + + migrations_v::const_iterator i_mig = m_vrMigrations->begin(); + while (i_mig != m_vrMigrations->end()) + { + if( i_mig->service.getLength() > 0) + { + + try + { + // set black list for extension migration + uno::Sequence< rtl::OUString > seqExtBlackList; + sal_uInt32 nSize = i_mig->excludeExtensions.size(); + if ( nSize > 0 ) + seqExtBlackList = comphelper::arrayToSequence< ::rtl::OUString >( + &i_mig->excludeExtensions[0], nSize ); + seqArguments[2] = uno::makeAny(NamedValue( + OUString(RTL_CONSTASCII_USTRINGPARAM("ExtensionBlackList")), + uno::makeAny( seqExtBlackList ))); + + xMigrationJob = uno::Reference< XJob >(m_xFactory->createInstanceWithArguments( + i_mig->service, seqArguments), uno::UNO_QUERY_THROW); + + xMigrationJob->execute(uno::Sequence< NamedValue >()); + + + } catch (Exception& e) + { + OString aMsg("Execution of migration service failed (Exception caught).\nService: "); + aMsg += OUStringToOString(i_mig->service, RTL_TEXTENCODING_ASCII_US) + "\nMessage: "; + aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US); + OSL_ENSURE(sal_False, aMsg.getStr()); + } catch (...) + { + OString aMsg("Execution of migration service failed (Exception caught).\nService: "); + aMsg += OUStringToOString(i_mig->service, RTL_TEXTENCODING_ASCII_US) + + "\nNo message available"; + OSL_ENSURE(sal_False, aMsg.getStr()); + } + + } + i_mig++; + } +} + +::std::vector< MigrationModuleInfo > MigrationImpl::dectectUIChangesForAllModules() const +{ + ::std::vector< MigrationModuleInfo > vModulesInfo; + const ::rtl::OUString MENUBAR(RTL_CONSTASCII_USTRINGPARAM("menubar")); + const ::rtl::OUString TOOLBAR(RTL_CONSTASCII_USTRINGPARAM("toolbar")); + + uno::Sequence< uno::Any > lArgs(2); + lArgs[0] <<= m_aInfo.userdata + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/user/config/soffice.cfg/modules")); + lArgs[1] <<= embed::ElementModes::READ; + + uno::Reference< lang::XSingleServiceFactory > xStorageFactory(m_xFactory->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.FileSystemStorageFactory"))), uno::UNO_QUERY); + uno::Reference< embed::XStorage > xModules; + + xModules = uno::Reference< embed::XStorage >(xStorageFactory->createInstanceWithArguments(lArgs), uno::UNO_QUERY); + if (!xModules.is()) + return vModulesInfo; + + uno::Reference< container::XNameAccess > xAccess = uno::Reference< container::XNameAccess >(xModules, uno::UNO_QUERY); + uno::Sequence< ::rtl::OUString > lNames = xAccess->getElementNames(); + sal_Int32 nLength = lNames.getLength(); + for (sal_Int32 i=0; i<nLength; ++i) + { + ::rtl::OUString sModuleShortName = lNames[i]; + uno::Reference< embed::XStorage > xModule = xModules->openStorageElement(sModuleShortName, embed::ElementModes::READ); + if (xModule.is()) + { + MigrationModuleInfo aModuleInfo; + + uno::Reference< embed::XStorage > xMenubar = xModule->openStorageElement(MENUBAR, embed::ElementModes::READ); + if (xMenubar.is()) + { + uno::Reference< container::XNameAccess > xNameAccess = uno::Reference< container::XNameAccess >(xMenubar, uno::UNO_QUERY); + if (xNameAccess->getElementNames().getLength() > 0) + { + aModuleInfo.sModuleShortName = sModuleShortName; + aModuleInfo.bHasMenubar = sal_True; + } + } + + uno::Reference< embed::XStorage > xToolbar = xModule->openStorageElement(TOOLBAR, embed::ElementModes::READ); + if (xToolbar.is()) + { + const ::rtl::OUString RESOURCEURL_CUSTOM_ELEMENT(RTL_CONSTASCII_USTRINGPARAM("custom_")); + sal_Int32 nCustomLen = 7; + + uno::Reference< container::XNameAccess > xNameAccess = uno::Reference< container::XNameAccess >(xToolbar, uno::UNO_QUERY); + ::uno::Sequence< ::rtl::OUString > lToolbars = xNameAccess->getElementNames(); + for (sal_Int32 j=0; j<lToolbars.getLength(); ++j) + { + ::rtl::OUString sToolbarName = lToolbars[j]; + if (sToolbarName.getLength()>=nCustomLen && + sToolbarName.copy(0, nCustomLen).equals(RESOURCEURL_CUSTOM_ELEMENT)) + continue; + + aModuleInfo.sModuleShortName = sModuleShortName; + sal_Int32 nIndex = sToolbarName.lastIndexOf('.'); + if (nIndex > 0) + { + ::rtl::OUString sExtension(sToolbarName.copy(nIndex)); + ::rtl::OUString sToolbarResourceName(sToolbarName.copy(0, nIndex)); + if (sToolbarResourceName.getLength()>0 && sExtension.equalsAsciiL(".xml", 4)) + aModuleInfo.m_vToolbars.push_back(sToolbarResourceName); + } + } + } + + if (aModuleInfo.sModuleShortName.getLength()>0) + vModulesInfo.push_back(aModuleInfo); + } + } + + return vModulesInfo; +} + +void MigrationImpl::compareOldAndNewConfig(const ::rtl::OUString& sParent, + const uno::Reference< container::XIndexContainer >& xIndexOld, + const uno::Reference< container::XIndexContainer >& xIndexNew, + const ::rtl::OUString& sResourceURL) +{ + ::std::vector< MigrationItem > vOldItems; + ::std::vector< MigrationItem > vNewItems; + uno::Sequence< beans::PropertyValue > aProp; + sal_Int32 nOldCount = xIndexOld->getCount(); + sal_Int32 nNewCount = xIndexNew->getCount(); + + for (int n=0; n<nOldCount; ++n) + { + MigrationItem aMigrationItem; + if (xIndexOld->getByIndex(n) >>= aProp) + { + for(int i=0; i<aProp.getLength(); ++i) + { + if (aProp[i].Name.equals(ITEM_DESCRIPTOR_COMMANDURL)) + aProp[i].Value >>= aMigrationItem.m_sCommandURL; + else if (aProp[i].Name.equals(ITEM_DESCRIPTOR_CONTAINER)) + aProp[i].Value >>= aMigrationItem.m_xPopupMenu; + } + + if (aMigrationItem.m_sCommandURL.getLength()) + vOldItems.push_back(aMigrationItem); + } + } + + for (int n=0; n<nNewCount; ++n) + { + MigrationItem aMigrationItem; + if (xIndexNew->getByIndex(n) >>= aProp) + { + for(int i=0; i<aProp.getLength(); ++i) + { + if (aProp[i].Name.equals(ITEM_DESCRIPTOR_COMMANDURL)) + aProp[i].Value >>= aMigrationItem.m_sCommandURL; + else if (aProp[i].Name.equals(ITEM_DESCRIPTOR_CONTAINER)) + aProp[i].Value >>= aMigrationItem.m_xPopupMenu; + } + + if (aMigrationItem.m_sCommandURL.getLength()) + vNewItems.push_back(aMigrationItem); + } + } + + ::std::vector< MigrationItem >::iterator it; + + ::rtl::OUString sSibling; + for (it = vOldItems.begin(); it!=vOldItems.end(); ++it) + { + ::std::vector< MigrationItem >::iterator pFound = ::std::find(vNewItems.begin(), vNewItems.end(), *it); + if (pFound != vNewItems.end() && it->m_xPopupMenu.is()) + { + ::rtl::OUString sName; + if (sParent.getLength()>0) + sName = sParent + MENU_SEPERATOR + it->m_sCommandURL; + else + sName = it->m_sCommandURL; + compareOldAndNewConfig(sName, it->m_xPopupMenu, pFound->m_xPopupMenu, sResourceURL); + } + else if (pFound == vNewItems.end()) + { + MigrationItem aMigrationItem(sParent, sSibling, it->m_sCommandURL, it->m_xPopupMenu); + if (m_aOldVersionItemsHashMap.find(sResourceURL)==m_aOldVersionItemsHashMap.end()) + { + ::std::vector< MigrationItem > vMigrationItems; + m_aOldVersionItemsHashMap.insert(MigrationHashMap::value_type(sResourceURL, vMigrationItems)); + m_aOldVersionItemsHashMap[sResourceURL].push_back(aMigrationItem); + } + else + { + if (::std::find(m_aOldVersionItemsHashMap[sResourceURL].begin(), m_aOldVersionItemsHashMap[sResourceURL].end(), aMigrationItem)==m_aOldVersionItemsHashMap[sResourceURL].end()) + m_aOldVersionItemsHashMap[sResourceURL].push_back(aMigrationItem); + } + } + + sSibling = it->m_sCommandURL; + } + + ::rtl::OUString sNewSibling; + uno::Reference< container::XIndexContainer > xPopup; + for (it = vNewItems.begin(); it!=vNewItems.end(); ++it) + { + ::std::vector< MigrationItem >::iterator pFound = ::std::find(vOldItems.begin(), vOldItems.end(), *it); + if (pFound != vOldItems.end() && it->m_xPopupMenu.is()) + { + ::rtl::OUString sName; + if (sParent.getLength()>0) + sName = sParent + MENU_SEPERATOR + it->m_sCommandURL; + else + sName = it->m_sCommandURL; + compareOldAndNewConfig(sName, pFound->m_xPopupMenu, it->m_xPopupMenu, sResourceURL); + } + else if (::std::find(vOldItems.begin(), vOldItems.end(), *it) == vOldItems.end()) + { + MigrationItem aMigrationItem(sParent, sSibling, it->m_sCommandURL, it->m_xPopupMenu); + if (m_aNewVersionItemsHashMap.find(sResourceURL)==m_aNewVersionItemsHashMap.end()) + { + ::std::vector< MigrationItem > vMigrationItems; + m_aNewVersionItemsHashMap.insert(MigrationHashMap::value_type(sResourceURL, vMigrationItems)); + m_aNewVersionItemsHashMap[sResourceURL].push_back(aMigrationItem); + } + else + { + if (::std::find(m_aNewVersionItemsHashMap[sResourceURL].begin(), m_aNewVersionItemsHashMap[sResourceURL].end(), aMigrationItem)==m_aNewVersionItemsHashMap[sResourceURL].end()) + m_aNewVersionItemsHashMap[sResourceURL].push_back(aMigrationItem); + } + } + } +} + +void MigrationImpl::mergeOldToNewVersion(const uno::Reference< ui::XUIConfigurationManager >& xCfgManager, + const uno::Reference< container::XIndexContainer>& xIndexContainer, + const ::rtl::OUString& sModuleIdentifier, + const ::rtl::OUString& sResourceURL) +{ + MigrationHashMap::iterator pFound = m_aOldVersionItemsHashMap.find(sResourceURL); + if (pFound==m_aOldVersionItemsHashMap.end()) + return; + + ::std::vector< MigrationItem >::iterator it; + for (it=pFound->second.begin(); it!=pFound->second.end(); ++it) + { + uno::Reference< container::XIndexContainer > xTemp = xIndexContainer; + + ::rtl::OUString sParentNodeName = it->m_sParentNodeName; + sal_Int32 nIndex = 0; + do + { + ::rtl::OUString sToken = sParentNodeName.getToken(0, '|', nIndex).trim(); + if (sToken.getLength()<=0) + break; + + sal_Int32 nCount = xTemp->getCount(); + for (sal_Int32 i=0; i<nCount; ++i) + { + ::rtl::OUString sCommandURL; + ::rtl::OUString sLabel; + uno::Reference< container::XIndexContainer > xChild; + + uno::Sequence< beans::PropertyValue > aPropSeq; + xTemp->getByIndex(i) >>= aPropSeq; + for (sal_Int32 j=0; j<aPropSeq.getLength(); ++j) + { + ::rtl::OUString sPropName = aPropSeq[j].Name; + if (sPropName.equals(ITEM_DESCRIPTOR_COMMANDURL)) + aPropSeq[j].Value >>= sCommandURL; + else if (sPropName.equals(ITEM_DESCRIPTOR_LABEL)) + aPropSeq[j].Value >>= sLabel; + else if (sPropName.equals(ITEM_DESCRIPTOR_CONTAINER)) + aPropSeq[j].Value >>= xChild; + } + + if (sCommandURL == sToken) + { + xTemp = xChild; + break; + } + } + + } while (nIndex>=0); + + if (nIndex == -1) + { + uno::Sequence< beans::PropertyValue > aPropSeq(3); + + aPropSeq[0].Name = ITEM_DESCRIPTOR_COMMANDURL; + aPropSeq[0].Value <<= it->m_sCommandURL; + aPropSeq[1].Name = ITEM_DESCRIPTOR_LABEL; + aPropSeq[1].Value <<= retrieveLabelFromCommand(it->m_sCommandURL, sModuleIdentifier); + aPropSeq[2].Name = ITEM_DESCRIPTOR_CONTAINER; + aPropSeq[2].Value <<= it->m_xPopupMenu; + + if (it->m_sPrevSibling.getLength() == 0) + xTemp->insertByIndex(0, uno::makeAny(aPropSeq)); + else if (it->m_sPrevSibling.getLength() > 0) + { + sal_Int32 nCount = xTemp->getCount(); + sal_Int32 i = 0; + for (; i<nCount; ++i) + { + ::rtl::OUString sCmd; + uno::Sequence< beans::PropertyValue > aTempPropSeq; + xTemp->getByIndex(i) >>= aTempPropSeq; + for (sal_Int32 j=0; j<aTempPropSeq.getLength(); ++j) + { + if (aTempPropSeq[j].Name.equals(ITEM_DESCRIPTOR_COMMANDURL)) + { + aTempPropSeq[j].Value >>= sCmd; + break; + } + } + + if (sCmd.equals(it->m_sPrevSibling)) + break; + } + + xTemp->insertByIndex(i+1, uno::makeAny(aPropSeq)); + } + } + } + + uno::Reference< container::XIndexAccess > xIndexAccess(xIndexContainer, uno::UNO_QUERY); + if (xIndexAccess.is()) + xCfgManager->replaceSettings(sResourceURL, xIndexAccess); + + uno::Reference< ui::XUIConfigurationPersistence > xUIConfigurationPersistence(xCfgManager, uno::UNO_QUERY); + if (xUIConfigurationPersistence.is()) + xUIConfigurationPersistence->store(); +} + +uno::Reference< ui::XUIConfigurationManager > NewVersionUIInfo::getConfigManager(const ::rtl::OUString& sModuleShortName) const +{ + uno::Reference< ui::XUIConfigurationManager > xCfgManager; + + for (sal_Int32 i=0; i<m_lCfgManagerSeq.getLength(); ++i) + { + if (m_lCfgManagerSeq[i].Name.equals(sModuleShortName)) + { + m_lCfgManagerSeq[i].Value >>= xCfgManager; + break; + } + } + + return xCfgManager; +} + +uno::Reference< container::XIndexContainer > NewVersionUIInfo::getNewMenubarSettings(const ::rtl::OUString& sModuleShortName) const +{ + uno::Reference< container::XIndexContainer > xNewMenuSettings; + + for (sal_Int32 i=0; i<m_lNewVersionMenubarSettingsSeq.getLength(); ++i) + { + if (m_lNewVersionMenubarSettingsSeq[i].Name.equals(sModuleShortName)) + { + m_lNewVersionMenubarSettingsSeq[i].Value >>= xNewMenuSettings; + break; + } + } + + return xNewMenuSettings; +} + +uno::Reference< container::XIndexContainer > NewVersionUIInfo::getNewToolbarSettings(const ::rtl::OUString& sModuleShortName, const ::rtl::OUString& sToolbarName) const +{ + uno::Reference< container::XIndexContainer > xNewToolbarSettings; + + for (sal_Int32 i=0; i<m_lNewVersionToolbarSettingsSeq.getLength(); ++i) + { + if (m_lNewVersionToolbarSettingsSeq[i].Name.equals(sModuleShortName)) + { + uno::Sequence< beans::PropertyValue > lToolbarSettingsSeq; + m_lNewVersionToolbarSettingsSeq[i].Value >>= lToolbarSettingsSeq; + for (sal_Int32 j=0; j<lToolbarSettingsSeq.getLength(); ++j) + { + if (lToolbarSettingsSeq[j].Name.equals(sToolbarName)) + { + lToolbarSettingsSeq[j].Value >>= xNewToolbarSettings; + break; + } + } + + break; + } + } + + return xNewToolbarSettings; +} + +void NewVersionUIInfo::init(const ::std::vector< MigrationModuleInfo >& vModulesInfo) +{ + m_lCfgManagerSeq.realloc(vModulesInfo.size()); + m_lNewVersionMenubarSettingsSeq.realloc(vModulesInfo.size()); + m_lNewVersionToolbarSettingsSeq.realloc(vModulesInfo.size()); + + const ::rtl::OUString sModuleCfgSupplier(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.ModuleUIConfigurationManagerSupplier")); + const ::rtl::OUString sMenubarResourceURL(RTL_CONSTASCII_USTRINGPARAM("private:resource/menubar/menubar")); + const ::rtl::OUString sToolbarResourcePre(RTL_CONSTASCII_USTRINGPARAM("private:resource/toolbar/")); + + uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xModuleCfgSupplier = uno::Reference< ui::XModuleUIConfigurationManagerSupplier >(::comphelper::getProcessServiceFactory()->createInstance(sModuleCfgSupplier), uno::UNO_QUERY); + + for (sal_uInt32 i=0; i<vModulesInfo.size(); ++i) + { + ::rtl::OUString sModuleIdentifier = mapModuleShortNameToIdentifier(vModulesInfo[i].sModuleShortName); + if (sModuleIdentifier.getLength() > 0) + { + uno::Reference< ui::XUIConfigurationManager > xCfgManager = xModuleCfgSupplier->getUIConfigurationManager(sModuleIdentifier); + m_lCfgManagerSeq[i].Name = vModulesInfo[i].sModuleShortName; + m_lCfgManagerSeq[i].Value <<= xCfgManager; + + if (vModulesInfo[i].bHasMenubar) + { + m_lNewVersionMenubarSettingsSeq[i].Name = vModulesInfo[i].sModuleShortName; + m_lNewVersionMenubarSettingsSeq[i].Value <<= xCfgManager->getSettings(sMenubarResourceURL, sal_True); + } + + sal_Int32 nToolbars = vModulesInfo[i].m_vToolbars.size(); + if (nToolbars > 0) + { + uno::Sequence< beans::PropertyValue > lPropSeq(nToolbars); + for (sal_Int32 j=0; j<nToolbars; ++j) + { + ::rtl::OUString sToolbarName = vModulesInfo[i].m_vToolbars[j]; + ::rtl::OUString sToolbarResourceURL = sToolbarResourcePre + sToolbarName; + + lPropSeq[j].Name = sToolbarName; + lPropSeq[j].Value <<= xCfgManager->getSettings(sToolbarResourceURL, sal_True); + } + + m_lNewVersionToolbarSettingsSeq[i].Name = vModulesInfo[i].sModuleShortName; + m_lNewVersionToolbarSettingsSeq[i].Value <<= lPropSeq; + } + } + } +} + +} // namespace desktop + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/migration_impl.hxx b/desktop/source/migration/migration_impl.hxx new file mode 100644 index 000000000000..d66cabad941e --- /dev/null +++ b/desktop/source/migration/migration_impl.hxx @@ -0,0 +1,254 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_MIGRATION_IMPL_HXX_ +#define _DESKTOP_MIGRATION_IMPL_HXX_ + +#include <vector> +#include <algorithm> +#include <memory> +#include <hash_map> + +#include "migration.hxx" + +#include <sal/types.h> +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> + +#include <com/sun/star/uno/Reference.hxx> + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/lang/XSingleComponentFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp> +#include <com/sun/star/ui/XUIConfigurationManager.hpp> +#include <com/sun/star/ui/XUIConfigurationPersistence.hpp> + +#define NS_CSS com::sun::star +#define NS_UNO com::sun::star::uno + +namespace desktop +{ + +struct install_info +{ + rtl::OUString productname; // human readeable product name + rtl::OUString userdata; // file: url for user installation +}; + +typedef std::vector< rtl::OUString > strings_v; +typedef std::auto_ptr< strings_v > strings_vr; + +struct migration_step +{ + rtl::OUString name; + strings_v includeFiles; + strings_v excludeFiles; + strings_v includeConfig; + strings_v excludeConfig; + strings_v includeExtensions; + strings_v excludeExtensions; + rtl::OUString service; +}; + +struct supported_migration +{ + rtl::OUString name; + sal_Int32 nPriority; + strings_v supported_versions; +}; + +typedef std::vector< migration_step > migrations_v; +typedef std::auto_ptr< migrations_v > migrations_vr; +typedef std::vector< supported_migration > migrations_available; + +//__________________________________________ +/** + define the item, e.g.:menuitem, toolbaritem, to be migrated. we keep the information + of the command URL, the previous sibling node and the parent node of a item +*/ +struct MigrationItem +{ + ::rtl::OUString m_sParentNodeName; + ::rtl::OUString m_sPrevSibling; + ::rtl::OUString m_sCommandURL; + NS_UNO::Reference< NS_CSS::container::XIndexContainer > m_xPopupMenu; + + MigrationItem() + :m_xPopupMenu(0) + { + } + + MigrationItem(const ::rtl::OUString& sParentNodeName, + const ::rtl::OUString& sPrevSibling, + const ::rtl::OUString& sCommandURL, + const NS_UNO::Reference< NS_CSS::container::XIndexContainer > xPopupMenu) + { + m_sParentNodeName = sParentNodeName; + m_sPrevSibling = sPrevSibling; + m_sCommandURL = sCommandURL; + m_xPopupMenu = xPopupMenu; + } + + MigrationItem& operator=(const MigrationItem& aMigrationItem) + { + m_sParentNodeName = aMigrationItem.m_sParentNodeName; + m_sPrevSibling = aMigrationItem.m_sPrevSibling; + m_sCommandURL = aMigrationItem.m_sCommandURL; + m_xPopupMenu = aMigrationItem.m_xPopupMenu; + + return *this; + } + + sal_Bool operator==(const MigrationItem& aMigrationItem) + { + return ( aMigrationItem.m_sParentNodeName == m_sParentNodeName && + aMigrationItem.m_sPrevSibling == m_sPrevSibling && + aMigrationItem.m_sCommandURL == m_sCommandURL && + aMigrationItem.m_xPopupMenu.is() == m_xPopupMenu.is() ); + } + + ::rtl::OUString GetPrevSibling() const { return m_sPrevSibling; } +}; + +typedef ::std::hash_map< ::rtl::OUString, + ::std::vector< MigrationItem >, + ::rtl::OUStringHash, + ::std::equal_to< ::rtl::OUString > > MigrationHashMap; + +struct MigrationItemInfo +{ + ::rtl::OUString m_sResourceURL; + MigrationItem m_aMigrationItem; + + MigrationItemInfo(){} + + MigrationItemInfo(const ::rtl::OUString& sResourceURL, const MigrationItem& aMigratiionItem) + { + m_sResourceURL = sResourceURL; + m_aMigrationItem = aMigratiionItem; + } +}; + +//__________________________________________ +/** + information for the UI elements to be migrated for one module +*/ +struct MigrationModuleInfo +{ + ::rtl::OUString sModuleShortName; + sal_Bool bHasMenubar; + ::std::vector< ::rtl::OUString > m_vToolbars; + + MigrationModuleInfo():bHasMenubar(sal_False){}; +}; + +//__________________________________________ +/** + get the information before copying the ui configuration files of old version to new version +*/ +class NewVersionUIInfo +{ +public: + + NS_UNO::Reference< NS_CSS::ui::XUIConfigurationManager > getConfigManager(const ::rtl::OUString& sModuleShortName) const; + NS_UNO::Reference< NS_CSS::container::XIndexContainer > getNewMenubarSettings(const ::rtl::OUString& sModuleShortName) const; + NS_UNO::Reference< NS_CSS::container::XIndexContainer > getNewToolbarSettings(const ::rtl::OUString& sModuleShortName, const ::rtl::OUString& sToolbarName) const; + void init(const ::std::vector< MigrationModuleInfo >& vModulesInfo); + +private: + + NS_UNO::Sequence< NS_CSS::beans::PropertyValue > m_lCfgManagerSeq; + NS_UNO::Sequence< NS_CSS::beans::PropertyValue > m_lNewVersionMenubarSettingsSeq; + NS_UNO::Sequence< NS_CSS::beans::PropertyValue > m_lNewVersionToolbarSettingsSeq; +}; + +class MigrationImpl +{ + +private: + strings_vr m_vrVersions; + NS_UNO::Reference< NS_CSS::lang::XMultiServiceFactory > m_xFactory; + + migrations_available m_vMigrationsAvailable; // list of all available migrations + migrations_vr m_vrMigrations; // list of all migration specs from config + install_info m_aInfo; // info about the version being migrated + strings_vr m_vrFileList; // final list of files to be copied + MigrationHashMap m_aOldVersionItemsHashMap; + MigrationHashMap m_aNewVersionItemsHashMap; + ::rtl::OUString m_sModuleIdentifier; + + // functions to control the migration process + bool readAvailableMigrations(migrations_available&); + bool alreadyMigrated(); + migrations_vr readMigrationSteps(const ::rtl::OUString& rMigrationName); + sal_Int32 findPreferedMigrationProcess(const migrations_available&); + install_info findInstallation(const strings_v& rVersions); + strings_vr compileFileList(); + + // helpers + void subtract(strings_v& va, const strings_v& vb_c) const; + strings_vr getAllFiles(const rtl::OUString& baseURL) const; + strings_vr applyPatterns(const strings_v& vSet, const strings_v& vPatterns) const; + NS_UNO::Reference< NS_CSS::container::XNameAccess > getConfigAccess(const sal_Char* path, sal_Bool rw=sal_False); + + ::std::vector< MigrationModuleInfo > dectectUIChangesForAllModules() const; + void compareOldAndNewConfig(const ::rtl::OUString& sParentNodeName, + const NS_UNO::Reference< NS_CSS::container::XIndexContainer >& xOldIndexContainer, + const NS_UNO::Reference< NS_CSS::container::XIndexContainer >& xNewIndexContainer, + const ::rtl::OUString& sToolbarName); + void mergeOldToNewVersion(const NS_UNO::Reference< NS_CSS::ui::XUIConfigurationManager >& xCfgManager, + const NS_UNO::Reference< NS_CSS::container::XIndexContainer>& xIndexContainer, + const ::rtl::OUString& sModuleIdentifier, + const ::rtl::OUString& sResourceURL); + + // actual processing function that perform the migration steps + void copyFiles(); + void copyConfig(); + void runServices(); + void refresh(); + + void setMigrationCompleted(); + bool checkMigrationCompleted(); + +public: + MigrationImpl(const NS_UNO::Reference< NS_CSS::lang::XMultiServiceFactory >&); + ~MigrationImpl(); + bool initializeMigration(); + sal_Bool doMigration(); + rtl::OUString getOldVersionName(); +}; +} +#undef NS_CSS +#undef NS_UNO + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/autocorrmigration.cxx b/desktop/source/migration/services/autocorrmigration.cxx new file mode 100644 index 000000000000..1f5290f383cf --- /dev/null +++ b/desktop/source/migration/services/autocorrmigration.cxx @@ -0,0 +1,288 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "autocorrmigration.hxx" +#include <i18npool/mslangid.hxx> +#include <tools/urlobj.hxx> +#include <unotools/bootstrap.hxx> + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + + +//......................................................................... +namespace migration +{ +//......................................................................... + + + static ::rtl::OUString sSourceSubDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/autocorr" ) ); + static ::rtl::OUString sTargetSubDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/autocorr" ) ); + static ::rtl::OUString sBaseName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/acor" ) ); + static ::rtl::OUString sSuffix = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".dat" ) ); + + + // ============================================================================= + // component operations + // ============================================================================= + + ::rtl::OUString AutocorrectionMigration_getImplementationName() + { + static ::rtl::OUString* pImplName = 0; + if ( !pImplName ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !pImplName ) + { + static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.desktop.migration.Autocorrection" ) ); + pImplName = &aImplName; + } + } + return *pImplName; + } + + // ----------------------------------------------------------------------------- + + Sequence< ::rtl::OUString > AutocorrectionMigration_getSupportedServiceNames() + { + static Sequence< ::rtl::OUString >* pNames = 0; + if ( !pNames ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !pNames ) + { + static Sequence< ::rtl::OUString > aNames(1); + aNames.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.migration.Autocorrection" ) ); + pNames = &aNames; + } + } + return *pNames; + } + + // ============================================================================= + // AutocorrectionMigration + // ============================================================================= + + AutocorrectionMigration::AutocorrectionMigration() + { + } + + // ----------------------------------------------------------------------------- + + AutocorrectionMigration::~AutocorrectionMigration() + { + } + + // ----------------------------------------------------------------------------- + + TStringVectorPtr AutocorrectionMigration::getFiles( const ::rtl::OUString& rBaseURL ) const + { + TStringVectorPtr aResult( new TStringVector ); + ::osl::Directory aDir( rBaseURL); + + if ( aDir.open() == ::osl::FileBase::E_None ) + { + // iterate over directory content + TStringVector aSubDirs; + ::osl::DirectoryItem aItem; + while ( aDir.getNextItem( aItem ) == ::osl::FileBase::E_None ) + { + ::osl::FileStatus aFileStatus( FileStatusMask_Type | FileStatusMask_FileURL ); + if ( aItem.getFileStatus( aFileStatus ) == ::osl::FileBase::E_None ) + { + if ( aFileStatus.getFileType() == ::osl::FileStatus::Directory ) + aSubDirs.push_back( aFileStatus.getFileURL() ); + else + aResult->push_back( aFileStatus.getFileURL() ); + } + } + + // iterate recursive over subfolders + TStringVector::const_iterator aI = aSubDirs.begin(); + while ( aI != aSubDirs.end() ) + { + TStringVectorPtr aSubResult = getFiles( *aI ); + aResult->insert( aResult->end(), aSubResult->begin(), aSubResult->end() ); + ++aI; + } + } + + return aResult; + } + + // ----------------------------------------------------------------------------- + + ::osl::FileBase::RC AutocorrectionMigration::checkAndCreateDirectory( INetURLObject& rDirURL ) + { + ::osl::FileBase::RC aResult = ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) ); + if ( aResult == ::osl::FileBase::E_NOENT ) + { + INetURLObject aBaseURL( rDirURL ); + aBaseURL.removeSegment(); + checkAndCreateDirectory( aBaseURL ); + return ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) ); + } + else + { + return aResult; + } + } + + // ----------------------------------------------------------------------------- + + void AutocorrectionMigration::copyFiles() + { + ::rtl::OUString sTargetDir; + ::utl::Bootstrap::PathStatus aStatus = ::utl::Bootstrap::locateUserInstallation( sTargetDir ); + if ( aStatus == ::utl::Bootstrap::PATH_EXISTS ) + { + sTargetDir += sTargetSubDir; + TStringVectorPtr aFileList = getFiles( m_sSourceDir ); + TStringVector::const_iterator aI = aFileList->begin(); + while ( aI != aFileList->end() ) + { + ::rtl::OUString sSourceLocalName = aI->copy( m_sSourceDir.getLength() ); + sal_Int32 nStart = sBaseName.getLength(); + sal_Int32 nEnd = sSourceLocalName.lastIndexOf ( sSuffix ); + ::rtl::OUString sLanguageType = sSourceLocalName.copy( nStart, nEnd - nStart ); + ::rtl::OUString sIsoName = MsLangId::convertLanguageToIsoString( (LanguageType) sLanguageType.toInt32() ); + ::rtl::OUString sTargetLocalName = sBaseName; + sTargetLocalName += ::rtl::OUString::createFromAscii( "_" ); + sTargetLocalName += sIsoName; + sTargetLocalName += sSuffix; + ::rtl::OUString sTargetName = sTargetDir + sTargetLocalName; + INetURLObject aURL( sTargetName ); + aURL.removeSegment(); + checkAndCreateDirectory( aURL ); + ::osl::FileBase::RC aResult = ::osl::File::copy( *aI, sTargetName ); + if ( aResult != ::osl::FileBase::E_None ) + { + ::rtl::OString aMsg( "AutocorrectionMigration::copyFiles: cannot copy " ); + aMsg += ::rtl::OUStringToOString( *aI, RTL_TEXTENCODING_UTF8 ) + " to " + + ::rtl::OUStringToOString( sTargetName, RTL_TEXTENCODING_UTF8 ); + OSL_ENSURE( sal_False, aMsg.getStr() ); + } + ++aI; + } + } + else + { + OSL_ENSURE( sal_False, "AutocorrectionMigration::copyFiles: no user installation!" ); + } + } + + // ----------------------------------------------------------------------------- + // XServiceInfo + // ----------------------------------------------------------------------------- + + ::rtl::OUString AutocorrectionMigration::getImplementationName() throw (RuntimeException) + { + return AutocorrectionMigration_getImplementationName(); + } + + // ----------------------------------------------------------------------------- + + sal_Bool AutocorrectionMigration::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() ); + const ::rtl::OUString* pNames = aNames.getConstArray(); + const ::rtl::OUString* pEnd = pNames + aNames.getLength(); + for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames ) + ; + + return pNames != pEnd; + } + + // ----------------------------------------------------------------------------- + + Sequence< ::rtl::OUString > AutocorrectionMigration::getSupportedServiceNames() throw (RuntimeException) + { + return AutocorrectionMigration_getSupportedServiceNames(); + } + + // ----------------------------------------------------------------------------- + // XInitialization + // ----------------------------------------------------------------------------- + + void AutocorrectionMigration::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + const Any* pIter = aArguments.getConstArray(); + const Any* pEnd = pIter + aArguments.getLength(); + for ( ; pIter != pEnd ; ++pIter ) + { + beans::NamedValue aValue; + *pIter >>= aValue; + if ( aValue.Name.equalsAscii( "UserData" ) ) + { + if ( !(aValue.Value >>= m_sSourceDir) ) + { + OSL_ENSURE( false, "AutocorrectionMigration::initialize: argument UserData has wrong type!" ); + } + m_sSourceDir += sSourceSubDir; + break; + } + } + } + + // ----------------------------------------------------------------------------- + // XJob + // ----------------------------------------------------------------------------- + + Any AutocorrectionMigration::execute( const Sequence< beans::NamedValue >& ) + throw (lang::IllegalArgumentException, Exception, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + copyFiles(); + + return Any(); + } + + // ============================================================================= + // component operations + // ============================================================================= + + Reference< XInterface > SAL_CALL AutocorrectionMigration_create( + Reference< XComponentContext > const & ) + SAL_THROW( () ) + { + return static_cast< lang::XTypeProvider * >( new AutocorrectionMigration() ); + } + + // ----------------------------------------------------------------------------- + +//......................................................................... +} // namespace migration +//......................................................................... + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/autocorrmigration.hxx b/desktop/source/migration/services/autocorrmigration.hxx new file mode 100644 index 000000000000..9a8aef32cdda --- /dev/null +++ b/desktop/source/migration/services/autocorrmigration.hxx @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_AUTOCORRMIGRATION_HXX_ +#define _DESKTOP_AUTOCORRMIGRATION_HXX_ + +#include "misc.hxx" +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/task/XJob.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/implbase3.hxx> +#include <osl/mutex.hxx> +#include <osl/file.hxx> + + +class INetURLObject; + + +//......................................................................... +namespace migration +{ +//......................................................................... + + ::rtl::OUString SAL_CALL AutocorrectionMigration_getImplementationName(); + ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL AutocorrectionMigration_getSupportedServiceNames(); + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL AutocorrectionMigration_create( + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & xContext ) + SAL_THROW( (::com::sun::star::uno::Exception) ); + + + // ============================================================================= + // class AutocorrectionMigration + // ============================================================================= + + typedef ::cppu::WeakImplHelper3< + ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::lang::XInitialization, + ::com::sun::star::task::XJob > AutocorrectionMigration_BASE; + + class AutocorrectionMigration : public AutocorrectionMigration_BASE + { + private: + ::osl::Mutex m_aMutex; + ::rtl::OUString m_sSourceDir; + + TStringVectorPtr getFiles( const ::rtl::OUString& rBaseURL ) const; + ::osl::FileBase::RC checkAndCreateDirectory( INetURLObject& rDirURL ); + void copyFiles(); + + public: + AutocorrectionMigration(); + virtual ~AutocorrectionMigration(); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& rServiceName ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() + throw (::com::sun::star::uno::RuntimeException); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XJob + virtual ::com::sun::star::uno::Any SAL_CALL execute( + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& Arguments ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException); + }; + +//......................................................................... +} // namespace migration +//......................................................................... + +#endif // _DESKTOP_AUTOCORRMIGRATION_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/basicmigration.cxx b/desktop/source/migration/services/basicmigration.cxx new file mode 100644 index 000000000000..4ed093cfe446 --- /dev/null +++ b/desktop/source/migration/services/basicmigration.cxx @@ -0,0 +1,277 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "basicmigration.hxx" +#include <tools/urlobj.hxx> +#include <unotools/bootstrap.hxx> + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + + +//......................................................................... +namespace migration +{ +//......................................................................... + + + static ::rtl::OUString sSourceUserBasic = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/basic" ) ); + static ::rtl::OUString sTargetUserBasic = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/__basic_80" ) ); + + + // ============================================================================= + // component operations + // ============================================================================= + + ::rtl::OUString BasicMigration_getImplementationName() + { + static ::rtl::OUString* pImplName = 0; + if ( !pImplName ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !pImplName ) + { + static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.desktop.migration.Basic" ) ); + pImplName = &aImplName; + } + } + return *pImplName; + } + + // ----------------------------------------------------------------------------- + + Sequence< ::rtl::OUString > BasicMigration_getSupportedServiceNames() + { + static Sequence< ::rtl::OUString >* pNames = 0; + if ( !pNames ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !pNames ) + { + static Sequence< ::rtl::OUString > aNames(1); + aNames.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.migration.Basic" ) ); + pNames = &aNames; + } + } + return *pNames; + } + + // ============================================================================= + // BasicMigration + // ============================================================================= + + BasicMigration::BasicMigration() + { + } + + // ----------------------------------------------------------------------------- + + BasicMigration::~BasicMigration() + { + } + + // ----------------------------------------------------------------------------- + + TStringVectorPtr BasicMigration::getFiles( const ::rtl::OUString& rBaseURL ) const + { + TStringVectorPtr aResult( new TStringVector ); + ::osl::Directory aDir( rBaseURL); + + if ( aDir.open() == ::osl::FileBase::E_None ) + { + // iterate over directory content + TStringVector aSubDirs; + ::osl::DirectoryItem aItem; + while ( aDir.getNextItem( aItem ) == ::osl::FileBase::E_None ) + { + ::osl::FileStatus aFileStatus( FileStatusMask_Type | FileStatusMask_FileURL ); + if ( aItem.getFileStatus( aFileStatus ) == ::osl::FileBase::E_None ) + { + if ( aFileStatus.getFileType() == ::osl::FileStatus::Directory ) + aSubDirs.push_back( aFileStatus.getFileURL() ); + else + aResult->push_back( aFileStatus.getFileURL() ); + } + } + + // iterate recursive over subfolders + TStringVector::const_iterator aI = aSubDirs.begin(); + while ( aI != aSubDirs.end() ) + { + TStringVectorPtr aSubResult = getFiles( *aI ); + aResult->insert( aResult->end(), aSubResult->begin(), aSubResult->end() ); + ++aI; + } + } + + return aResult; + } + + // ----------------------------------------------------------------------------- + + ::osl::FileBase::RC BasicMigration::checkAndCreateDirectory( INetURLObject& rDirURL ) + { + ::osl::FileBase::RC aResult = ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) ); + if ( aResult == ::osl::FileBase::E_NOENT ) + { + INetURLObject aBaseURL( rDirURL ); + aBaseURL.removeSegment(); + checkAndCreateDirectory( aBaseURL ); + return ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) ); + } + else + { + return aResult; + } + } + + // ----------------------------------------------------------------------------- + + void BasicMigration::copyFiles() + { + ::rtl::OUString sTargetDir; + ::utl::Bootstrap::PathStatus aStatus = ::utl::Bootstrap::locateUserInstallation( sTargetDir ); + if ( aStatus == ::utl::Bootstrap::PATH_EXISTS ) + { + sTargetDir += sTargetUserBasic; + TStringVectorPtr aFileList = getFiles( m_sSourceDir ); + TStringVector::const_iterator aI = aFileList->begin(); + while ( aI != aFileList->end() ) + { + ::rtl::OUString sLocalName = aI->copy( m_sSourceDir.getLength() ); + ::rtl::OUString sTargetName = sTargetDir + sLocalName; + INetURLObject aURL( sTargetName ); + aURL.removeSegment(); + checkAndCreateDirectory( aURL ); + ::osl::FileBase::RC aResult = ::osl::File::copy( *aI, sTargetName ); + if ( aResult != ::osl::FileBase::E_None ) + { + ::rtl::OString aMsg( "BasicMigration::copyFiles: cannot copy " ); + aMsg += ::rtl::OUStringToOString( *aI, RTL_TEXTENCODING_UTF8 ) + " to " + + ::rtl::OUStringToOString( sTargetName, RTL_TEXTENCODING_UTF8 ); + OSL_ENSURE( sal_False, aMsg.getStr() ); + } + ++aI; + } + } + else + { + OSL_ENSURE( sal_False, "BasicMigration::copyFiles: no user installation!" ); + } + } + + // ----------------------------------------------------------------------------- + // XServiceInfo + // ----------------------------------------------------------------------------- + + ::rtl::OUString BasicMigration::getImplementationName() throw (RuntimeException) + { + return BasicMigration_getImplementationName(); + } + + // ----------------------------------------------------------------------------- + + sal_Bool BasicMigration::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() ); + const ::rtl::OUString* pNames = aNames.getConstArray(); + const ::rtl::OUString* pEnd = pNames + aNames.getLength(); + for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames ) + ; + + return pNames != pEnd; + } + + // ----------------------------------------------------------------------------- + + Sequence< ::rtl::OUString > BasicMigration::getSupportedServiceNames() throw (RuntimeException) + { + return BasicMigration_getSupportedServiceNames(); + } + + // ----------------------------------------------------------------------------- + // XInitialization + // ----------------------------------------------------------------------------- + + void BasicMigration::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + const Any* pIter = aArguments.getConstArray(); + const Any* pEnd = pIter + aArguments.getLength(); + for ( ; pIter != pEnd ; ++pIter ) + { + beans::NamedValue aValue; + *pIter >>= aValue; + if ( aValue.Name.equalsAscii( "UserData" ) ) + { + if ( !(aValue.Value >>= m_sSourceDir) ) + { + OSL_ENSURE( false, "BasicMigration::initialize: argument UserData has wrong type!" ); + } + m_sSourceDir += sSourceUserBasic; + break; + } + } + } + + // ----------------------------------------------------------------------------- + // XJob + // ----------------------------------------------------------------------------- + + Any BasicMigration::execute( const Sequence< beans::NamedValue >& ) + throw (lang::IllegalArgumentException, Exception, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + copyFiles(); + + return Any(); + } + + // ============================================================================= + // component operations + // ============================================================================= + + Reference< XInterface > SAL_CALL BasicMigration_create( + Reference< XComponentContext > const & ) + SAL_THROW( () ) + { + return static_cast< lang::XTypeProvider * >( new BasicMigration() ); + } + + // ----------------------------------------------------------------------------- + +//......................................................................... +} // namespace migration +//......................................................................... + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/basicmigration.hxx b/desktop/source/migration/services/basicmigration.hxx new file mode 100644 index 000000000000..131092748a63 --- /dev/null +++ b/desktop/source/migration/services/basicmigration.hxx @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_BASICMIGRATION_HXX_ +#define _DESKTOP_BASICMIGRATION_HXX_ + +#include "misc.hxx" +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/task/XJob.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/implbase3.hxx> +#include <osl/mutex.hxx> +#include <osl/file.hxx> + + +class INetURLObject; + + +//......................................................................... +namespace migration +{ +//......................................................................... + + ::rtl::OUString SAL_CALL BasicMigration_getImplementationName(); + ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL BasicMigration_getSupportedServiceNames(); + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL BasicMigration_create( + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & xContext ) + SAL_THROW( (::com::sun::star::uno::Exception) ); + + + // ============================================================================= + // class BasicMigration + // ============================================================================= + + typedef ::cppu::WeakImplHelper3< + ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::lang::XInitialization, + ::com::sun::star::task::XJob > BasicMigration_BASE; + + class BasicMigration : public BasicMigration_BASE + { + private: + ::osl::Mutex m_aMutex; + ::rtl::OUString m_sSourceDir; + + TStringVectorPtr getFiles( const ::rtl::OUString& rBaseURL ) const; + ::osl::FileBase::RC checkAndCreateDirectory( INetURLObject& rDirURL ); + void copyFiles(); + + public: + BasicMigration(); + virtual ~BasicMigration(); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& rServiceName ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() + throw (::com::sun::star::uno::RuntimeException); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XJob + virtual ::com::sun::star::uno::Any SAL_CALL execute( + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& Arguments ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException); + }; + +//......................................................................... +} // namespace migration +//......................................................................... + +#endif // _DESKTOP_BASICMIGRATION_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/cexports.cxx b/desktop/source/migration/services/cexports.cxx new file mode 100644 index 000000000000..261cf266653c --- /dev/null +++ b/desktop/source/migration/services/cexports.cxx @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "cppuhelper/implementationentry.hxx" +#include "basicmigration.hxx" +#include "wordbookmigration.hxx" + + +extern "C" +{ + +::cppu::ImplementationEntry entries [] = +{ + { + migration::BasicMigration_create, migration::BasicMigration_getImplementationName, + migration::BasicMigration_getSupportedServiceNames, ::cppu::createSingleComponentFactory, + 0, 0 + }, + { + migration::WordbookMigration_create, migration::WordbookMigration_getImplementationName, + migration::WordbookMigration_getSupportedServiceNames, ::cppu::createSingleComponentFactory, + 0, 0 + }, + // Extension migration was disabled by Oracle / OpenOffice.org +#if 0 + { + migration::ExtensionMigration_create, migration::ExtensionMigration_getImplementationName, + migration::ExtensionMigration_getSupportedServiceNames, ::cppu::createSingleComponentFactory, + 0, 0 + }, +#endif + { 0, 0, 0, 0, 0, 0 } +}; + + +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +sal_Bool SAL_CALL component_writeInfo( + void * pServiceManager, void * pRegistryKey ) +{ + return ::cppu::component_writeInfoHelper( + pServiceManager, pRegistryKey, entries ); +} + +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) +{ + return ::cppu::component_getFactoryHelper( + pImplName, pServiceManager, pRegistryKey, entries ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/cexportsoo3.cxx b/desktop/source/migration/services/cexportsoo3.cxx new file mode 100644 index 000000000000..771c161879e0 --- /dev/null +++ b/desktop/source/migration/services/cexportsoo3.cxx @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "cppuhelper/implementationentry.hxx" +#include "oo3extensionmigration.hxx" + +extern "C" +{ + +::cppu::ImplementationEntry entries [] = +{ + { + migration::OO3ExtensionMigration_create, migration::OO3ExtensionMigration_getImplementationName, + migration::OO3ExtensionMigration_getSupportedServiceNames, ::cppu::createSingleComponentFactory, + 0, 0 + }, + { 0, 0, 0, 0, 0, 0 } +}; + + +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +sal_Bool SAL_CALL component_writeInfo( + void * pServiceManager, void * pRegistryKey ) +{ + return ::cppu::component_writeInfoHelper( + pServiceManager, pRegistryKey, entries ); +} + +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) +{ + return ::cppu::component_getFactoryHelper( + pImplName, pServiceManager, pRegistryKey, entries ); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/cppumaker.mk b/desktop/source/migration/services/cppumaker.mk new file mode 100644 index 000000000000..5ab16ed1e3fe --- /dev/null +++ b/desktop/source/migration/services/cppumaker.mk @@ -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. +# +#************************************************************************* + +.IF "$(debug)" != "" + +# MSVC++: no inlining +.IF "$(COM)" == "MSC" +CFLAGS += -Ob0 +.ENDIF + +.ENDIF + diff --git a/desktop/source/migration/services/jvmfwk.cxx b/desktop/source/migration/services/jvmfwk.cxx new file mode 100644 index 000000000000..f6ad3f54bcac --- /dev/null +++ b/desktop/source/migration/services/jvmfwk.cxx @@ -0,0 +1,531 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "cppuhelper/implbase4.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "rtl/bootstrap.hxx" +#include "sal/types.h" +#include "sal/config.h" +#include "boost/scoped_array.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XInitialization.hpp" +#include "com/sun/star/lang/WrappedTargetException.hpp" +#include "com/sun/star/task/XJob.hpp" +#include "com/sun/star/configuration/backend/XLayer.hpp" +#include "com/sun/star/configuration/backend/XLayerHandler.hpp" +#include "com/sun/star/configuration/backend/MalformedDataException.hpp" +#include "com/sun/star/configuration/backend/TemplateIdentifier.hpp" +#include "jvmfwk/framework.h" +#include "jvmfwk.hxx" +#include <stack> +#include <stdio.h> + +#include "osl/thread.hxx" +#define OUSTR(x) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( x )) + +#define SERVICE_NAME "com.sun.star.migration.Java" +#define IMPL_NAME "com.sun.star.comp.desktop.migration.Java" + +#define ENABLE_JAVA 1 +#define USER_CLASS_PATH 2 + +namespace css = com::sun::star; +using namespace rtl; +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::configuration::backend; + +namespace migration +{ + +class CJavaInfo +{ + CJavaInfo(const CJavaInfo&); + CJavaInfo& operator = (const CJavaInfo&); +public: + JavaInfo* pData; + CJavaInfo(); + ~CJavaInfo(); + operator JavaInfo* (); +}; + +CJavaInfo::CJavaInfo(): pData(NULL) +{ +} + +CJavaInfo::~CJavaInfo() +{ + jfw_freeJavaInfo(pData); +} + +CJavaInfo::operator JavaInfo*() +{ + return pData; +} + + +class JavaMigration : public ::cppu::WeakImplHelper4< + css::lang::XServiceInfo, + css::lang::XInitialization, + css::task::XJob, + css::configuration::backend::XLayerHandler> +{ +public: + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) + throw (css::uno::RuntimeException); + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() + throw (css::uno::RuntimeException); + + //XInitialization + virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) + throw(css::uno::Exception, css::uno::RuntimeException); + + //XJob + virtual css::uno::Any SAL_CALL execute( + const css::uno::Sequence<css::beans::NamedValue >& Arguments ) + throw (css::lang::IllegalArgumentException, css::uno::Exception, + css::uno::RuntimeException); + + // XLayerHandler + virtual void SAL_CALL startLayer() + throw(::com::sun::star::lang::WrappedTargetException); + + virtual void SAL_CALL endLayer() + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL overrideNode( + const rtl::OUString& aName, + sal_Int16 aAttributes, + sal_Bool bClear) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL addOrReplaceNode( + const rtl::OUString& aName, + sal_Int16 aAttributes) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL addOrReplaceNodeFromTemplate( + const rtl::OUString& aName, + const ::com::sun::star::configuration::backend::TemplateIdentifier& aTemplate, + sal_Int16 aAttributes ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL endNode() + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL dropNode( + const rtl::OUString& aName ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL overrideProperty( + const rtl::OUString& aName, + sal_Int16 aAttributes, + const css::uno::Type& aType, + sal_Bool bClear ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL setPropertyValue( + const css::uno::Any& aValue ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL setPropertyValueForLocale( + const css::uno::Any& aValue, + const rtl::OUString& aLocale ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL endProperty() + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL addProperty( + const rtl::OUString& aName, + sal_Int16 aAttributes, + const css::uno::Type& aType ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + virtual void SAL_CALL addPropertyWithValue( + const rtl::OUString& aName, + sal_Int16 aAttributes, + const css::uno::Any& aValue ) + throw( + ::com::sun::star::configuration::backend::MalformedDataException, + ::com::sun::star::lang::WrappedTargetException ); + + + + //---------------- + ~JavaMigration(); + +private: + OUString m_sUserDir; + css::uno::Reference< ::css::configuration::backend::XLayer> m_xLayer; + + void migrateJavarc(); + typedef ::std::pair< ::rtl::OUString, sal_Int16> TElementType; + typedef ::std::stack< TElementType > TElementStack; + TElementStack m_aStack; + +}; + +JavaMigration::~JavaMigration() +{ + OSL_ASSERT(m_aStack.empty()); +} + +OUString jvmfwk_getImplementationName() +{ + return OUSTR(IMPL_NAME); +} + +css::uno::Sequence< OUString > jvmfwk_getSupportedServiceNames() +{ + OUString str_name = OUSTR(SERVICE_NAME); + return css::uno::Sequence< OUString >( &str_name, 1 ); +} + +// XServiceInfo +OUString SAL_CALL JavaMigration::getImplementationName() + throw (css::uno::RuntimeException) +{ + return jvmfwk_getImplementationName(); +} + +sal_Bool SAL_CALL JavaMigration::supportsService( const OUString & rServiceName ) + throw (css::uno::RuntimeException) +{ + css::uno::Sequence< OUString > const & rSNL = getSupportedServiceNames(); + OUString const * pArray = rSNL.getConstArray(); + for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) + { + if (rServiceName.equals( pArray[ nPos ] )) + return true; + } + return false; + +} + +css::uno::Sequence< OUString > SAL_CALL JavaMigration::getSupportedServiceNames() + throw (css::uno::RuntimeException) +{ + return jvmfwk_getSupportedServiceNames(); +} + +//XInitialization ---------------------------------------------------------------------- +void SAL_CALL JavaMigration::initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) + throw(css::uno::Exception, css::uno::RuntimeException) +{ + const css::uno::Any* pIter = aArguments.getConstArray(); + const css::uno::Any* pEnd = pIter + aArguments.getLength(); + css::uno::Sequence<css::beans::NamedValue> aOldConfigValues; + css::beans::NamedValue aValue; + for(;pIter != pEnd;++pIter) + { + *pIter >>= aValue; + if (aValue.Name.equalsAscii("OldConfiguration")) + { + sal_Bool bSuccess = aValue.Value >>= aOldConfigValues; + OSL_ENSURE(bSuccess == sal_True, "[Service implementation " IMPL_NAME + "] XInitialization::initialize: Argument OldConfiguration has wrong type."); + if (bSuccess) + { + const css::beans::NamedValue* pIter2 = aOldConfigValues.getConstArray(); + const css::beans::NamedValue* pEnd2 = pIter2 + aOldConfigValues.getLength(); + for(;pIter2 != pEnd2;++pIter2) + { + if ( pIter2->Name.equalsAscii("org.openoffice.Office.Java") ) + { + pIter2->Value >>= m_xLayer; + break; + } + } + } + } + else if (aValue.Name.equalsAscii("UserData")) + { + if ( !(aValue.Value >>= m_sUserDir) ) + { + OSL_ENSURE( + false, + "[Service implementation " IMPL_NAME + "] XInitialization::initialize: Argument UserData has wrong type."); + } + } + } + +} + +//XJob +css::uno::Any SAL_CALL JavaMigration::execute( + const css::uno::Sequence<css::beans::NamedValue >& ) + throw (css::lang::IllegalArgumentException, css::uno::Exception, + css::uno::RuntimeException) +{ + migrateJavarc(); + if (m_xLayer.is()) + m_xLayer->readData(this); + + return css::uno::Any(); +} + +void JavaMigration::migrateJavarc() +{ + if (m_sUserDir.getLength() == 0) + return; + + OUString sValue; + rtl::Bootstrap javaini(m_sUserDir + OUSTR("/user/config/"SAL_CONFIGFILE("java"))); + sal_Bool bSuccess = javaini.getFrom(OUSTR("Home"), sValue); + OSL_ENSURE(bSuccess, "[Service implementation " IMPL_NAME + "] XJob::execute: Could not get Home entry from java.ini/javarc."); + if (bSuccess == sal_True && sValue.getLength() > 0) + { + //get the directory + CJavaInfo aInfo; + javaFrameworkError err = jfw_getJavaInfoByPath(sValue.pData, &aInfo.pData); + + if (err == JFW_E_NONE) + { + if (jfw_setSelectedJRE(aInfo) != JFW_E_NONE) + { + OSL_ENSURE(0, "[Service implementation " IMPL_NAME + "] XJob::execute: jfw_setSelectedJRE failed."); + fprintf(stderr, "\nCannot migrate Java. An error occured.\n"); + } + } + else if (err == JFW_E_FAILED_VERSION) + { + fprintf(stderr, "\nCannot migrate Java settings because the version of the Java " + "is not supported anymore.\n"); + } + } +} + + +// XLayerHandler +void SAL_CALL JavaMigration::startLayer() + throw(css::lang::WrappedTargetException) +{ +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::endLayer() + throw( + MalformedDataException, + WrappedTargetException ) +{ +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::overrideNode( + const ::rtl::OUString&, + sal_Int16, + sal_Bool) + throw( + MalformedDataException, + WrappedTargetException ) + +{ + +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::addOrReplaceNode( + const ::rtl::OUString&, + sal_Int16) + throw( + MalformedDataException, + WrappedTargetException ) +{ + +} +void SAL_CALL JavaMigration::endNode() + throw( + MalformedDataException, + WrappedTargetException ) +{ +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::dropNode( + const ::rtl::OUString& ) + throw( + MalformedDataException, + WrappedTargetException ) +{ +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::overrideProperty( + const ::rtl::OUString& aName, + sal_Int16, + const Type&, + sal_Bool ) + throw( + MalformedDataException, + WrappedTargetException ) +{ + if (aName.equalsAscii("Enable")) + m_aStack.push(TElementStack::value_type(aName,ENABLE_JAVA)); + else if (aName.equalsAscii("UserClassPath")) + m_aStack.push(TElementStack::value_type(aName, USER_CLASS_PATH)); +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::setPropertyValue( + const Any& aValue ) + throw( + MalformedDataException, + WrappedTargetException ) +{ + if ( !m_aStack.empty()) + { + switch (m_aStack.top().second) + { + case ENABLE_JAVA: + { + sal_Bool val = sal_Bool(); + if ((aValue >>= val) == sal_False) + throw MalformedDataException( + OUSTR("[Service implementation " IMPL_NAME + "] XLayerHandler::setPropertyValue received wrong type for Enable property"), 0, Any()); + if (jfw_setEnabled(val) != JFW_E_NONE) + throw WrappedTargetException( + OUSTR("[Service implementation " IMPL_NAME + "] XLayerHandler::setPropertyValue: jfw_setEnabled failed."), 0, Any()); + + break; + } + case USER_CLASS_PATH: + { + OUString cp; + if ((aValue >>= cp) == sal_False) + throw MalformedDataException( + OUSTR("[Service implementation " IMPL_NAME + "] XLayerHandler::setPropertyValue received wrong type for UserClassPath property"), 0, Any()); + + if (jfw_setUserClassPath(cp.pData) != JFW_E_NONE) + throw WrappedTargetException( + OUSTR("[Service implementation " IMPL_NAME + "] XLayerHandler::setPropertyValue: jfw_setUserClassPath failed."), 0, Any()); + break; + } + default: + OSL_ASSERT(0); + } + } +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::setPropertyValueForLocale( + const Any&, + const ::rtl::OUString& ) + throw( + MalformedDataException, + WrappedTargetException ) +{ +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::endProperty() + throw( + MalformedDataException, + WrappedTargetException ) +{ + if (!m_aStack.empty()) + m_aStack.pop(); +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::addProperty( + const rtl::OUString&, + sal_Int16, + const Type& ) + throw( + MalformedDataException, + WrappedTargetException ) +{ +} +// ----------------------------------------------------------------------------- + +void SAL_CALL JavaMigration::addPropertyWithValue( + const rtl::OUString&, + sal_Int16, + const Any& ) + throw( + MalformedDataException, + WrappedTargetException ) +{ +} + +void SAL_CALL JavaMigration::addOrReplaceNodeFromTemplate( + const rtl::OUString&, + const TemplateIdentifier&, + sal_Int16 ) + throw( + MalformedDataException, + WrappedTargetException ) +{ +} + +// ----------------------------------------------------------------------------- +//ToDo enable java, user class path + +} //end namespace jfw + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/jvmfwk.hxx b/desktop/source/migration/services/jvmfwk.hxx new file mode 100644 index 000000000000..96e459521d93 --- /dev/null +++ b/desktop/source/migration/services/jvmfwk.hxx @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "cppuhelper/implbase3.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "boost/scoped_array.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XInitialization.hpp" +#include "com/sun/star/task/XJob.hpp" + + +namespace css = com::sun::star; + +namespace migration +{ + +rtl::OUString jvmfwk_getImplementationName(); + +css::uno::Sequence< rtl::OUString > jvmfwk_getSupportedServiceNames(); + +} //end blind namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/makefile.mk b/desktop/source/migration/services/makefile.mk new file mode 100644 index 000000000000..2f3eb9308ebd --- /dev/null +++ b/desktop/source/migration/services/makefile.mk @@ -0,0 +1,119 @@ +#************************************************************************* +# +# 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 = migrationoo2.uno +ENABLE_EXCEPTIONS=TRUE +COMP1TYPELIST = migrationoo2 +LIBTARGET=NO + +# --- Settings ----------------------------------------------------- +.INCLUDE : ..$/..$/deployment/inc/dp_misc.mk +.INCLUDE : settings.mk +DLLPRE = + +# ------------------------------------------------------------------ + +.INCLUDE : cppumaker.mk + +.IF "$(SYSTEM_DB)" == "YES" +CFLAGS+=-DSYSTEM_DB -I$(DB_INCLUDES) +.ENDIF + +SLOFILES= \ + $(SLO)$/jvmfwk.obj \ + $(SLO)$/cexports.obj \ + $(SLO)$/basicmigration.obj \ + $(SLO)$/wordbookmigration.obj \ + $(SLO)$/autocorrmigration.obj \ + $(SLO)$/oo3extensionmigration.obj \ + $(SLO)$/cexportsoo3.obj + +SHL1OBJS= \ + $(SLO)$/jvmfwk.obj \ + $(SLO)$/cexports.obj \ + $(SLO)$/basicmigration.obj \ + $(SLO)$/wordbookmigration.obj \ + $(SLO)$/autocorrmigration.obj + +SHL1TARGET=$(TARGET) +SHL1VERSIONMAP = $(SOLARENV)/src/component.map + +SHL1STDLIBS= \ + $(DEPLOYMENTMISCLIB) \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) \ + $(UCBHELPERLIB) \ + $(UNOTOOLSLIB) \ + $(TOOLSLIB) \ + $(I18NISOLANGLIB) \ + $(JVMFWKLIB) \ + $(XMLSCRIPTLIB) \ + $(BERKELEYLIB) + +SHL1DEPN= +SHL1IMPLIB=imigrationoo2 +#SHL1LIBS=$(SLB)$/$(TARGET).lib +SHL1DEF=$(MISC)$/$(SHL1TARGET).def + +DEF1NAME=$(SHL1TARGET) + +COMP2TYPELIST = migrationoo3 +SHL2TARGET=migrationoo3.uno +SHL2VERSIONMAP = migrationoo3.map + +SHL2OBJS= \ + $(SLO)$/cexportsoo3.obj \ + $(SLO)$/oo3extensionmigration.obj + +SHL2STDLIBS= \ + $(DEPLOYMENTMISCLIB) \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) \ + $(UCBHELPERLIB) \ + $(UNOTOOLSLIB) \ + $(TOOLSLIB) \ + $(I18NISOLANGLIB) \ + $(JVMFWKLIB) \ + $(XMLSCRIPTLIB) \ + $(BERKELEYLIB) + +SHL2DEPN= +SHL2IMPLIB=imigrationoo3 +#SHL2LIBS=$(SLB)$/$(SHL2TARGET).lib +SHL2DEF=$(MISC)$/$(SHL2TARGET).def + +DEF2NAME=$(SHL2TARGET) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/desktop/source/migration/services/migrationoo2.xml b/desktop/source/migration/services/migrationoo2.xml new file mode 100644 index 000000000000..0c77badebcd3 --- /dev/null +++ b/desktop/source/migration/services/migrationoo2.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + <module-name> migrationoo2.uno </module-name> + <component-description> + <author> Joachim Lingner </author> + <name> com.sun.star.comp.jvmfwk.MigrationOO2</name> + <description> +Specifies a factory object to create proxy objects. +These proxy object represent a given target object and can be +be aggregated. The proxy objects act UNO conform and do NOT provide +original target interfaces on queryInterface() calls. +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> C++ </language> + <status value="final"/> + <supported-service> com.sun.star.reflection.ProxyFactory </supported-service> + <service-dependency> ... </service-dependency> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XInitialization </type> + <type> com.sun.star.lang.WrappedTargetException </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.lang.XSingleComponentFactory </type> + <type> com.sun.star.task.XJob </type> + <type> com.sun.star.beans.NamedValue </type> + <type> com.sun.star.configuration.backend.XLayer </type> + <type> com.sun.star.configuration.backend.XLayerHandler </type> + <type> com.sun.star.configuration.backend.MalformedDataException </type> + <type> com.sun.star.configuration.backend.TemplateIdentifier </type> + </component-description> + <component-description> + <author>Thomas Benisch</author> + <name>com.sun.star.comp.desktop.migration.Basic</name> + <description>migration service for OpenOffice.org Basic and dialogs</description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.migration.Basic</supported-service> + <service-dependency>...</service-dependency> + <type>com.sun.star.beans.NamedValue</type> + <type>com.sun.star.lang.IllegalArgumentException</type> + <type>com.sun.star.lang.XInitialization</type> + <type>com.sun.star.task.XJob</type> + <type>com.sun.star.lang.XServiceInfo</type> + <type>com.sun.star.lang.XTypeProvider</type> + <type>com.sun.star.uno.XComponentContext</type> + </component-description> + <component-description> + <author>Thomas Benisch</author> + <name>com.sun.star.comp.desktop.migration.Autocorrection</name> + <description>migration service for OpenOffice.org autocorrection</description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>c++</language> + <status value="final"/> + <supported-service>com.sun.star.migration.Autocorrection</supported-service> + <service-dependency>...</service-dependency> + <type>com.sun.star.beans.NamedValue</type> + <type>com.sun.star.lang.IllegalArgumentException</type> + <type>com.sun.star.lang.XInitialization</type> + <type>com.sun.star.task.XJob</type> + <type>com.sun.star.lang.XServiceInfo</type> + <type>com.sun.star.lang.XTypeProvider</type> + <type>com.sun.star.uno.XComponentContext</type> + </component-description> + <project-build-dependency>unotools</project-build-dependency> + <project-build-dependency>tools</project-build-dependency> + <project-build-dependency>cppuhelper</project-build-dependency> + <project-build-dependency>cppu</project-build-dependency> + <project-build-dependency>sal</project-build-dependency> + <runtime-module-dependency>utl</runtime-module-dependency> + <runtime-module-dependency>tl</runtime-module-dependency> + <runtime-module-dependency>cppuhelper3$(COM)</runtime-module-dependency> + <runtime-module-dependency>cppu3</runtime-module-dependency> + <runtime-module-dependency>sal3</runtime-module-dependency> +</module-description> diff --git a/desktop/source/migration/services/migrationoo3.map b/desktop/source/migration/services/migrationoo3.map new file mode 100644 index 000000000000..ac2c3750bfe0 --- /dev/null +++ b/desktop/source/migration/services/migrationoo3.map @@ -0,0 +1,8 @@ +UDK_3_0_0 { + global: + component_getImplementationEnvironment; + component_writeInfo; + component_getFactory; + local: + *; +}; diff --git a/desktop/source/migration/services/misc.hxx b/desktop/source/migration/services/misc.hxx new file mode 100644 index 000000000000..a8f7babef982 --- /dev/null +++ b/desktop/source/migration/services/misc.hxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_MISC_HXX_ +#define _DESKTOP_MISC_HXX_ + +#include <rtl/ustring.hxx> + +#include <vector> +#include <memory> + +//......................................................................... +namespace migration +{ +//......................................................................... + + typedef ::std::vector< ::rtl::OUString > TStringVector; + typedef ::std::auto_ptr< TStringVector > TStringVectorPtr; + +//......................................................................... +} // namespace migration +//......................................................................... + +#endif // _DESKTOP_MISC_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/oo3extensionmigration.cxx b/desktop/source/migration/services/oo3extensionmigration.cxx new file mode 100644 index 000000000000..e62cd1e2e2e2 --- /dev/null +++ b/desktop/source/migration/services/oo3extensionmigration.cxx @@ -0,0 +1,586 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "oo3extensionmigration.hxx" +#include <rtl/instance.hxx> +#include <osl/file.hxx> +#include <osl/thread.h> +#include <tools/urlobj.hxx> +#include <unotools/bootstrap.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <unotools/textsearch.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/processfactory.hxx> +#include <ucbhelper/content.hxx> + +#include <com/sun/star/task/XInteractionApprove.hpp> +#include <com/sun/star/task/XInteractionAbort.hpp> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/ucb/TransferInfo.hpp> +#include <com/sun/star/ucb/NameClash.hpp> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#include <com/sun/star/xml/xpath/XXPathAPI.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/deployment/ExtensionManager.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace migration +{ + +static ::rtl::OUString sExtensionSubDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/uno_packages/" ) ); +static ::rtl::OUString sSubDirName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cache" ) ); +static ::rtl::OUString sConfigDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/registry/data" ) ); +static ::rtl::OUString sOrgDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/registry/data/org" ) ); +static ::rtl::OUString sExcludeDir1 = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/registry/data/org" ) ); +static ::rtl::OUString sExcludeDir2 = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/registry/data/org/openoffice" ) ); +static ::rtl::OUString sDescriptionXmlFile = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/description.xml" ) ); +static ::rtl::OUString sExtensionRootSubDirName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/uno_packages" ) ); + +static ::rtl::OUString sConfigurationDataType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("application/vnd.sun.star.configuration-data")); +static ::rtl::OUString sConfigurationSchemaType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("application/vnd.sun.star.configuration-schema")); + +// ============================================================================= +// component operations +// ============================================================================= + +::rtl::OUString OO3ExtensionMigration_getImplementationName() +{ + static ::rtl::OUString* pImplName = 0; + if ( !pImplName ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !pImplName ) + { + static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.desktop.migration.OOo3Extensions" ) ); + pImplName = &aImplName; + } + } + return *pImplName; +} + +// ----------------------------------------------------------------------------- + +Sequence< ::rtl::OUString > OO3ExtensionMigration_getSupportedServiceNames() +{ + static Sequence< ::rtl::OUString >* pNames = 0; + if ( !pNames ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !pNames ) + { + static Sequence< ::rtl::OUString > aNames(1); + aNames.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.migration.Extensions" ) ); + pNames = &aNames; + } + } + return *pNames; +} + +// ============================================================================= +// ExtensionMigration +// ============================================================================= + +OO3ExtensionMigration::OO3ExtensionMigration(Reference< XComponentContext > const & ctx) : +m_ctx(ctx) +{ +} + +// ----------------------------------------------------------------------------- + +OO3ExtensionMigration::~OO3ExtensionMigration() +{ +} + +::osl::FileBase::RC OO3ExtensionMigration::checkAndCreateDirectory( INetURLObject& rDirURL ) +{ + ::osl::FileBase::RC aResult = ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) ); + if ( aResult == ::osl::FileBase::E_NOENT ) + { + INetURLObject aBaseURL( rDirURL ); + aBaseURL.removeSegment(); + checkAndCreateDirectory( aBaseURL ); + return ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) ); + } + else + { + return aResult; + } +} + +void OO3ExtensionMigration::scanUserExtensions( const ::rtl::OUString& sSourceDir, TStringVector& aMigrateExtensions ) +{ + osl::Directory aScanRootDir( sSourceDir ); + osl::FileStatus fs(FileStatusMask_Type | FileStatusMask_FileURL); + osl::FileBase::RC nRetCode = aScanRootDir.open(); + if ( nRetCode == osl::Directory::E_None ) + { + sal_uInt32 nHint( 0 ); + osl::DirectoryItem aItem; + while ( aScanRootDir.getNextItem( aItem, nHint ) == osl::Directory::E_None ) + { + if (( aItem.getFileStatus(fs) == osl::FileBase::E_None ) && + ( fs.getFileType() == osl::FileStatus::Directory )) + { + //Check next folder as the "real" extension folder is below a temp folder! + ::rtl::OUString sExtensionFolderURL = fs.getFileURL(); + + osl::DirectoryItem aExtDirItem; + osl::Directory aExtensionRootDir( sExtensionFolderURL ); + + nRetCode = aExtensionRootDir.open(); + if (( nRetCode == osl::Directory::E_None ) && + ( aExtensionRootDir.getNextItem( aExtDirItem, nHint ) == osl::Directory::E_None )) + { + bool bFileStatus = aExtDirItem.getFileStatus(fs) == osl::FileBase::E_None; + bool bIsDir = fs.getFileType() == osl::FileStatus::Directory; + + if ( bFileStatus && bIsDir ) + { + sExtensionFolderURL = fs.getFileURL(); + ScanResult eResult = scanExtensionFolder( sExtensionFolderURL ); + if ( eResult == SCANRESULT_MIGRATE_EXTENSION ) + aMigrateExtensions.push_back( sExtensionFolderURL ); + } + } + } + } + } +} + +OO3ExtensionMigration::ScanResult OO3ExtensionMigration::scanExtensionFolder( const ::rtl::OUString& sExtFolder ) +{ + ScanResult aResult = SCANRESULT_NOTFOUND; + osl::Directory aDir(sExtFolder); + + // get sub dirs + if (aDir.open() == osl::FileBase::E_None) + { + // work through directory contents... + osl::DirectoryItem item; + osl::FileStatus fs(FileStatusMask_Type | FileStatusMask_FileURL); + TStringVector aDirectories; + while ((aDir.getNextItem(item) == osl::FileBase::E_None ) && + ( aResult == SCANRESULT_NOTFOUND )) + { + if (item.getFileStatus(fs) == osl::FileBase::E_None) + { + ::rtl::OUString aDirEntryURL; + if (fs.getFileType() == osl::FileStatus::Directory) + aDirectories.push_back( fs.getFileURL() ); + else + { + aDirEntryURL = fs.getFileURL(); + if ( aDirEntryURL.indexOf( sDescriptionXmlFile ) > 0 ) + aResult = scanDescriptionXml( aDirEntryURL ) ? SCANRESULT_MIGRATE_EXTENSION : SCANRESULT_DONTMIGRATE_EXTENSION; + } + } + } + + TStringVector::const_iterator pIter = aDirectories.begin(); + while ( pIter != aDirectories.end() && aResult == SCANRESULT_NOTFOUND ) + { + aResult = scanExtensionFolder( *pIter ); + ++pIter; + } + } + return aResult; +} + +bool OO3ExtensionMigration::scanDescriptionXml( const ::rtl::OUString& sDescriptionXmlURL ) +{ + if ( !m_xDocBuilder.is() ) + { + m_xDocBuilder = uno::Reference< xml::dom::XDocumentBuilder >( + m_ctx->getServiceManager()->createInstanceWithContext( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.dom.DocumentBuilder")), + m_ctx ), uno::UNO_QUERY ); + } + + if ( !m_xSimpleFileAccess.is() ) + { + m_xSimpleFileAccess = uno::Reference< ucb::XSimpleFileAccess >( + m_ctx->getServiceManager()->createInstanceWithContext( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.SimpleFileAccess")), + m_ctx ), uno::UNO_QUERY ); + } + + ::rtl::OUString aExtIdentifier; + if ( m_xDocBuilder.is() && m_xSimpleFileAccess.is() ) + { + try + { + uno::Reference< io::XInputStream > xIn = + m_xSimpleFileAccess->openFileRead( sDescriptionXmlURL ); + + if ( xIn.is() ) + { + uno::Reference< xml::dom::XDocument > xDoc = m_xDocBuilder->parse( xIn ); + if ( xDoc.is() ) + { + uno::Reference< xml::dom::XElement > xRoot = xDoc->getDocumentElement(); + if ( xRoot.is() && + xRoot->getTagName().equals(::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("description"))) ) + { + uno::Reference< xml::xpath::XXPathAPI > xPath( + m_ctx->getServiceManager()->createInstanceWithContext( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.xpath.XPathAPI")), + m_ctx), + uno::UNO_QUERY); + + xPath->registerNS( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc")), + xRoot->getNamespaceURI()); + xPath->registerNS( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("xlink")), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("http://www.w3.org/1999/xlink"))); + + try + { + uno::Reference< xml::dom::XNode > xRootNode( xRoot, uno::UNO_QUERY ); + uno::Reference< xml::dom::XNode > xNode( + xPath->selectSingleNode( + xRootNode, + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:identifier/@value")) )); + if ( xNode.is() ) + aExtIdentifier = xNode->getNodeValue(); + } + catch ( xml::xpath::XPathException& ) + { + } + catch ( xml::dom::DOMException& ) + { + } + } + } + } + + if ( aExtIdentifier.getLength() > 0 ) + { + // scan extension identifier and try to match with our black list entries + for ( sal_uInt32 i = 0; i < m_aBlackList.size(); i++ ) + { + utl::SearchParam param(m_aBlackList[i], utl::SearchParam::SRCH_REGEXP); + utl::TextSearch ts(param, LANGUAGE_DONTKNOW); + + xub_StrLen start = 0; + xub_StrLen end = static_cast<USHORT>(aExtIdentifier.getLength()); + if (ts.SearchFrwrd(aExtIdentifier, &start, &end)) + return false; + } + } + } + catch ( ucb::CommandAbortedException& ) + { + } + catch ( uno::RuntimeException& ) + { + } + + if ( aExtIdentifier.getLength() == 0 ) + { + // Fallback: + // Try to use the folder name to match our black list + // as some extensions don't provide an identifier in the + // description.xml! + for ( sal_uInt32 i = 0; i < m_aBlackList.size(); i++ ) + { + utl::SearchParam param(m_aBlackList[i], utl::SearchParam::SRCH_REGEXP); + utl::TextSearch ts(param, LANGUAGE_DONTKNOW); + + xub_StrLen start = 0; + xub_StrLen end = static_cast<USHORT>(sDescriptionXmlURL.getLength()); + if (ts.SearchFrwrd(sDescriptionXmlURL, &start, &end)) + return false; + } + } + } + + return true; +} + +bool OO3ExtensionMigration::migrateExtension( const ::rtl::OUString& sSourceDir ) +{ + if ( !m_xExtensionManager.is() ) + { + try + { + m_xExtensionManager = deployment::ExtensionManager::get( m_ctx ); + } + catch ( ucb::CommandFailedException & ){} + catch ( uno::RuntimeException & ) {} + } + + if ( m_xExtensionManager.is() ) + { + try + { + TmpRepositoryCommandEnv* pCmdEnv = new TmpRepositoryCommandEnv(); + + uno::Reference< ucb::XCommandEnvironment > xCmdEnv( + static_cast< cppu::OWeakObject* >( pCmdEnv ), uno::UNO_QUERY ); + uno::Reference< task::XAbortChannel > xAbortChannel; + uno::Reference< deployment::XPackage > xPackage = + m_xExtensionManager->addExtension( + sSourceDir, uno::Sequence<beans::NamedValue>(), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("user")), xAbortChannel, xCmdEnv ); + + if ( xPackage.is() ) + return true; + } + catch ( ucb::CommandFailedException& ) + { + } + catch ( ucb::CommandAbortedException& ) + { + } + catch ( lang::IllegalArgumentException& ) + { + } + } + + return false; +} + + +// ----------------------------------------------------------------------------- +// XServiceInfo +// ----------------------------------------------------------------------------- + +::rtl::OUString OO3ExtensionMigration::getImplementationName() throw (RuntimeException) +{ + return OO3ExtensionMigration_getImplementationName(); +} + +// ----------------------------------------------------------------------------- + +sal_Bool OO3ExtensionMigration::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException) +{ + Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() ); + const ::rtl::OUString* pNames = aNames.getConstArray(); + const ::rtl::OUString* pEnd = pNames + aNames.getLength(); + for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames ) + ; + + return pNames != pEnd; +} + +// ----------------------------------------------------------------------------- + +Sequence< ::rtl::OUString > OO3ExtensionMigration::getSupportedServiceNames() throw (RuntimeException) +{ + return OO3ExtensionMigration_getSupportedServiceNames(); +} + +// ----------------------------------------------------------------------------- +// XInitialization +// ----------------------------------------------------------------------------- + +void OO3ExtensionMigration::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + const Any* pIter = aArguments.getConstArray(); + const Any* pEnd = pIter + aArguments.getLength(); + for ( ; pIter != pEnd ; ++pIter ) + { + beans::NamedValue aValue; + *pIter >>= aValue; + if ( aValue.Name.equalsAscii( "UserData" ) ) + { + if ( !(aValue.Value >>= m_sSourceDir) ) + { + OSL_ENSURE( false, "ExtensionMigration::initialize: argument UserData has wrong type!" ); + } + } + else if ( aValue.Name.equalsAscii( "ExtensionBlackList" ) ) + { + Sequence< ::rtl::OUString > aBlackList; + if ( (aValue.Value >>= aBlackList ) && ( aBlackList.getLength() > 0 )) + { + m_aBlackList.resize( aBlackList.getLength() ); + ::comphelper::sequenceToArray< ::rtl::OUString >( &m_aBlackList[0], aBlackList ); + } + } + } +} + +// ----------------------------------------------------------------------------- + +TStringVectorPtr getContent( const ::rtl::OUString& rBaseURL ) +{ + TStringVectorPtr aResult( new TStringVector ); + ::osl::Directory aDir( rBaseURL); + if ( aDir.open() == ::osl::FileBase::E_None ) + { + // iterate over directory content + TStringVector aSubDirs; + ::osl::DirectoryItem aItem; + while ( aDir.getNextItem( aItem ) == ::osl::FileBase::E_None ) + { + ::osl::FileStatus aFileStatus( FileStatusMask_Type | FileStatusMask_FileURL ); + if ( aItem.getFileStatus( aFileStatus ) == ::osl::FileBase::E_None ) + aResult->push_back( aFileStatus.getFileURL() ); + } + } + + return aResult; +} + +Any OO3ExtensionMigration::execute( const Sequence< beans::NamedValue >& ) + throw (lang::IllegalArgumentException, Exception, RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + ::utl::Bootstrap::PathStatus aStatus = ::utl::Bootstrap::locateUserInstallation( m_sTargetDir ); + if ( aStatus == ::utl::Bootstrap::PATH_EXISTS ) + { + // copy all extensions + ::rtl::OUString sSourceDir( m_sSourceDir ); + sSourceDir += sExtensionSubDir; + sSourceDir += sSubDirName; + sSourceDir += sExtensionRootSubDirName; + TStringVector aExtensionToMigrate; + scanUserExtensions( sSourceDir, aExtensionToMigrate ); + if ( aExtensionToMigrate.size() > 0 ) + { + TStringVector::iterator pIter = aExtensionToMigrate.begin(); + while ( pIter != aExtensionToMigrate.end() ) + { + migrateExtension( *pIter ); + ++pIter; + } + } + } + + return Any(); +} + +// ----------------------------------------------------------------------------- +// TmpRepositoryCommandEnv +// ----------------------------------------------------------------------------- + +TmpRepositoryCommandEnv::TmpRepositoryCommandEnv() +{ +} + +TmpRepositoryCommandEnv::~TmpRepositoryCommandEnv() +{ +} +// XCommandEnvironment +//______________________________________________________________________________ +uno::Reference< task::XInteractionHandler > TmpRepositoryCommandEnv::getInteractionHandler() +throw ( uno::RuntimeException ) +{ + return this; +} + +//______________________________________________________________________________ +uno::Reference< ucb::XProgressHandler > TmpRepositoryCommandEnv::getProgressHandler() +throw ( uno::RuntimeException ) +{ + return this; +} + +// XInteractionHandler +void TmpRepositoryCommandEnv::handle( + uno::Reference< task::XInteractionRequest> const & xRequest ) + throw ( uno::RuntimeException ) +{ + uno::Any request( xRequest->getRequest() ); + OSL_ASSERT( request.getValueTypeClass() == uno::TypeClass_EXCEPTION ); + + bool approve = true; + bool abort = false; + + // select: + 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 (approve) { + uno::Reference< task::XInteractionApprove > xInteractionApprove( + pConts[ pos ], uno::UNO_QUERY ); + if (xInteractionApprove.is()) { + xInteractionApprove->select(); + // don't query again for ongoing continuations: + approve = false; + } + } + else if (abort) { + uno::Reference< task::XInteractionAbort > xInteractionAbort( + pConts[ pos ], uno::UNO_QUERY ); + if (xInteractionAbort.is()) { + xInteractionAbort->select(); + // don't query again for ongoing continuations: + abort = false; + } + } + } +} + +// XProgressHandler +void TmpRepositoryCommandEnv::push( uno::Any const & /*Status*/ ) +throw (uno::RuntimeException) +{ +} + + +void TmpRepositoryCommandEnv::update( uno::Any const & /*Status */) +throw (uno::RuntimeException) +{ +} + +void TmpRepositoryCommandEnv::pop() throw (uno::RuntimeException) +{ +} + +// ============================================================================= +// component operations +// ============================================================================= + +Reference< XInterface > SAL_CALL OO3ExtensionMigration_create( + Reference< XComponentContext > const & ctx ) + SAL_THROW( () ) +{ + return static_cast< lang::XTypeProvider * >( new OO3ExtensionMigration( + ctx) ); +} + +// ----------------------------------------------------------------------------- + +} // namespace migration + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/oo3extensionmigration.hxx b/desktop/source/migration/services/oo3extensionmigration.hxx new file mode 100644 index 000000000000..0843707fb660 --- /dev/null +++ b/desktop/source/migration/services/oo3extensionmigration.hxx @@ -0,0 +1,163 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_OO3EXTENSIONMIGRATION_HXX_ +#define _DESKTOP_OO3EXTENSIONMIGRATION_HXX_ + +#include "misc.hxx" +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/task/XJob.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/xml/dom/XDocumentBuilder.hpp> +#include <com/sun/star/ucb/XSimpleFileAccess.hpp> +#include <com/sun/star/deployment/XExtensionManager.hpp> + +#include <osl/mutex.hxx> +#include <osl/file.hxx> +#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/compbase3.hxx> +#include <ucbhelper/content.hxx> +#include <xmlscript/xmllib_imexp.hxx> + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } + namespace deployment { + class XPackage; + } +}}} + +class INetURLObject; + + +namespace migration +{ + + ::rtl::OUString SAL_CALL OO3ExtensionMigration_getImplementationName(); + ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL OO3ExtensionMigration_getSupportedServiceNames(); + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL OO3ExtensionMigration_create( + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & xContext ) + SAL_THROW( (::com::sun::star::uno::Exception) ); + + + // ============================================================================= + // class ExtensionMigration + // ============================================================================= + + typedef ::cppu::WeakImplHelper3< + ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::lang::XInitialization, + ::com::sun::star::task::XJob > ExtensionMigration_BASE; + + class OO3ExtensionMigration : public ExtensionMigration_BASE + { + private: + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_ctx; + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XDocumentBuilder > m_xDocBuilder; + ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess > m_xSimpleFileAccess; + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XExtensionManager > m_xExtensionManager; + ::osl::Mutex m_aMutex; + ::rtl::OUString m_sSourceDir; + ::rtl::OUString m_sTargetDir; + TStringVector m_aBlackList; + + enum ScanResult + { + SCANRESULT_NOTFOUND, + SCANRESULT_MIGRATE_EXTENSION, + SCANRESULT_DONTMIGRATE_EXTENSION + }; + + ::osl::FileBase::RC checkAndCreateDirectory( INetURLObject& rDirURL ); + ScanResult scanExtensionFolder( const ::rtl::OUString& sExtFolder ); + void scanUserExtensions( const ::rtl::OUString& sSourceDir, TStringVector& aMigrateExtensions ); + bool scanDescriptionXml( const ::rtl::OUString& sDescriptionXmlFilePath ); + bool migrateExtension( const ::rtl::OUString& sSourceDir ); + + public: + OO3ExtensionMigration(::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > const & ctx); + virtual ~OO3ExtensionMigration(); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& rServiceName ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() + throw (::com::sun::star::uno::RuntimeException); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XJob + virtual ::com::sun::star::uno::Any SAL_CALL execute( + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& Arguments ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException); + }; + + class TmpRepositoryCommandEnv + : public ::cppu::WeakImplHelper3< ::com::sun::star::ucb::XCommandEnvironment, + ::com::sun::star::task::XInteractionHandler, + ::com::sun::star::ucb::XProgressHandler > + { + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > m_xContext; + ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler> m_forwardHandler; + public: + virtual ~TmpRepositoryCommandEnv(); + TmpRepositoryCommandEnv(); + + // XCommandEnvironment + virtual ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > SAL_CALL + getInteractionHandler() throw ( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XProgressHandler > + SAL_CALL getProgressHandler() throw ( ::com::sun::star::uno::RuntimeException ); + + // XInteractionHandler + virtual void SAL_CALL handle( + ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionRequest > const & xRequest ) + throw (::com::sun::star::uno::RuntimeException); + + // XProgressHandler + virtual void SAL_CALL push( ::com::sun::star::uno::Any const & Status ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL update( ::com::sun::star::uno::Any const & Status ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL pop() throw (::com::sun::star::uno::RuntimeException); + }; + +//......................................................................... +} // namespace migration +//......................................................................... + +#endif // _DESKTOP_OO3EXTENSIONMIGRATION_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/wordbookmigration.cxx b/desktop/source/migration/services/wordbookmigration.cxx new file mode 100644 index 000000000000..152cded83c9b --- /dev/null +++ b/desktop/source/migration/services/wordbookmigration.cxx @@ -0,0 +1,325 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "wordbookmigration.hxx" +#include <tools/urlobj.hxx> +#include <unotools/bootstrap.hxx> +#include <unotools/ucbstreamhelper.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + + +//......................................................................... +namespace migration +{ +//......................................................................... + + + static ::rtl::OUString sSourceSubDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/wordbook" ) ); + static ::rtl::OUString sTargetSubDir = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/user/wordbook" ) ); + static ::rtl::OUString sBaseName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/wordbook" ) ); + static ::rtl::OUString sSuffix = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".dic" ) ); + + + // ============================================================================= + // component operations + // ============================================================================= + + ::rtl::OUString WordbookMigration_getImplementationName() + { + static ::rtl::OUString* pImplName = 0; + if ( !pImplName ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !pImplName ) + { + static ::rtl::OUString aImplName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.desktop.migration.Wordbooks" ) ); + pImplName = &aImplName; + } + } + return *pImplName; + } + + // ----------------------------------------------------------------------------- + + Sequence< ::rtl::OUString > WordbookMigration_getSupportedServiceNames() + { + static Sequence< ::rtl::OUString >* pNames = 0; + if ( !pNames ) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if ( !pNames ) + { + static Sequence< ::rtl::OUString > aNames(1); + aNames.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.migration.Wordbooks" ) ); + pNames = &aNames; + } + } + return *pNames; + } + + // ============================================================================= + // WordbookMigration + // ============================================================================= + + WordbookMigration::WordbookMigration() + { + } + + // ----------------------------------------------------------------------------- + + WordbookMigration::~WordbookMigration() + { + } + + // ----------------------------------------------------------------------------- + + TStringVectorPtr WordbookMigration::getFiles( const ::rtl::OUString& rBaseURL ) const + { + TStringVectorPtr aResult( new TStringVector ); + ::osl::Directory aDir( rBaseURL); + + if ( aDir.open() == ::osl::FileBase::E_None ) + { + // iterate over directory content + TStringVector aSubDirs; + ::osl::DirectoryItem aItem; + while ( aDir.getNextItem( aItem ) == ::osl::FileBase::E_None ) + { + ::osl::FileStatus aFileStatus( FileStatusMask_Type | FileStatusMask_FileURL ); + if ( aItem.getFileStatus( aFileStatus ) == ::osl::FileBase::E_None ) + { + if ( aFileStatus.getFileType() == ::osl::FileStatus::Directory ) + aSubDirs.push_back( aFileStatus.getFileURL() ); + else + aResult->push_back( aFileStatus.getFileURL() ); + } + } + + // iterate recursive over subfolders + TStringVector::const_iterator aI = aSubDirs.begin(); + while ( aI != aSubDirs.end() ) + { + TStringVectorPtr aSubResult = getFiles( *aI ); + aResult->insert( aResult->end(), aSubResult->begin(), aSubResult->end() ); + ++aI; + } + } + + return aResult; + } + + // ----------------------------------------------------------------------------- + + ::osl::FileBase::RC WordbookMigration::checkAndCreateDirectory( INetURLObject& rDirURL ) + { + ::osl::FileBase::RC aResult = ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) ); + if ( aResult == ::osl::FileBase::E_NOENT ) + { + INetURLObject aBaseURL( rDirURL ); + aBaseURL.removeSegment(); + checkAndCreateDirectory( aBaseURL ); + return ::osl::Directory::create( rDirURL.GetMainURL( INetURLObject::DECODE_TO_IURI ) ); + } + else + { + return aResult; + } + } + +#define MAX_HEADER_LENGTH 16 +bool IsUserWordbook( const ::rtl::OUString& rFile ) +{ + static const sal_Char* pVerStr2 = "WBSWG2"; + static const sal_Char* pVerStr5 = "WBSWG5"; + static const sal_Char* pVerStr6 = "WBSWG6"; + static const sal_Char* pVerOOo7 = "OOoUserDict1"; + + bool bRet = false; + SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( String(rFile), STREAM_STD_READ ); + if ( pStream && !pStream->GetError() ) + { + sal_Size nSniffPos = pStream->Tell(); + static sal_Size nVerOOo7Len = sal::static_int_cast< sal_Size >(strlen( pVerOOo7 )); + sal_Char pMagicHeader[MAX_HEADER_LENGTH]; + pMagicHeader[ nVerOOo7Len ] = '\0'; + if ((pStream->Read((void *) pMagicHeader, nVerOOo7Len) == nVerOOo7Len)) + { + if ( !strcmp(pMagicHeader, pVerOOo7) ) + bRet = true; + else + { + USHORT nLen; + pStream->Seek (nSniffPos); + *pStream >> nLen; + if ( nLen < MAX_HEADER_LENGTH ) + { + pStream->Read(pMagicHeader, nLen); + pMagicHeader[nLen] = '\0'; + if ( !strcmp(pMagicHeader, pVerStr2) + || !strcmp(pMagicHeader, pVerStr5) + || !strcmp(pMagicHeader, pVerStr6) ) + bRet = true; + } + } + } + } + + delete pStream; + return bRet; +} + + + // ----------------------------------------------------------------------------- + + void WordbookMigration::copyFiles() + { + ::rtl::OUString sTargetDir; + ::utl::Bootstrap::PathStatus aStatus = ::utl::Bootstrap::locateUserInstallation( sTargetDir ); + if ( aStatus == ::utl::Bootstrap::PATH_EXISTS ) + { + sTargetDir += sTargetSubDir; + TStringVectorPtr aFileList = getFiles( m_sSourceDir ); + TStringVector::const_iterator aI = aFileList->begin(); + while ( aI != aFileList->end() ) + { + if (IsUserWordbook(*aI) ) + { + ::rtl::OUString sSourceLocalName = aI->copy( m_sSourceDir.getLength() ); + ::rtl::OUString sTargetName = sTargetDir + sSourceLocalName; + INetURLObject aURL( sTargetName ); + aURL.removeSegment(); + checkAndCreateDirectory( aURL ); + ::osl::FileBase::RC aResult = ::osl::File::copy( *aI, sTargetName ); + if ( aResult != ::osl::FileBase::E_None ) + { + ::rtl::OString aMsg( "WordbookMigration::copyFiles: cannot copy " ); + aMsg += ::rtl::OUStringToOString( *aI, RTL_TEXTENCODING_UTF8 ) + " to " + + ::rtl::OUStringToOString( sTargetName, RTL_TEXTENCODING_UTF8 ); + OSL_ENSURE( sal_False, aMsg.getStr() ); + } + } + ++aI; + } + } + else + { + OSL_ENSURE( sal_False, "WordbookMigration::copyFiles: no user installation!" ); + } + } + + // ----------------------------------------------------------------------------- + // XServiceInfo + // ----------------------------------------------------------------------------- + + ::rtl::OUString WordbookMigration::getImplementationName() throw (RuntimeException) + { + return WordbookMigration_getImplementationName(); + } + + // ----------------------------------------------------------------------------- + + sal_Bool WordbookMigration::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() ); + const ::rtl::OUString* pNames = aNames.getConstArray(); + const ::rtl::OUString* pEnd = pNames + aNames.getLength(); + for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames ) + ; + + return pNames != pEnd; + } + + // ----------------------------------------------------------------------------- + + Sequence< ::rtl::OUString > WordbookMigration::getSupportedServiceNames() throw (RuntimeException) + { + return WordbookMigration_getSupportedServiceNames(); + } + + // ----------------------------------------------------------------------------- + // XInitialization + // ----------------------------------------------------------------------------- + + void WordbookMigration::initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + const Any* pIter = aArguments.getConstArray(); + const Any* pEnd = pIter + aArguments.getLength(); + for ( ; pIter != pEnd ; ++pIter ) + { + beans::NamedValue aValue; + *pIter >>= aValue; + if ( aValue.Name.equalsAscii( "UserData" ) ) + { + if ( !(aValue.Value >>= m_sSourceDir) ) + { + OSL_ENSURE( false, "WordbookMigration::initialize: argument UserData has wrong type!" ); + } + m_sSourceDir += sSourceSubDir; + break; + } + } + } + + // ----------------------------------------------------------------------------- + // XJob + // ----------------------------------------------------------------------------- + + Any WordbookMigration::execute( const Sequence< beans::NamedValue >& ) + throw (lang::IllegalArgumentException, Exception, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + copyFiles(); + + return Any(); + } + + // ============================================================================= + // component operations + // ============================================================================= + + Reference< XInterface > SAL_CALL WordbookMigration_create( + Reference< XComponentContext > const & ) + SAL_THROW( () ) + { + return static_cast< lang::XTypeProvider * >( new WordbookMigration() ); + } + + // ----------------------------------------------------------------------------- + +//......................................................................... +} // namespace migration +//......................................................................... + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/migration/services/wordbookmigration.hxx b/desktop/source/migration/services/wordbookmigration.hxx new file mode 100644 index 000000000000..8b04417dbaf7 --- /dev/null +++ b/desktop/source/migration/services/wordbookmigration.hxx @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_WORDBOOKMIGRATION_HXX_ +#define _DESKTOP_WORDBOOKMIGRATION_HXX_ + +#include "misc.hxx" +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/task/XJob.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/implbase3.hxx> +#include <osl/mutex.hxx> +#include <osl/file.hxx> + + +class INetURLObject; + + +//......................................................................... +namespace migration +{ +//......................................................................... + + ::rtl::OUString SAL_CALL WordbookMigration_getImplementationName(); + ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL WordbookMigration_getSupportedServiceNames(); + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL WordbookMigration_create( + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & xContext ) + SAL_THROW( (::com::sun::star::uno::Exception) ); + + + // ============================================================================= + // class WordbookMigration + // ============================================================================= + + typedef ::cppu::WeakImplHelper3< + ::com::sun::star::lang::XServiceInfo, + ::com::sun::star::lang::XInitialization, + ::com::sun::star::task::XJob > WordbookMigration_BASE; + + class WordbookMigration : public WordbookMigration_BASE + { + private: + ::osl::Mutex m_aMutex; + ::rtl::OUString m_sSourceDir; + + TStringVectorPtr getFiles( const ::rtl::OUString& rBaseURL ) const; + ::osl::FileBase::RC checkAndCreateDirectory( INetURLObject& rDirURL ); + void copyFiles(); + + public: + WordbookMigration(); + virtual ~WordbookMigration(); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& rServiceName ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() + throw (::com::sun::star::uno::RuntimeException); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XJob + virtual ::com::sun::star::uno::Any SAL_CALL execute( + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& Arguments ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::Exception, + ::com::sun::star::uno::RuntimeException); + }; + +//......................................................................... +} // namespace migration +//......................................................................... + +#endif // _DESKTOP_AUTOCORRMIGRATION_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/offacc/acceptor.cxx b/desktop/source/offacc/acceptor.cxx new file mode 100644 index 000000000000..19899375973b --- /dev/null +++ b/desktop/source/offacc/acceptor.cxx @@ -0,0 +1,367 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "acceptor.hxx" +#include <unotools/bootstrap.hxx> +#include <tools/urlobj.hxx> +#include <tools/stream.hxx> +#include <vcl/svapp.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/uno/XNamingService.hpp> + +#include <cppuhelper/factory.hxx> + +namespace desktop +{ + +extern "C" void workerfunc (void * acc) +{ + ((Acceptor*)acc)->run(); +} + +static Reference<XInterface> getComponentContext( const Reference<XMultiServiceFactory>& rFactory) +{ + Reference<XInterface> rContext; + Reference< XPropertySet > rPropSet( rFactory, UNO_QUERY ); + Any a = rPropSet->getPropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ); + a >>= rContext; + return rContext; +} + +Mutex Acceptor::m_aMutex; + +Acceptor::Acceptor( const Reference< XMultiServiceFactory >& rFactory ) + : m_thread(NULL) + , m_aAcceptString() + , m_aConnectString() + , m_aProtocol() + , m_bInit(sal_False) + , m_bDying(false) +{ + m_rSMgr = rFactory; + m_rAcceptor = Reference< XAcceptor > (m_rSMgr->createInstance( + rtl::OUString::createFromAscii( "com.sun.star.connection.Acceptor" )), + UNO_QUERY ); + m_rBridgeFactory = Reference < XBridgeFactory > (m_rSMgr->createInstance( + rtl::OUString::createFromAscii( "com.sun.star.bridge.BridgeFactory" )), + UNO_QUERY ); + // get component context + m_rContext = getComponentContext(m_rSMgr); +} + + +Acceptor::~Acceptor() +{ + m_rAcceptor->stopAccepting(); + oslThread t; + { + osl::MutexGuard g(m_aMutex); + t = m_thread; + } + //prevent locking if the thread is still waiting + m_bDying = true; + m_cEnable.set(); + osl_joinWithThread(t); + { + // Make the final state of m_bridges visible to this thread (since + // m_thread is joined, the code that follows is the only one left + // accessing m_bridges): + osl::MutexGuard g(m_aMutex); + } + for (;;) { + com::sun::star::uno::Reference< com::sun::star::bridge::XBridge > b( + m_bridges.remove()); + if (!b.is()) { + break; + } + com::sun::star::uno::Reference< com::sun::star::lang::XComponent >( + b, com::sun::star::uno::UNO_QUERY_THROW)->dispose(); + } +} + +void SAL_CALL Acceptor::run() +{ + while ( m_rAcceptor.is() && m_rBridgeFactory.is() ) + { + RTL_LOGFILE_CONTEXT( aLog, "desktop (lo119109) Acceptor::run" ); + try + { + // wait until we get enabled + RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109)"\ + "Acceptor::run waiting for office to come up"); + m_cEnable.wait(); + if (m_bDying) //see destructor + break; + RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109)"\ + "Acceptor::run now enabled and continuing"); + + // accept connection + Reference< XConnection > rConnection = m_rAcceptor->accept( m_aConnectString ); + // if we return without a valid connection we mus assume that the acceptor + // is destructed so we break out of the run method terminating the thread + if (! rConnection.is()) break; + OUString aDescription = rConnection->getDescription(); + RTL_LOGFILE_CONTEXT_TRACE1( aLog, "desktop (lo119109) Acceptor::run connection %s", + OUStringToOString(aDescription, RTL_TEXTENCODING_ASCII_US).getStr()); + + // create instanceprovider for this connection + Reference< XInstanceProvider > rInstanceProvider( + (XInstanceProvider*)new AccInstanceProvider(m_rSMgr, rConnection)); + // create the bridge. The remote end will have a reference to this bridge + // thus preventing the bridge from being disposed. When the remote end releases + // the bridge, it will be destructed. + Reference< XBridge > rBridge = m_rBridgeFactory->createBridge( + rtl::OUString() ,m_aProtocol ,rConnection ,rInstanceProvider ); + osl::MutexGuard g(m_aMutex); + m_bridges.add(rBridge); + } catch (Exception&) { + // connection failed... + // something went wrong during connection setup. + // just wait for a new connection to accept + } + } +} + +// XInitialize +void SAL_CALL Acceptor::initialize( const Sequence<Any>& aArguments ) + throw( Exception ) +{ + // prevent multiple initialization + ClearableMutexGuard aGuard( m_aMutex ); + RTL_LOGFILE_CONTEXT( aLog, "destop (lo119109) Acceptor::initialize()" ); + + sal_Bool bOk = sal_False; + + // arg count + int nArgs = aArguments.getLength(); + + // not yet initialized and acceptstring + if (!m_bInit && nArgs > 0 && (aArguments[0] >>= m_aAcceptString)) + { + RTL_LOGFILE_CONTEXT_TRACE1( aLog, "desktop (lo119109) Acceptor::initialize string=%s", + OUStringToOString(m_aAcceptString, RTL_TEXTENCODING_ASCII_US).getStr()); + + // get connect string and protocol from accept string + // "<connectString>;<protocol>" + sal_Int32 nIndex1 = m_aAcceptString.indexOf( (sal_Unicode) ';' ); + if (nIndex1 < 0) throw IllegalArgumentException( + OUString::createFromAscii("Invalid accept-string format"), m_rContext, 1); + m_aConnectString = m_aAcceptString.copy( 0 , nIndex1 ).trim(); + nIndex1++; + sal_Int32 nIndex2 = m_aAcceptString.indexOf( (sal_Unicode) ';' , nIndex1 ); + if (nIndex2 < 0) nIndex2 = m_aAcceptString.getLength(); + m_aProtocol = m_aAcceptString.copy( nIndex1, nIndex2 - nIndex1 ); + + // start accepting in new thread... + m_thread = osl_createThread(workerfunc, this); + m_bInit = sal_True; + bOk = sal_True; + } + + // do we want to enable accepting? + sal_Bool bEnable = sal_False; + if (((nArgs == 1 && (aArguments[0] >>= bEnable)) || + (nArgs == 2 && (aArguments[1] >>= bEnable))) && + bEnable ) + { + m_cEnable.set(); + bOk = sal_True; + } + + if (!bOk) + { + throw IllegalArgumentException( + OUString::createFromAscii("invalid initialization"), m_rContext, 1); + } +} + +// XServiceInfo +const sal_Char *Acceptor::serviceName = "com.sun.star.office.Acceptor"; +const sal_Char *Acceptor::implementationName = "com.sun.star.office.comp.Acceptor"; +const sal_Char *Acceptor::supportedServiceNames[] = {"com.sun.star.office.Acceptor", NULL}; +OUString Acceptor::impl_getImplementationName() +{ + return OUString::createFromAscii( implementationName ); +} +OUString SAL_CALL Acceptor::getImplementationName() + throw (RuntimeException) +{ + return Acceptor::impl_getImplementationName(); +} +Sequence<OUString> Acceptor::impl_getSupportedServiceNames() +{ + Sequence<OUString> aSequence; + for (int i=0; supportedServiceNames[i]!=NULL; i++) { + aSequence.realloc(i+1); + aSequence[i]=(OUString::createFromAscii(supportedServiceNames[i])); + } + return aSequence; +} +Sequence<OUString> SAL_CALL Acceptor::getSupportedServiceNames() + throw (RuntimeException) +{ + return Acceptor::impl_getSupportedServiceNames(); +} +sal_Bool SAL_CALL Acceptor::supportsService( const OUString&) + throw (RuntimeException) +{ + return sal_False; +} + +// Factory +Reference< XInterface > Acceptor::impl_getInstance( const Reference< XMultiServiceFactory >& aFactory ) +{ + try { + return (XComponent*) new Acceptor( aFactory ); + } catch ( Exception& ) { + return (XComponent*) NULL; + } +} + +// InstanceProvider +AccInstanceProvider::AccInstanceProvider(const Reference<XMultiServiceFactory>& aFactory, const Reference<XConnection>& rConnection) +{ + m_rSMgr = aFactory; + m_rConnection = rConnection; +} + +AccInstanceProvider::~AccInstanceProvider() +{ +} + +Reference<XInterface> SAL_CALL AccInstanceProvider::getInstance (const OUString& aName ) + throw ( NoSuchElementException ) +{ + + Reference<XInterface> rInstance; + + if ( aName.compareToAscii( "StarOffice.ServiceManager" ) == 0) + { + rInstance = Reference< XInterface >( m_rSMgr ); + } + else if(aName.compareToAscii( "StarOffice.ComponentContext" ) == 0 ) + { + rInstance = getComponentContext( m_rSMgr ); + } + else if ( aName.compareToAscii("StarOffice.NamingService" ) == 0 ) + { + Reference< XNamingService > rNamingService( + m_rSMgr->createInstance( OUString::createFromAscii( "com.sun.star.uno.NamingService" )), + UNO_QUERY ); + if ( rNamingService.is() ) + { + rNamingService->registerObject( + OUString::createFromAscii( "StarOffice.ServiceManager" ), m_rSMgr ); + rNamingService->registerObject( + OUString::createFromAscii( "StarOffice.ComponentContext" ), getComponentContext( m_rSMgr )); + rInstance = rNamingService; + } + } + /* + else if ( aName.compareToAscii("com.sun.star.ucb.RemoteContentProviderAcceptor" )) + { + Reference< XMultiServiceFactory > rSMgr = ::comphelper::getProcessServiceFactory(); + if ( rSMgr.is() ) { + try { + rInstance = rSMgr->createInstance( sObjectName ); + } + catch (Exception const &) {} + } + } + */ + return rInstance; +} + +} + +// component management stuff... +// ---------------------------------------------------------------------------- +extern "C" +{ +using namespace desktop; + +void SAL_CALL +component_getImplementationEnvironment(const sal_Char **ppEnvironmentTypeName, uno_Environment **) +{ + *ppEnvironmentTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ; +} + +sal_Bool SAL_CALL +component_writeInfo(void *pServiceManager, void *pRegistryKey) +{ + Reference< XMultiServiceFactory > xMan(reinterpret_cast< XMultiServiceFactory* >(pServiceManager)); + Reference< XRegistryKey > xKey(reinterpret_cast< XRegistryKey* >(pRegistryKey)); + + // register service + ::rtl::OUString aTempStr; + ::rtl::OUString aImpl(RTL_CONSTASCII_USTRINGPARAM("/")); + aImpl += Acceptor::impl_getImplementationName(); + aImpl += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/UNO/SERVICES")); + Reference< XRegistryKey > xNewKey = xKey->createKey(aImpl); + xNewKey->createKey(Acceptor::impl_getSupportedServiceNames()[0]); + + return sal_True; +} + +void * SAL_CALL +component_getFactory(const sal_Char *pImplementationName, void *pServiceManager, void *) +{ + void* pReturn = NULL ; + if ( pImplementationName && pServiceManager ) + { + // Define variables which are used in following macros. + Reference< XSingleServiceFactory > xFactory; + Reference< XMultiServiceFactory > xServiceManager( + reinterpret_cast< XMultiServiceFactory* >(pServiceManager)); + + if (Acceptor::impl_getImplementationName().compareToAscii( pImplementationName ) == COMPARE_EQUAL ) + { + xFactory = Reference< XSingleServiceFactory >( cppu::createSingleFactory( + xServiceManager, Acceptor::impl_getImplementationName(), + Acceptor::impl_getInstance, Acceptor::impl_getSupportedServiceNames()) ); + } + + // Factory is valid - service was found. + if ( xFactory.is() ) + { + xFactory->acquire(); + pReturn = xFactory.get(); + } + } + + // Return with result of this operation. + return pReturn ; +} + +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/offacc/acceptor.hxx b/desktop/source/offacc/acceptor.hxx new file mode 100644 index 000000000000..4096b3e63c48 --- /dev/null +++ b/desktop/source/offacc/acceptor.hxx @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/connection/XAcceptor.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/bridge/XInstanceProvider.hpp> +#include <com/sun/star/bridge/XBridgeFactory.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.hxx> +#include <cppuhelper/interfacecontainer.h> +#include <rtl/logfile.hxx> + +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <comphelper/weakbag.hxx> +#include <osl/mutex.hxx> +#include <osl/conditn.hxx> +#include <osl/thread.hxx> + + +using namespace ::rtl; +using namespace ::osl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::bridge; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::connection; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::registry; + +namespace desktop { + +class Acceptor + : public ::cppu::WeakImplHelper2<XServiceInfo, XInitialization> +{ +private: + static const sal_Char *serviceName; + static const sal_Char *implementationName; + static const sal_Char *supportedServiceNames[]; + + static Mutex m_aMutex; + + oslThread m_thread; + comphelper::WeakBag< com::sun::star::bridge::XBridge > m_bridges; + + Condition m_cEnable; + + Reference< XMultiServiceFactory > m_rSMgr; + Reference< XInterface > m_rContext; + Reference< XAcceptor > m_rAcceptor; + Reference< XBridgeFactory > m_rBridgeFactory; + + OUString m_aAcceptString; + OUString m_aConnectString; + OUString m_aProtocol; + + sal_Bool m_bInit; + bool m_bDying; + +public: + Acceptor( const Reference< XMultiServiceFactory >& aFactory ); + virtual ~Acceptor(); + + void SAL_CALL run(); + + // XService info + static OUString impl_getImplementationName(); + virtual OUString SAL_CALL getImplementationName() + throw (RuntimeException); + static Sequence<OUString> impl_getSupportedServiceNames(); + virtual Sequence<OUString> SAL_CALL getSupportedServiceNames() + throw (RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const OUString& aName ) + throw (RuntimeException); + + // XInitialize + virtual void SAL_CALL initialize( const Sequence<Any>& aArguments ) + throw ( Exception ); + + static Reference<XInterface> impl_getInstance( const Reference< XMultiServiceFactory >& aFactory ); +}; + +class AccInstanceProvider : public ::cppu::WeakImplHelper1<XInstanceProvider> +{ +private: + Reference<XMultiServiceFactory> m_rSMgr; + Reference<XConnection> m_rConnection; + +public: + AccInstanceProvider(const Reference< XMultiServiceFactory >& aFactory, + const Reference< XConnection >& rConnection); + virtual ~AccInstanceProvider(); + + // XInstanceProvider + virtual Reference<XInterface> SAL_CALL getInstance (const OUString& aName ) + throw ( NoSuchElementException ); +}; + + +} //namespace desktop + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/offacc/makefile.mk b/desktop/source/offacc/makefile.mk new file mode 100644 index 000000000000..c2d53930b580 --- /dev/null +++ b/desktop/source/offacc/makefile.mk @@ -0,0 +1,62 @@ +#************************************************************************* +# +# 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=offacc +LIBTARGET=NO + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +SLOFILES = $(SLO)$/acceptor.obj + +SHL1DEPN= makefile.mk +SHL1OBJS= $(SLOFILES) + +SHL1TARGET= $(TARGET)$(DLLPOSTFIX) +SHL1IMPLIB= i$(TARGET) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +DEF1NAME=$(SHL1TARGET) + +SHL1STDLIBS= \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/desktop/source/pagein/file_image.h b/desktop/source/pagein/file_image.h new file mode 100644 index 000000000000..4234140027f2 --- /dev/null +++ b/desktop/source/pagein/file_image.h @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_FILE_IMAGE_H +#define INCLUDED_FILE_IMAGE_H + +#ifndef INCLUDED_STDDEF_H +#include <stddef.h> +#define INCLUDED_STDDEF_H +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** file_image. + */ +struct file_image_st +{ + void * m_base; + size_t m_size; +}; + +typedef struct file_image_st file_image; + +#define FILE_IMAGE_INITIALIZER { 0, 0 } + + +/** file_image_open. + */ +int file_image_open ( + file_image * image, + const char * filename); + + +/** file_image_pagein. + */ +int file_image_pagein ( + file_image * image); + + +/** file_image_close. + */ +int file_image_close ( + file_image * image); + + +/** Epilog. + */ +#ifdef __cplusplus +} +#endif + +#endif /* INCLUDED_ODEP_IMAGE_H */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/pagein/file_image_unx.c b/desktop/source/pagein/file_image_unx.c new file mode 100644 index 000000000000..41d60e80350c --- /dev/null +++ b/desktop/source/pagein/file_image_unx.c @@ -0,0 +1,153 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "file_image.h" + +#include <unistd.h> + +#include <errno.h> +#include <fcntl.h> + +#if defined(LINUX) +# ifndef __USE_BSD +# define __USE_BSD /* madvise, MADV_WILLNEED */ +# endif +#endif /* Linux */ + +#include <sys/mman.h> +#include <sys/stat.h> + +#include <string.h> + +/* + * file_image_open + */ +int file_image_open (file_image * image, const char * filename) +{ + int result = 0; + int fd; + struct stat st; + void * p; + + if (image == 0) + return (EINVAL); + + image->m_base = MAP_FAILED, image->m_size = 0; + + if ((fd = open (filename, O_RDONLY)) == -1) + return (errno); + + if (fstat (fd, &st) == -1) + { + result = errno; + goto cleanup_and_leave; + } + + p = mmap (0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (p == MAP_FAILED) + { + result = errno; + goto cleanup_and_leave; + } + + image->m_base = p, image->m_size = st.st_size; + +cleanup_and_leave: + close (fd); + return (result); +} + +/* + * file_image_pagein. + */ +int file_image_pagein (file_image * image) +{ + file_image w; + long s; + size_t k; + volatile char c = 0; + + if (image == 0) + return (EINVAL); + + if ((w.m_base = image->m_base) == 0) + return (EINVAL); + if ((w.m_size = image->m_size) == 0) + return (0); + + if (madvise (w.m_base, w.m_size, MADV_WILLNEED) == -1) + { +#ifndef MACOSX + return (errno); +#else + /* madvise MADV_WILLNEED need not succeed here */ + /* but that is fine */ +#endif + } + + +#ifndef MACOSX + if ((s = sysconf (_SC_PAGESIZE)) == -1) + s = 0x1000; +#else + s = getpagesize(); +#endif + + k = (size_t)(s); + while (w.m_size > k) + { + c ^= ((char*)(w.m_base))[0]; + w.m_base = (char*)(w.m_base) + k; + w.m_size -= k; + } + if (w.m_size > 0) + { + c ^= ((char*)(w.m_base))[0]; + w.m_base = (char*)(w.m_base) + w.m_size; + w.m_size -= w.m_size; + } + + return (0); +} + +/* + * file_image_close + */ +int file_image_close (file_image * image) +{ + if (image == 0) + return (EINVAL); + + if (munmap (image->m_base, image->m_size) == -1) + return (errno); + + image->m_base = 0, image->m_size = 0; + return (0); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/pagein/makefile.mk b/desktop/source/pagein/makefile.mk new file mode 100644 index 000000000000..01452a858e66 --- /dev/null +++ b/desktop/source/pagein/makefile.mk @@ -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. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=desktop +TARGET=pagein +TARGETTYPE=CUI +LIBTARGET=NO + +NO_DEFAULT_STL=TRUE +LIBSALCPPRT=$(0) + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +.INCLUDE .IGNORE : icuversion.mk + +# --- Files -------------------------------------------------------- + +OBJFILES= \ + $(OBJ)$/pagein.obj \ + $(OBJ)$/file_image_unx.obj + +APP1TARGET=$(TARGET) +APP1OBJS=$(OBJFILES) +APP1CODETYPE=C + +# depends on libc only. +STDLIB= + +# --- Targets ------------------------------------------------------ + +ALL: \ + $(MISC)$/$(TARGET)-calc \ + $(MISC)$/$(TARGET)-draw \ + $(MISC)$/$(TARGET)-impress \ + $(MISC)$/$(TARGET)-writer \ + $(MISC)$/$(TARGET)-common \ + ALLTAR + +.INCLUDE : target.mk + +ICUDLLPOST=$(DLLPOST).$(ICU_MAJOR)$(ICU_MINOR) +UDKDLLPOST=$(DLLPOST).$(UDK_MAJOR) +UNODLLPOST=.uno$(DLLPOST) +DFTDLLPOST=$(DLLPOSTFIX)$(DLLPOST) # Default + +URELIBPATH=..$/ure-link$/lib + +$(MISC)$/$(TARGET)-calc : makefile.mk + @echo Making: $@ + @-echo $(DLLPRE)sc$(DFTDLLPOST) > $@ + @-echo $(DLLPRE)svx$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)svxcore$(DFTDLLPOST) >> $@ + +$(MISC)$/$(TARGET)-draw : makefile.mk + @echo Making: $@ + @-echo $(DLLPRE)sd$(DFTDLLPOST) > $@ + @-echo $(DLLPRE)svx$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)svxcore$(DFTDLLPOST) >> $@ + +$(MISC)$/$(TARGET)-impress : makefile.mk + @echo Making: $@ + @-echo $(DLLPRE)sd$(DFTDLLPOST) > $@ + @-echo $(DLLPRE)svx$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)svxcore$(DFTDLLPOST) >> $@ + +$(MISC)$/$(TARGET)-writer : makefile.mk + @echo Making: $@ + @-echo $(DLLPRE)sw$(DFTDLLPOST) > $@ + @-echo $(DLLPRE)svx$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)svxcore$(DFTDLLPOST) >> $@ + +# sorted in approx. reverse load order (ld.so.1) +$(MISC)$/$(TARGET)-common : makefile.mk + @echo Making: $@ + @-echo i18npool$(UNODLLPOST) > $@ +.IF "$(SYSTEM_ICU)" != "YES" + @-echo $(DLLPRE)icui18n$(ICUDLLPOST) >> $@ + @-echo $(DLLPRE)icule$(ICUDLLPOST) >> $@ + @-echo $(DLLPRE)icuuc$(ICUDLLPOST) >> $@ + @-echo $(DLLPRE)icudata$(ICUDLLPOST) >> $@ +.ENDIF # SYSTEM_ICU +# + @-echo $(DLLPRE)lng$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)xo$(DFTDLLPOST) >> $@ +# + + @-echo $(DLLPRE)fwe$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)fwk$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)fwi$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)fwl$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)package2$(DLLPOST) >> $@ + @-echo $(DLLPRE)ucpfile1$(DLLPOST) >> $@ + @-echo $(DLLPRE)ucb1$(DLLPOST) >> $@ + @-echo $(DLLPRE)configmgr$(DLLPOST) >> $@ +# + @-echo $(DLLPRE)dtrans$(DLLPOST) >> $@ + @-echo $(DLLPRE)vclplug_gen$(DFTDLLPOST) >> $@ +.IF "$(ENABLE_GTK)" != "" + @-echo $(DLLPRE)vclplug_gtk$(DFTDLLPOST) >> $@ +.ENDIF # ENABLE_GTK +.IF "$(ENABLE_KDE)" != "" + @-echo $(DLLPRE)vclplug_kde$(DFTDLLPOST) >> $@ +.ENDIF # ENABLE_KDE +# + @-echo $(DLLPRE)basegfx$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)sot$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)xcr$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)sb$(DFTDLLPOST) >> $@ +# +# uno runtime environment +# + @-echo $(URELIBPATH)$/stocservices$(UNODLLPOST) >> $@ + @-echo $(URELIBPATH)$/bootstrap$(UNODLLPOST) >> $@ + @-echo $(URELIBPATH)$/$(DLLPRE)reg$(UDKDLLPOST) >> $@ + @-echo $(URELIBPATH)$/$(DLLPRE)store$(UDKDLLPOST) >> $@ +.IF "$(USE_SYSTEM_STL)"!="YES" +.IF "$(COMNAME)" == "gcc2" || "$(COMNAME)" == "gcc3" + @-echo $(URELIBPATH)$/$(DLLPRE)stlport_gcc$(DLLPOST) >> $@ +.ENDIF # gcc +.IF "$(COMNAME)" == "sunpro5" + @-echo $(URELIBPATH)$/$(DLLPRE)stlport_sunpro$(DLLPOST) >> $@ +.ENDIF # sunpro5 +.ENDIF # SYSTEM_STL + @-echo $(URELIBPATH)$/$(DLLPRE)uno_cppuhelper$(COMID)$(UDKDLLPOST) >> $@ + @-echo $(URELIBPATH)$/$(DLLPRE)uno_cppu$(UDKDLLPOST) >> $@ + @-echo $(URELIBPATH)$/$(DLLPRE)uno_sal$(UDKDLLPOST) >> $@ +# + @-echo $(DLLPRE)ucbhelper$(UCBHELPER_MAJOR)$(COMID)$(DLLPOST) >> $@ + @-echo $(DLLPRE)comphelp$(COMPHLP_MAJOR)$(COMID)$(DLLPOST) >> $@ + @-echo $(DLLPRE)tl$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)utl$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)svl$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)vcl$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)tk$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)svt$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)sfx$(DFTDLLPOST) >> $@ + @-echo $(DLLPRE)sofficeapp$(DLLPOST) >> $@ diff --git a/desktop/source/pagein/pagein.c b/desktop/source/pagein/pagein.c new file mode 100644 index 000000000000..15623bfd8d1a --- /dev/null +++ b/desktop/source/pagein/pagein.c @@ -0,0 +1,152 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "file_image.h" + +#include <unistd.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +/* do_pagein */ +static int do_pagein (const char * filename, size_t * size) +{ + int result; + file_image image = FILE_IMAGE_INITIALIZER; + + if ((result = file_image_open (&image, filename)) != 0) + return (result); + + if ((result = file_image_pagein (&image)) != 0) + { + fprintf (stderr, "file_image_pagein: %s\n", strerror(result)); + goto cleanup_and_leave; + } + + if (size) + { + *size = image.m_size; + } + +cleanup_and_leave: + file_image_close (&image); + return (result); +} + +/* main */ +int main (int argc, char **argv) +{ + int i, v = 0; + size_t nfiles = 0, nbytes = 0; + + if (argc < 2) + { + fprintf ( + stderr, + "%s: Usage: pagein [-v[v]] [-L<path>] [@]<filename> ...\n", + argv[0]); + return (1); + } + + for (i = 1; i < argc; i++) + { + FILE * fp = 0; + size_t k = 0; + + if (argv[i][0] == '-') + { + /* option */ + int j = 1; + switch (argv[i][j]) + { + case 'v': + /* verbosity level */ + for (v += 1, j += 1; argv[i][j]; j++) + v += (argv[i][j] == 'v'); + break; + case 'L': + /* search path */ + if (chdir (&(argv[i][2])) == -1) + fprintf (stderr, "chdir: %s\n", strerror(errno)); + break; + default: + /* ignored */ + break; + } + + /* next argv */ + continue; + } + + + if ((argv[i][0] == '@') && ((fp = fopen (argv[i], "r")) == 0)) + { + char path[1024]; + if ((fp = fopen (&(argv[i][1]), "r")) == 0) + { + fprintf (stderr, "fopen: %s\n", strerror(errno)); + continue; + } + while (fgets (path, sizeof(path), fp) != 0) + { + path[strlen(path) - 1] = '\0', k = 0; + if (do_pagein (path, &k) == 0) + { + /* accumulate total size */ + nbytes += k; + } + + if (v >= 2) + fprintf (stderr, "pagein(\"%s\") = %d bytes\n", path, (int) k); + nfiles += 1; + } + fclose (fp); + } + else + { + if (fp != 0) + fclose (fp); + + if (do_pagein (argv[i], &k) == 0) + { + /* accumulate total size */ + nbytes += k; + } + + if (v >= 2) + fprintf (stderr, "pagein(\"%s\") = %d bytes\n", argv[i], (int) k); + nfiles += 1; + } + } + + if (v >= 1) + fprintf (stderr, "Total: %d files (%d bytes)\n", (int) nfiles, (int) nbytes); + return (0); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/pkgchk/unopkg/makefile.mk b/desktop/source/pkgchk/unopkg/makefile.mk new file mode 100644 index 000000000000..8384f1b24372 --- /dev/null +++ b/desktop/source/pkgchk/unopkg/makefile.mk @@ -0,0 +1,104 @@ +#************************************************************************* +# +# 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 = unopkg +.IF "$(GUI)" == "OS2" +TARGETTYPE = CUI +.ELSE +TARGETTYPE = GUI +.ENDIF +ENABLE_EXCEPTIONS = TRUE +LIBTARGET=NO + +PRJINC += ..$/..$/deployment ..$/.. +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/source$/deployment$/inc$/dp_misc.mk + +.IF "$(SYSTEM_DB)" == "YES" +CFLAGS+=-DSYSTEM_DB -I$(DB_INCLUDES) +.ENDIF + +.IF "$(LINK_SO)"!="" +APP1TARGET = so$/unopkg +APP1OBJS = $(OBJFILES) +APP1STDLIBS = $(SALLIB) $(UNOPKGAPPLIB) +APP1DEPN = $(SHL1TARGETN) +APP1NOSAL = TRUE +APP1RPATH = BRAND +.IF "$(OS)" == "WNT" +APP1ICON = $(SOLARRESDIR)$/icons/so9_main_app.ico +APP1LINKRES = $(MISC)$/$(TARGET)1.res +.ENDIF +.ENDIF # "$(LINK_SO)"!="" + +APP2TARGET = unopkg +APP2OBJS = $(OBJFILES) +APP2STDLIBS = $(SALLIB) $(UNOPKGAPPLIB) +APP2DEPN = $(SHL1TARGETN) +APP2NOSAL = TRUE +APP2RPATH = BRAND +.IF "$(OS)" == "WNT" +APP2ICON = $(SOLARRESDIR)$/icons/ooo3_main_app.ico +APP2LINKRES = $(MISC)$/$(TARGET)2.res +.ENDIF + +SHL1TARGET = unopkgapp +SHL1OBJS = $(SLOFILES) $(SLO)$/lockfile.obj +SHL1STDLIBS = \ + $(SALLIB) \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(COMPHELPERLIB) \ + $(UCBHELPERLIB) \ + $(UNOTOOLSLIB) \ + $(TOOLSLIB) \ + $(VCLLIB) \ + $(DEPLOYMENTMISCLIB) +SHL1VERSIONMAP = version.map +SHL1IMPLIB = i$(SHL1TARGET) +DEF1NAME = $(SHL1TARGET) + +SLOFILES = \ + $(SLO)$/unopkg_app.obj \ + $(SLO)$/unopkg_cmdenv.obj \ + $(SLO)$/unopkg_misc.obj + +OBJFILES = $(OBJ)$/unopkg_main.obj + +.INCLUDE : target.mk + +.IF "$(APP1TARGETN)" != "" # not set during depend=x +$(APP1TARGETN) : $(MISC)$/binso_created.flg +.ENDIF # "$(APP1TARGETN)"!="" + +$(MISC)$/binso_created.flg: + @@-$(MKDIRHIER) $(BIN)$/so && $(TOUCH) $@ + @@-$(MKDIRHIER) $(MISC)$/so && $(TOUCH) $@ + diff --git a/desktop/source/pkgchk/unopkg/unopkg_app.cxx b/desktop/source/pkgchk/unopkg/unopkg_app.cxx new file mode 100644 index 000000000000..de8c13bcf7c3 --- /dev/null +++ b/desktop/source/pkgchk/unopkg/unopkg_app.cxx @@ -0,0 +1,692 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_misc.h" +#include "unopkg_main.h" +#include "unopkg_shared.h" +#include "dp_identifier.hxx" +#include "sal/main.h" +#include "tools/extendapplicationenvironment.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/uri.hxx" +#include "rtl/bootstrap.hxx" +#include "osl/thread.h" +#include "osl/process.h" +#include "osl/conditn.hxx" +#include "osl/file.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "comphelper/anytostring.hxx" +#include "comphelper/sequence.hxx" +#include "com/sun/star/deployment/ExtensionManager.hpp" + +#include "com/sun/star/deployment/ui/PackageManagerDialog.hpp" +#include "com/sun/star/ui/dialogs/XExecutableDialog.hpp" +#include "com/sun/star/lang/DisposedException.hpp" +#include "boost/scoped_array.hpp" +#include "com/sun/star/ui/dialogs/XDialogClosedListener.hpp" +#include "com/sun/star/bridge/XBridgeFactory.hpp" +#include <stdio.h> +#include <vector> + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::unopkg; +using ::rtl::OUString; +namespace css = ::com::sun::star; +namespace { + +struct ExtensionName +{ + OUString m_str; + ExtensionName( OUString const & str ) : m_str( str ) {} + bool operator () ( Reference<deployment::XPackage> const & e ) const + { + if (m_str.equals(dp_misc::getIdentifier(e)) + || m_str.equals(e->getName())) + return true; + return false; + } +}; + +//------------------------------------------------------------------------------ +const char s_usingText [] = +"\n" +"using: " APP_NAME " add <options> extension-path...\n" +" " APP_NAME " validate <options> extension-identifier...\n" +" " APP_NAME " remove <options> extension-identifier...\n" +" " APP_NAME " list <options> extension-identifier...\n" +" " APP_NAME " reinstall <options>\n" +" " APP_NAME " gui\n" +" " APP_NAME " -V\n" +" " APP_NAME " -h\n" +"\n" +"sub-commands:\n" +" add add extension\n" +" validate checks the prerequisites of an installed extension and" +" registers it if possible\n" +" remove remove extensions by identifier\n" +" reinstall expert feature: reinstall all deployed extensions\n" +" list list information about deployed extensions\n" +" gui raise Extension Manager Graphical User Interface (GUI)\n" +"\n" +"options:\n" +" -h, --help this help\n" +" -V, --version version information\n" +" -v, --verbose verbose output to stdout\n" +" -f, --force force overwriting existing extensions\n" +" -s, --suppress-license prevents showing the license\n" +" --log-file <file> custom log file; default: <cache-dir>/log.txt\n" +" --shared expert feature: operate on shared installation\n" +" deployment context;\n" +" run only when no concurrent Office\n" +" process(es) are running!\n" +" --bundled expert feature: operate on bundled extensions. Only\n" +" works with list, validate, reinstall;\n" +" --deployment-context expert feature: explicit deployment context\n" +" <context>\n" +"\n" +"To learn more about the Extension Manager and extensions, see:\n" +"http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/Extensions/Extensions\n\n"; + +//------------------------------------------------------------------------------ +const OptionInfo s_option_infos [] = { + { RTL_CONSTASCII_STRINGPARAM("help"), 'h', false }, + { RTL_CONSTASCII_STRINGPARAM("version"), 'V', false }, + { RTL_CONSTASCII_STRINGPARAM("verbose"), 'v', false }, + { RTL_CONSTASCII_STRINGPARAM("force"), 'f', false }, + { RTL_CONSTASCII_STRINGPARAM("log-file"), '\0', true }, + { RTL_CONSTASCII_STRINGPARAM("shared"), '\0', false }, + { RTL_CONSTASCII_STRINGPARAM("deployment-context"), '\0', true }, + { RTL_CONSTASCII_STRINGPARAM("bundled"), '\0', false}, + { RTL_CONSTASCII_STRINGPARAM("suppress-license"), 's', false}, + + { 0, 0, '\0', false } +}; + +class DialogClosedListenerImpl : + public ::cppu::WeakImplHelper1< ui::dialogs::XDialogClosedListener > +{ + osl::Condition & m_rDialogClosedCondition; + +public: + DialogClosedListenerImpl( osl::Condition & rDialogClosedCondition ) + : m_rDialogClosedCondition( rDialogClosedCondition ) {} + + // XEventListener (base of XDialogClosedListener) + virtual void SAL_CALL disposing( lang::EventObject const & Source ) + throw (RuntimeException); + + // XDialogClosedListener + virtual void SAL_CALL dialogClosed( + ui::dialogs::DialogClosedEvent const & aEvent ) + throw (RuntimeException); +}; + +// XEventListener (base of XDialogClosedListener) +void DialogClosedListenerImpl::disposing( lang::EventObject const & ) + throw (RuntimeException) +{ + // nothing to do +} + +// XDialogClosedListener +void DialogClosedListenerImpl::dialogClosed( + ui::dialogs::DialogClosedEvent const & ) + throw (RuntimeException) +{ + m_rDialogClosedCondition.set(); +} + +// If a package had been installed with a pre OOo 2.2, it could not normally be +// found via its identifier; similarly (and for ease of use), a package +// installed with OOo 2.2 or later could not normally be found via its file +// name. +Reference<deployment::XPackage> findPackage( + OUString const & repository, + Reference<deployment::XExtensionManager> const & manager, + Reference<ucb::XCommandEnvironment > const & environment, + OUString const & idOrFileName ) +{ + Sequence< Reference<deployment::XPackage> > ps( + manager->getDeployedExtensions(repository, + Reference<task::XAbortChannel>(), environment ) ); + for ( sal_Int32 i = 0; i < ps.getLength(); ++i ) + if ( dp_misc::getIdentifier( ps[i] ) == idOrFileName ) + return ps[i]; + for ( sal_Int32 i = 0; i < ps.getLength(); ++i ) + if ( ps[i]->getName() == idOrFileName ) + return ps[i]; + return Reference<deployment::XPackage>(); +} + +} // anon namespace + + +//workaround for some reason the bridge threads which communicate with the uno.exe +//process are not releases on time +void disposeBridges(Reference<css::uno::XComponentContext> ctx) +{ + if (!ctx.is()) + return; + + Reference<css::bridge::XBridgeFactory> bridgeFac( + ctx->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.bridge.BridgeFactory"), ctx), + UNO_QUERY); + + if (bridgeFac.is()) + { + const Sequence< Reference<css::bridge::XBridge> >seqBridges = bridgeFac->getExistingBridges(); + for (sal_Int32 i = 0; i < seqBridges.getLength(); i++) + { + Reference<css::lang::XComponent> comp(seqBridges[i], UNO_QUERY); + if (comp.is()) + { + try { + comp->dispose(); + } + catch (css::lang::DisposedException& ) + { + } + } + } + } +} + +//############################################################################## +extern "C" int unopkg_main() +{ + tools::extendApplicationEnvironment(); + DisposeGuard disposeGuard; + bool bNoOtherErrorMsg = false; + OUString subCommand; + bool option_shared = false; + bool option_force = false; + bool option_verbose = false; + bool option_bundled = false; + bool option_suppressLicense = false; + bool subcmd_add = false; + bool subcmd_gui = false; + OUString logFile; + OUString repository; + OUString cmdArg; + ::std::vector<OUString> cmdPackages; + + OptionInfo const * info_shared = getOptionInfo( + s_option_infos, OUSTR("shared") ); + OptionInfo const * info_force = getOptionInfo( + s_option_infos, OUSTR("force") ); + OptionInfo const * info_verbose = getOptionInfo( + s_option_infos, OUSTR("verbose") ); + OptionInfo const * info_log = getOptionInfo( + s_option_infos, OUSTR("log-file") ); + OptionInfo const * info_context = getOptionInfo( + s_option_infos, OUSTR("deployment-context") ); + OptionInfo const * info_help = getOptionInfo( + s_option_infos, OUSTR("help") ); + OptionInfo const * info_version = getOptionInfo( + s_option_infos, OUSTR("version") ); + OptionInfo const * info_bundled = getOptionInfo( + s_option_infos, OUSTR("bundled") ); + OptionInfo const * info_suppressLicense = getOptionInfo( + s_option_infos, OUSTR("suppress-license") ); + + + Reference<XComponentContext> xComponentContext; + Reference<XComponentContext> xLocalComponentContext; + + try { + sal_uInt32 nPos = 0; + sal_uInt32 nCount = osl_getCommandArgCount(); + if (nCount == 0 || isOption( info_help, &nPos )) + { + dp_misc::writeConsole(s_usingText); + return 0; + } + else if (isOption( info_version, &nPos )) { + dp_misc::writeConsole("\n"APP_NAME" Version 3.3\n"); + return 0; + } + //consume all bootstrap variables which may occur before the subcommannd + while(isBootstrapVariable(&nPos)); + + if(nPos >= nCount) + return 0; + //get the sub command + osl_getCommandArg( nPos, &subCommand.pData ); + ++nPos; + subCommand = subCommand.trim(); + subcmd_add = subCommand.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("add") ); + subcmd_gui = subCommand.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("gui") ); + + // sun-command options and packages: + while (nPos < nCount) + { + if (readArgument( &cmdArg, info_log, &nPos )) { + logFile = makeAbsoluteFileUrl( + cmdArg.trim(), getProcessWorkingDir() ); + } + else if (!readOption( &option_verbose, info_verbose, &nPos ) && + !readOption( &option_shared, info_shared, &nPos ) && + !readOption( &option_force, info_force, &nPos ) && + !readOption( &option_bundled, info_bundled, &nPos ) && + !readOption( &option_suppressLicense, info_suppressLicense, &nPos ) && + !readArgument( &repository, info_context, &nPos ) && + !isBootstrapVariable(&nPos)) + { + osl_getCommandArg( nPos, &cmdArg.pData ); + ++nPos; + cmdArg = cmdArg.trim(); + if (cmdArg.getLength() > 0) + { + if (cmdArg[ 0 ] == '-') + { + // is option: + dp_misc::writeConsoleError( + OUSTR("\nERROR: unexpected option ") + + cmdArg + + OUSTR("!\n") + + OUSTR(" Use " APP_NAME " ") + + toString(info_help) + + OUSTR(" to print all options.\n")); + return 1; + } + else + { + // is package: + cmdPackages.push_back( + subcmd_add || subcmd_gui + ? makeAbsoluteFileUrl( + cmdArg, getProcessWorkingDir() ) + : cmdArg ); + } + } + } + } + + if (repository.getLength() == 0) + { + if (option_shared) + repository = OUSTR("shared"); + else if (option_bundled) + repository = OUSTR("bundled"); + else + repository = OUSTR("user"); + } + else + { + if (repository.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("shared") )) { + option_shared = true; + } + else if (option_shared) { + dp_misc::writeConsoleError( + OUSTR("WARNING: explicit context given! ") + + OUSTR("Ignoring option ") + + toString( info_shared ) + + OUSTR("!\n") ); + } + } + + if (subCommand.equals(OUSTR("reinstall"))) + { + //We must prevent that services and types are loaded by UNO, + //otherwise we cannot delete the registry data folder. + OUString extensionUnorc; + if (repository.equals(OUSTR("user"))) + extensionUnorc = OUSTR("$UNO_USER_PACKAGES_CACHE/registry/com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc"); + else if (repository.equals(OUSTR("shared"))) + extensionUnorc = OUSTR("$SHARED_EXTENSIONS_USER/registry/com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc"); + else if (repository.equals(OUSTR("bundled"))) + extensionUnorc = OUSTR("$BUNDLED_EXTENSIONS_USER/registry/com.sun.star.comp.deployment.component.PackageRegistryBackend/unorc"); + else + OSL_ASSERT(0); + + ::rtl::Bootstrap::expandMacros(extensionUnorc); + oslFileError e = osl_removeFile(extensionUnorc.pData); + if (e != osl_File_E_None && e != osl_File_E_NOENT) + throw Exception(OUSTR("Could not delete ") + extensionUnorc, 0); + } + else if (subCommand.equals(OUSTR("sync"))) + { + //sync is private!!!! Only for bundled extensions!!! + //For performance reasons unopkg sync is called during the setup and + //creates the registration data for the repository of the bundled + //extensions. It is then copied to the user installation during + //startup of OOo (userdata/extensions/bundled). The registration + //data is in the brand installation and must be removed when + //uninstalling OOo. We do this here, before UNO is + //bootstrapped. Otherwies files could be locked by this process. + + //If there is no folder left in + //$BRAND_BASE_DIR/share/extensions + //then we can delete the registration data at + //$BUNDLED_EXTENSIONS_USER + if (hasNoFolder(OUSTR("$BRAND_BASE_DIR/share/extensions"))) + { + removeFolder(OUSTR("$BUNDLED_EXTENSIONS_USER")); + //return otherwise we create the registration data again + return 0; + } + + } + + xComponentContext = getUNO( + disposeGuard, option_verbose, option_shared, subcmd_gui, + xLocalComponentContext ); + + Reference<deployment::XExtensionManager> xExtensionManager( + deployment::ExtensionManager::get( xComponentContext ) ); + + Reference< ::com::sun::star::ucb::XCommandEnvironment > xCmdEnv( + createCmdEnv( xComponentContext, logFile, + option_force, option_verbose, option_suppressLicense) ); + + //synchronize bundled/shared extensions + //Do not synchronize when command is "reinstall". This could add types and services to UNO and + //prevent the deletion of the registry data folder + //synching is done in XExtensionManager.reinstall + if (!subcmd_gui && ! subCommand.equals(OUSTR("reinstall")) + && ! dp_misc::office_is_running()) + dp_misc::syncRepositories(xCmdEnv); + + if (subcmd_add || + subCommand.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("remove") )) + { + for ( ::std::size_t pos = 0; pos < cmdPackages.size(); ++pos ) + { + OUString const & cmdPackage = cmdPackages[ pos ]; + if (subcmd_add) + { + beans::NamedValue nvSuppress( + OUSTR("SUPPRESS_LICENSE"), option_suppressLicense ? + makeAny(OUSTR("1")):makeAny(OUSTR("0"))); + xExtensionManager->addExtension( + cmdPackage, Sequence<beans::NamedValue>(&nvSuppress, 1), + repository, Reference<task::XAbortChannel>(), xCmdEnv); + } + else + { + try + { + xExtensionManager->removeExtension( + cmdPackage, cmdPackage, repository, + Reference<task::XAbortChannel>(), xCmdEnv ); + } + catch (lang::IllegalArgumentException &) + { + Reference<deployment::XPackage> p( + findPackage(repository, + xExtensionManager, xCmdEnv, cmdPackage ) ); + if ( !p.is()) + throw; + else if (p.is()) + xExtensionManager->removeExtension( + ::dp_misc::getIdentifier(p), p->getName(), + repository, + Reference<task::XAbortChannel>(), xCmdEnv ); + } + } + } + } + else if (subCommand.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("reinstall") )) + { + xExtensionManager->reinstallDeployedExtensions( + repository, Reference<task::XAbortChannel>(), xCmdEnv); + } + else if (subCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("list") )) + { + ::std::vector<Reference<deployment::XPackage> > vecExtUnaccepted; + ::comphelper::sequenceToContainer(vecExtUnaccepted, + xExtensionManager->getExtensionsWithUnacceptedLicenses( + repository, xCmdEnv)); + + //This vector tells what XPackage in allExtensions has an + //unaccepted license. + std::vector<bool> vecUnaccepted; + std::vector<Reference<deployment::XPackage> > allExtensions; + if (cmdPackages.empty()) + { + Sequence< Reference<deployment::XPackage> > + packages = xExtensionManager->getDeployedExtensions( + repository, Reference<task::XAbortChannel>(), xCmdEnv ); + + ::std::vector<Reference<deployment::XPackage> > vec_packages; + ::comphelper::sequenceToContainer(vec_packages, packages); + + //First copy the extensions with the unaccepted license + //to vector allExtensions. + allExtensions.resize(vecExtUnaccepted.size() + vec_packages.size()); + + ::std::vector<Reference<deployment::XPackage> >::iterator i_all_ext = + ::std::copy(vecExtUnaccepted.begin(), vecExtUnaccepted.end(), + allExtensions.begin()); + //Now copy those we got from getDeployedExtensions + ::std::copy(vec_packages.begin(), vec_packages.end(), i_all_ext); + + //Now prepare the vector which tells what extension has an + //unaccepted license + vecUnaccepted.resize(vecExtUnaccepted.size() + vec_packages.size()); + ::std::vector<bool>::iterator i_unaccepted = + ::std::fill_n(vecUnaccepted.begin(), + vecExtUnaccepted.size(), true); + ::std::fill_n(i_unaccepted, vec_packages.size(), false); + + dp_misc::writeConsole( + OUSTR("All deployed ") + repository + OUSTR(" extensions:\n\n")); + } + else + { + //The user provided the names (ids or file names) of the extensions + //which shall be listed + for ( ::std::size_t pos = 0; pos < cmdPackages.size(); ++pos ) + { + Reference<deployment::XPackage> extension; + try + { + extension = xExtensionManager->getDeployedExtension( + repository, cmdPackages[ pos ], cmdPackages[ pos ], xCmdEnv ); + } + catch (lang::IllegalArgumentException &) + { + extension = findPackage(repository, + xExtensionManager, xCmdEnv, cmdPackages[ pos ] ); + } + + //Now look if the requested extension has an unaccepted license + bool bUnacceptedLic = false; + if (!extension.is()) + { + ::std::vector<Reference<deployment::XPackage> >::const_iterator + i = ::std::find_if( + vecExtUnaccepted.begin(), + vecExtUnaccepted.end(), ExtensionName(cmdPackages[pos])); + if (i != vecExtUnaccepted.end()) + { + extension = *i; + bUnacceptedLic = true; + } + } + + if (extension.is()) + { + allExtensions.push_back(extension); + vecUnaccepted.push_back(bUnacceptedLic); + } + + else + throw lang::IllegalArgumentException( + OUSTR("There is no such extension deployed: ") + + cmdPackages[pos],0,-1); + } + + } + + printf_packages(allExtensions, vecUnaccepted, xCmdEnv ); + } + else if (subCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("validate") )) + { + ::std::vector<Reference<deployment::XPackage> > vecExtUnaccepted; + ::comphelper::sequenceToContainer( + vecExtUnaccepted, xExtensionManager->getExtensionsWithUnacceptedLicenses( + repository, xCmdEnv)); + + for ( ::std::size_t pos = 0; pos < cmdPackages.size(); ++pos ) + { + Reference<deployment::XPackage> extension; + try + { + extension = xExtensionManager->getDeployedExtension( + repository, cmdPackages[ pos ], cmdPackages[ pos ], xCmdEnv ); + } + catch (lang::IllegalArgumentException &) + { + extension = findPackage( + repository, xExtensionManager, xCmdEnv, cmdPackages[ pos ] ); + } + + if (!extension.is()) + { + ::std::vector<Reference<deployment::XPackage> >::const_iterator + i = ::std::find_if( + vecExtUnaccepted.begin(), + vecExtUnaccepted.end(), ExtensionName(cmdPackages[pos])); + if (i != vecExtUnaccepted.end()) + { + extension = *i; + } + } + + if (extension.is()) + xExtensionManager->checkPrerequisitesAndEnable( + extension, Reference<task::XAbortChannel>(), xCmdEnv); + } + } + else if (subCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("gui") )) + { + Reference<ui::dialogs::XAsynchronousExecutableDialog> xDialog( + deployment::ui::PackageManagerDialog::createAndInstall( + xComponentContext, + cmdPackages.size() > 0 ? cmdPackages[0] : OUString() )); + + osl::Condition dialogEnded; + dialogEnded.reset(); + + Reference< ui::dialogs::XDialogClosedListener > xListener( + new DialogClosedListenerImpl( dialogEnded ) ); + + xDialog->startExecuteModal(xListener); + dialogEnded.wait(); + } + else if (subCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("sync"))) + { + //This sub command may be removed later and is only there to have a + //possibility to start extension synching without any output. + //This is just here so we do not get an error, because of an unknown + //sub-command. We do synching before + //the sub-commands are processed. + + } + else + { + dp_misc::writeConsoleError( + OUSTR("\nERROR: unknown sub-command ") + + subCommand + + OUSTR("!\n") + + OUSTR(" Use " APP_NAME " ") + + toString(info_help) + + OUSTR(" to print all options.\n")); + return 1; + } + + if (option_verbose) + dp_misc::writeConsole(OUSTR("\n"APP_NAME" done.\n")); + //Force to release all bridges which connect us to the child processes + disposeBridges(xLocalComponentContext); + return 0; + } + catch (ucb::CommandFailedException &e) + { + dp_misc::writeConsoleError(e.Message + OUSTR("\n")); + bNoOtherErrorMsg = true; + } + catch (ucb::CommandAbortedException &) + { + dp_misc::writeConsoleError("\n"APP_NAME" aborted!\n"); + } + catch (deployment::DeploymentException & exc) + { + OUString cause; + if (option_verbose) + { + cause = ::comphelper::anyToString(exc.Cause); + } + else + { + css::uno::Exception e; + if (exc.Cause >>= e) + cause = e.Message; + } + + dp_misc::writeConsoleError( + OUSTR("\nERROR: ") + exc.Message + OUSTR("\n")); + if (cause.getLength()) + dp_misc::writeConsoleError( + OUSTR(" Cause: ") + cause + OUSTR("\n")); + } + catch (LockFileException & e) + { + if (!subcmd_gui) + dp_misc::writeConsoleError(e.Message); + bNoOtherErrorMsg = true; + } + catch (::com::sun::star::uno::Exception & e ) { + Any exc( ::cppu::getCaughtException() ); + + dp_misc::writeConsoleError( + OUSTR("\nERROR: ") + + OUString(option_verbose ? e.Message + OUSTR("\nException details: \n") + + ::comphelper::anyToString(exc) : e.Message) + + OUSTR("\n")); + } + if (!bNoOtherErrorMsg) + dp_misc::writeConsoleError("\n"APP_NAME" failed.\n"); + disposeBridges(xLocalComponentContext); + return 1; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/pkgchk/unopkg/unopkg_cmdenv.cxx b/desktop/source/pkgchk/unopkg/unopkg_cmdenv.cxx new file mode 100644 index 000000000000..c6d26b1df1ef --- /dev/null +++ b/desktop/source/pkgchk/unopkg/unopkg_cmdenv.cxx @@ -0,0 +1,446 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "../../deployment/gui/dp_gui.hrc" +#include "../../deployment/gui/dp_gui_shared.hxx" +#include "unopkg_shared.h" +#include "osl/thread.h" +#include "rtl/memory.h" +#include "tools/string.hxx" +#include "tools/resmgr.hxx" +#include "cppuhelper/implbase3.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "comphelper/anytostring.hxx" +#include "unotools/configmgr.hxx" +#include "com/sun/star/lang/WrappedTargetException.hpp" +#include "com/sun/star/task/XInteractionAbort.hpp" +#include "com/sun/star/task/XInteractionApprove.hpp" +#include "com/sun/star/deployment/InstallException.hpp" +#include "com/sun/star/container/ElementExistException.hpp" +#include "com/sun/star/deployment/LicenseException.hpp" +#include "com/sun/star/deployment/VersionException.hpp" +#include "com/sun/star/deployment/PlatformException.hpp" +#include "com/sun/star/i18n/XCollator.hpp" +#include "com/sun/star/i18n/CollatorOptions.hpp" + +#include <stdio.h> +#include "deployment.hrc" +#include "dp_version.hxx" + +namespace css = ::com::sun::star; +using namespace ::com::sun::star; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::uno; +using namespace ::unopkg; +using ::rtl::OUString; + + +namespace { + +//============================================================================== +struct OfficeLocale : + public rtl::StaticWithInit<const lang::Locale, OfficeLocale> { + const lang::Locale operator () () { + OUString slang; + if (! (::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::LOCALE ) >>= slang)) + throw RuntimeException( OUSTR("Cannot determine language!"), 0 ); + return toLocale(slang); + } +}; + +//============================================================================== +class CommandEnvironmentImpl + : public ::cppu::WeakImplHelper3< XCommandEnvironment, + task::XInteractionHandler, + XProgressHandler > +{ + sal_Int32 m_logLevel; + bool m_option_force_overwrite; + bool m_option_verbose; + bool m_option_suppress_license; + Reference< XComponentContext > m_xComponentContext; + Reference< XProgressHandler > m_xLogFile; + + void update_( Any const & Status ) throw (RuntimeException); + void printLicense(const OUString & sName,const OUString& sLicense, + bool & accept, bool & decline); + +public: + virtual ~CommandEnvironmentImpl(); + CommandEnvironmentImpl( + Reference<XComponentContext> const & xComponentContext, + OUString const & log_file, + bool option_force_overwrite, + bool option_verbose, + bool option_suppress_license); + + // XCommandEnvironment + virtual Reference< task::XInteractionHandler > SAL_CALL + getInteractionHandler() throw (RuntimeException); + virtual Reference< XProgressHandler > SAL_CALL getProgressHandler() + throw (RuntimeException); + + // XInteractionHandler + virtual void SAL_CALL handle( + Reference< task::XInteractionRequest > const & xRequest ) + throw (RuntimeException); + + // XProgressHandler + virtual void SAL_CALL push( Any const & Status ) throw (RuntimeException); + virtual void SAL_CALL update( Any const & Status ) throw (RuntimeException); + virtual void SAL_CALL pop() throw (RuntimeException); +}; + + +//______________________________________________________________________________ +CommandEnvironmentImpl::CommandEnvironmentImpl( + Reference<XComponentContext> const & xComponentContext, + OUString const & log_file, + bool option_force_overwrite, + bool option_verbose, + bool option_suppressLicense) + : m_logLevel(0), + m_option_force_overwrite( option_force_overwrite ), + m_option_verbose( option_verbose ), + m_option_suppress_license( option_suppressLicense ), + m_xComponentContext(xComponentContext) +{ + if (log_file.getLength() > 0) { + const Any logfile(log_file); + m_xLogFile.set( + xComponentContext->getServiceManager() + ->createInstanceWithArgumentsAndContext( + OUSTR("com.sun.star.comp.deployment.ProgressLog"), + Sequence<Any>( &logfile, 1 ), xComponentContext ), + UNO_QUERY_THROW ); + } +} + +//______________________________________________________________________________ +CommandEnvironmentImpl::~CommandEnvironmentImpl() +{ + try { + Reference< lang::XComponent > xComp( m_xLogFile, UNO_QUERY ); + if (xComp.is()) + xComp->dispose(); + } + catch (RuntimeException & exc) { + (void) exc; + OSL_ENSURE( 0, ::rtl::OUStringToOString( + exc.Message, osl_getThreadTextEncoding() ).getStr() ); + } +} + +//May throw exceptions +void CommandEnvironmentImpl::printLicense( + const OUString & sName, const OUString& sLicense, bool & accept, bool &decline) +{ + ResMgr * pResMgr = DeploymentResMgr::get(); + String s1tmp(ResId(RID_STR_UNOPKG_ACCEPT_LIC_1, *pResMgr)); + s1tmp.SearchAndReplaceAllAscii( "$NAME", sName ); + OUString s1(s1tmp); + OUString s2 = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_2, *pResMgr)); + OUString s3 = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_3, *pResMgr)); + OUString s4 = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_4, *pResMgr)); + OUString sYES = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_YES, *pResMgr)); + OUString sY = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_Y, *pResMgr)); + OUString sNO = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_NO, *pResMgr)); + OUString sN = String(ResId(RID_STR_UNOPKG_ACCEPT_LIC_N, *pResMgr)); + + OUString sNewLine(RTL_CONSTASCII_USTRINGPARAM("\n")); + + dp_misc::writeConsole(sNewLine + sNewLine + s1 + sNewLine + sNewLine); + dp_misc::writeConsole(sLicense + sNewLine + sNewLine); + dp_misc::writeConsole(s2 + sNewLine); + dp_misc::writeConsole(s3); + + //the user may enter "yes" or "no", we compare in a case insensitive way + Reference< css::i18n::XCollator > xCollator( + m_xComponentContext->getServiceManager() + ->createInstanceWithContext( + OUSTR("com.sun.star.i18n.Collator"),m_xComponentContext), + UNO_QUERY_THROW ); + xCollator->loadDefaultCollator(OfficeLocale::get(), + css::i18n::CollatorOptions::CollatorOptions_IGNORE_CASE); + + do + { + OUString sAnswer = dp_misc::readConsole(); + if (xCollator->compareString(sAnswer, sYES) == 0 + || xCollator->compareString(sAnswer, sY) == 0) + { + accept = true; + break; + } + else if(xCollator->compareString(sAnswer, sNO) == 0 + || xCollator->compareString(sAnswer, sN) == 0) + { + decline = true; + break; + } + else + { + dp_misc::writeConsole(sNewLine + sNewLine + s4 + sNewLine); + } + } + while(true); +} + +// XCommandEnvironment +//______________________________________________________________________________ +Reference< task::XInteractionHandler > +CommandEnvironmentImpl::getInteractionHandler() throw (RuntimeException) +{ + return this; +} + +//______________________________________________________________________________ +Reference< XProgressHandler > CommandEnvironmentImpl::getProgressHandler() + throw (RuntimeException) +{ + return this; +} + +// XInteractionHandler +//______________________________________________________________________________ +void CommandEnvironmentImpl::handle( + Reference<task::XInteractionRequest> const & xRequest ) + throw (RuntimeException) +{ + Any request( xRequest->getRequest() ); + OSL_ASSERT( request.getValueTypeClass() == TypeClass_EXCEPTION ); + dp_misc::TRACE(OUSTR("[unopkg_cmdenv.cxx] incoming request:\n") + + ::comphelper::anyToString(request) + OUSTR("\n\n")); + + // selections: + bool approve = false; + bool abort = false; + + lang::WrappedTargetException wtExc; + deployment::LicenseException licExc; + deployment::InstallException instExc; + deployment::PlatformException platExc; + deployment::VersionException verExc; + + + bool bLicenseException = false; + if (request >>= wtExc) { + // ignore intermediate errors of legacy packages, i.e. + // former pkgchk behaviour: + const Reference<deployment::XPackage> xPackage( + wtExc.Context, UNO_QUERY ); + OSL_ASSERT( xPackage.is() ); + if (xPackage.is()) { + const Reference<deployment::XPackageTypeInfo> xPackageType( + xPackage->getPackageType() ); + OSL_ASSERT( xPackageType.is() ); + if (xPackageType.is()) { + approve = (xPackage->isBundle() && + xPackageType->getMediaType().matchAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "application/" + "vnd.sun.star.legacy-package-bundle") )); + } + } + abort = !approve; + if (abort) { + // notify cause as error: + request = wtExc.TargetException; + } + else { + // handable deployment error signalled, e.g. + // bundle item registration failed, notify as warning: + update_( wtExc.TargetException ); + } + } + else if (request >>= licExc) + { + if ( !m_option_suppress_license ) + printLicense(licExc.ExtensionName, licExc.Text, approve, abort); + else + { + approve = true; + abort = false; + } + } + else if (request >>= instExc) + { + //Only if the unopgk was started with gui + extension then we user is asked. + //In console mode there is no asking. + approve = true; + } + else if (request >>= platExc) + { + String sMsg(ResId(RID_STR_UNSUPPORTED_PLATFORM, *dp_gui::DeploymentGuiResMgr::get())); + sMsg.SearchAndReplaceAllAscii("%Name", platExc.package->getDisplayName()); + dp_misc::writeConsole(OUSTR("\n") + sMsg + OUSTR("\n\n")); + approve = true; + } + else { + deployment::VersionException nc_exc; + if (request >>= nc_exc) { + approve = m_option_force_overwrite || + (::dp_misc::compareVersions(nc_exc.NewVersion, nc_exc.Deployed->getVersion()) + == ::dp_misc::GREATER); + abort = !approve; + } + else + return; // unknown request => no selection at all + } + + //In case of a user declining a license abort is true but this is intended, + //therefore no logging + if (abort && m_option_verbose && !bLicenseException) + { + OUString msg = ::comphelper::anyToString(request); + dp_misc::writeConsoleError( + OUSTR("\nERROR: ") + msg + OUSTR("\n")); + } + + // select: + 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 (approve) { + Reference<task::XInteractionApprove> xInteractionApprove( + pConts[ pos ], UNO_QUERY ); + if (xInteractionApprove.is()) { + xInteractionApprove->select(); + break; + } + } + else if (abort) { + Reference<task::XInteractionAbort> xInteractionAbort( + pConts[ pos ], UNO_QUERY ); + if (xInteractionAbort.is()) { + xInteractionAbort->select(); + break; + } + } + } +} + +// XProgressHandler +//______________________________________________________________________________ +void CommandEnvironmentImpl::push( Any const & Status ) + throw (RuntimeException) +{ + update_( Status ); + OSL_ASSERT( m_logLevel >= 0 ); + ++m_logLevel; + if (m_xLogFile.is()) + m_xLogFile->push( Status ); +} + +//______________________________________________________________________________ +void CommandEnvironmentImpl::update_( Any const & Status ) + throw (RuntimeException) +{ + if (! Status.hasValue()) + return; + bool bUseErr = false; + OUString msg; + if (Status >>= msg) { + if (! m_option_verbose) + return; + } + else { + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("WARNING: ") ); + deployment::DeploymentException dp_exc; + if (Status >>= dp_exc) { + buf.append( dp_exc.Message ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", Cause: ") ); + buf.append( ::comphelper::anyToString(dp_exc.Cause) ); + } + else { + buf.append( ::comphelper::anyToString(Status) ); + } + msg = buf.makeStringAndClear(); + bUseErr = true; + } + OSL_ASSERT( m_logLevel >= 0 ); + for ( sal_Int32 n = 0; n < m_logLevel; ++n ) + { + if (bUseErr) + dp_misc::writeConsoleError(" "); + else + dp_misc::writeConsole(" "); + } + + if (bUseErr) + dp_misc::writeConsoleError(msg + OUSTR("\n")); + else + dp_misc::writeConsole(msg + OUSTR("\n")); +} + +//______________________________________________________________________________ +void CommandEnvironmentImpl::update( Any const & Status ) + throw (RuntimeException) +{ + update_( Status ); + if (m_xLogFile.is()) + m_xLogFile->update( Status ); +} + +//______________________________________________________________________________ +void CommandEnvironmentImpl::pop() throw (RuntimeException) +{ + OSL_ASSERT( m_logLevel > 0 ); + --m_logLevel; + if (m_xLogFile.is()) + m_xLogFile->pop(); +} + + +} // anon namespace + +namespace unopkg { + +//============================================================================== +Reference< XCommandEnvironment > createCmdEnv( + Reference< XComponentContext > const & xContext, + OUString const & logFile, + bool option_force_overwrite, + bool option_verbose, + bool option_suppress_license) +{ + return new CommandEnvironmentImpl( + xContext, logFile, option_force_overwrite, option_verbose, option_suppress_license); +} +} // unopkg + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/pkgchk/unopkg/unopkg_main.c b/desktop/source/pkgchk/unopkg/unopkg_main.c new file mode 100644 index 000000000000..1d5b31d03f56 --- /dev/null +++ b/desktop/source/pkgchk/unopkg/unopkg_main.c @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "unopkg_main.h" + +SAL_IMPLEMENT_MAIN() { + return unopkg_main(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/pkgchk/unopkg/unopkg_main.h b/desktop/source/pkgchk/unopkg/unopkg_main.h new file mode 100644 index 000000000000..694cc4155813 --- /dev/null +++ b/desktop/source/pkgchk/unopkg/unopkg_main.h @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_PKGCHK_UNOPKG_UNOPKG_MAIN_H +#define INCLUDED_DESKTOP_SOURCE_PKGCHK_UNOPKG_UNOPKG_MAIN_H + +#include "sal/config.h" + +#if defined __cplusplus +extern "C" { +#endif + +int unopkg_main(void); + +#if defined __cplusplus +} +#endif + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/pkgchk/unopkg/unopkg_misc.cxx b/desktop/source/pkgchk/unopkg/unopkg_misc.cxx new file mode 100644 index 000000000000..9b20f572873f --- /dev/null +++ b/desktop/source/pkgchk/unopkg/unopkg_misc.cxx @@ -0,0 +1,641 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "deployment.hrc" +#include "unopkg_shared.h" +#include "dp_identifier.hxx" +#include "../../deployment/gui/dp_gui.hrc" +#include "../../app/lockfile.hxx" +#include "vcl/svapp.hxx" +#include "vcl/msgbox.hxx" +#include "rtl/bootstrap.hxx" +#include "rtl/strbuf.hxx" +#include "rtl/ustrbuf.hxx" +#include "osl/process.h" +#include "osl/file.hxx" +#include "osl/thread.hxx" +#include "tools/getprocessworkingdir.hxx" +#include "ucbhelper/contentbroker.hxx" +#include "ucbhelper/configurationkeys.hxx" +#include "unotools/processfactory.hxx" +#include "unotools/configmgr.hxx" +#include "com/sun/star/lang/XMultiServiceFactory.hpp" +#include "cppuhelper/bootstrap.hxx" +#include "comphelper/sequence.hxx" +#include <stdio.h> + +using ::rtl::OUString; +using ::rtl::OString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; + +namespace unopkg { + +bool getLockFilePath(OUString & out); + +::rtl::OUString toString( OptionInfo const * info ) +{ + OSL_ASSERT( info != 0 ); + ::rtl::OUStringBuffer buf; + buf.appendAscii("--"); + buf.appendAscii(info->m_name); + if (info->m_short_option != '\0') + { + buf.appendAscii(" (short -" ); + buf.append(info->m_short_option ); + buf.appendAscii(")"); + } + if (info->m_has_argument) + buf.appendAscii(" <argument>" ); + return buf.makeStringAndClear(); +} + +//============================================================================== +OptionInfo const * getOptionInfo( + OptionInfo const * list, + OUString const & opt, sal_Unicode copt ) +{ + for ( ; list->m_name != 0; ++list ) + { + OptionInfo const & option_info = *list; + if (opt.getLength() > 0) + { + if (opt.equalsAsciiL( + option_info.m_name, option_info.m_name_length ) && + (copt == '\0' || copt == option_info.m_short_option)) + { + return &option_info; + } + } + else + { + OSL_ASSERT( copt != '\0' ); + if (copt == option_info.m_short_option) + { + return &option_info; + } + } + } + OSL_ENSURE( 0, ::rtl::OUStringToOString( + opt, osl_getThreadTextEncoding() ).getStr() ); + return 0; +} + +//============================================================================== +bool isOption( OptionInfo const * option_info, sal_uInt32 * pIndex ) +{ + OSL_ASSERT( option_info != 0 ); + if (osl_getCommandArgCount() <= *pIndex) + return false; + + OUString arg; + osl_getCommandArg( *pIndex, &arg.pData ); + sal_Int32 len = arg.getLength(); + + if (len < 2 || arg[ 0 ] != '-') + return false; + + if (len == 2 && arg[ 1 ] == option_info->m_short_option) + { + ++(*pIndex); + dp_misc::TRACE(OUSTR(__FILE__": identified option \'") + + OUSTR("\'") + OUString( option_info->m_short_option ) + OUSTR("\n")); + return true; + } + if (arg[ 1 ] == '-' && rtl_ustr_ascii_compare( + arg.pData->buffer + 2, option_info->m_name ) == 0) + { + ++(*pIndex); + dp_misc::TRACE(OUSTR( __FILE__": identified option \'") + + OUString::createFromAscii(option_info->m_name) + OUSTR("\'\n")); + return true; + } + return false; +} +//============================================================================== + +bool isBootstrapVariable(sal_uInt32 * pIndex) +{ + OSL_ASSERT(osl_getCommandArgCount() >= *pIndex); + + OUString arg; + osl_getCommandArg(*pIndex, &arg.pData); + if (arg.matchAsciiL("-env:", 5)) + { + ++(*pIndex); + return true; + } + return false; +} + +//============================================================================== +bool readArgument( + OUString * pValue, OptionInfo const * option_info, sal_uInt32 * pIndex ) +{ + if (isOption( option_info, pIndex )) + { + if (*pIndex < osl_getCommandArgCount()) + { + OSL_ASSERT( pValue != 0 ); + osl_getCommandArg( *pIndex, &pValue->pData ); + dp_misc::TRACE(OUSTR( __FILE__": argument value: ") + + *pValue + OUSTR("\n")); + ++(*pIndex); + return true; + } + --(*pIndex); + } + return false; +} + +//############################################################################## + +namespace { +struct ExecutableDir : public rtl::StaticWithInit< + const OUString, ExecutableDir> { + const OUString operator () () { + OUString path; + if (osl_getExecutableFile( &path.pData ) != osl_Process_E_None) { + throw RuntimeException( + OUSTR("cannot locate executable directory!"),0 ); + } + return path.copy( 0, path.lastIndexOf( '/' ) ); + } +}; +struct ProcessWorkingDir : public rtl::StaticWithInit< + const OUString, ProcessWorkingDir> { + const OUString operator () () { + OUString workingDir; + tools::getProcessWorkingDir(&workingDir); + return workingDir; + } +}; +} // anon namespace + +//============================================================================== +OUString const & getExecutableDir() +{ + return ExecutableDir::get(); +} + +//============================================================================== +OUString const & getProcessWorkingDir() +{ + return ProcessWorkingDir::get(); +} + +//============================================================================== +OUString makeAbsoluteFileUrl( + OUString const & sys_path, OUString const & base_url, bool throw_exc ) +{ + // system path to file url + OUString file_url; + oslFileError rc = osl_getFileURLFromSystemPath( sys_path.pData, &file_url.pData ); + if ( rc != osl_File_E_None) { + OUString tempPath; + if ( osl_getSystemPathFromFileURL( sys_path.pData, &tempPath.pData) == osl_File_E_None ) + { + file_url = sys_path; + } + else if (throw_exc) + { + throw RuntimeException( + OUSTR("cannot get file url from system path: ") + + sys_path, Reference< XInterface >() ); + } + } + + OUString abs; + if (osl_getAbsoluteFileURL( + base_url.pData, file_url.pData, &abs.pData ) != osl_File_E_None) + { + if (throw_exc) { + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "making absolute file url failed: \"") ); + buf.append( base_url ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "\" (base-url) and \"") ); + buf.append( file_url ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" (file-url)!") ); + throw RuntimeException( + buf.makeStringAndClear(), Reference< XInterface >() ); + } + return OUString(); + } + return abs[ abs.getLength() -1 ] == '/' + ? abs.copy( 0, abs.getLength() -1 ) : abs; +} + +//############################################################################## + +namespace { + +//------------------------------------------------------------------------------ +inline void printf_space( sal_Int32 space ) +{ + while (space--) + dp_misc::writeConsole(" "); +} + +//------------------------------------------------------------------------------ +void printf_line( + OUString const & name, OUString const & value, sal_Int32 level ) +{ + printf_space( level ); + dp_misc::writeConsole(name + OUSTR(": ") + value + OUSTR("\n")); +} + +//------------------------------------------------------------------------------ +void printf_package( + Reference<deployment::XPackage> const & xPackage, + Reference<XCommandEnvironment> const & xCmdEnv, sal_Int32 level ) +{ + beans::Optional< OUString > id( + level == 0 + ? beans::Optional< OUString >( + true, dp_misc::getIdentifier( xPackage ) ) + : xPackage->getIdentifier() ); + if (id.IsPresent) + printf_line( OUSTR("Identifier"), id.Value, level ); + OUString version(xPackage->getVersion()); + if (version.getLength() != 0) + printf_line( OUSTR("Version"), version, level + 1 ); + printf_line( OUSTR("URL"), xPackage->getURL(), level + 1 ); + + beans::Optional< beans::Ambiguous<sal_Bool> > option( + xPackage->isRegistered( Reference<task::XAbortChannel>(), xCmdEnv ) ); + OUString value; + if (option.IsPresent) { + beans::Ambiguous<sal_Bool> const & reg = option.Value; + if (reg.IsAmbiguous) + value = OUSTR("unknown"); + else + value = reg.Value ? OUSTR("yes") : OUSTR("no"); + } + else + value = OUSTR("n/a"); + printf_line( OUSTR("is registered"), value, level + 1 ); + + const Reference<deployment::XPackageTypeInfo> xPackageType( + xPackage->getPackageType() ); + OSL_ASSERT( xPackageType.is() ); + if (xPackageType.is()) { + printf_line( OUSTR("Media-Type"), + xPackageType->getMediaType(), level + 1 ); + } + printf_line( OUSTR("Description"), xPackage->getDescription(), level + 1 ); + if (xPackage->isBundle()) { + Sequence< Reference<deployment::XPackage> > seq( + xPackage->getBundle( Reference<task::XAbortChannel>(), xCmdEnv ) ); + printf_space( level + 1 ); + dp_misc::writeConsole("bundled Packages: {\n"); + ::std::vector<Reference<deployment::XPackage> >vec_bundle; + ::comphelper::sequenceToContainer(vec_bundle, seq); + printf_packages( vec_bundle, ::std::vector<bool>(vec_bundle.size()), + xCmdEnv, level + 2 ); + printf_space( level + 1 ); + dp_misc::writeConsole("}\n"); + } +} + +} // anon namespace + +void printf_unaccepted_licenses( + Reference<deployment::XPackage> const & ext) +{ + OUString id( + dp_misc::getIdentifier(ext) ); + printf_line( OUSTR("Identifier"), id, 0 ); + printf_space(1); + dp_misc::writeConsole(OUSTR("License not accepted\n\n")); +} + +//============================================================================== +void printf_packages( + ::std::vector< Reference<deployment::XPackage> > const & allExtensions, + ::std::vector<bool> const & vecUnaccepted, + Reference<XCommandEnvironment> const & xCmdEnv, sal_Int32 level ) +{ + OSL_ASSERT(allExtensions.size() == vecUnaccepted.size()); + + if (allExtensions.size() == 0) + { + printf_space( level ); + dp_misc::writeConsole("<none>\n"); + } + else + { + typedef ::std::vector< Reference<deployment::XPackage> >::const_iterator I_EXT; + int index = 0; + for (I_EXT i = allExtensions.begin(); i != allExtensions.end(); i++, index++) + { + if (vecUnaccepted[index]) + printf_unaccepted_licenses(*i); + else + printf_package( *i, xCmdEnv, level ); + dp_misc::writeConsole(OUSTR("\n")); + } + } +} + + +//############################################################################## + +namespace { + +//------------------------------------------------------------------------------ +Reference<XComponentContext> bootstrapStandAlone( + DisposeGuard & disposeGuard, bool /*verbose */) +{ + Reference<XComponentContext> xContext = + ::cppu::defaultBootstrap_InitialComponentContext(); + + // assure disposing of local component context: + disposeGuard.reset( + Reference<lang::XComponent>( xContext, UNO_QUERY ) ); + + Reference<lang::XMultiServiceFactory> xServiceManager( + xContext->getServiceManager(), UNO_QUERY_THROW ); + // set global process service factory used by unotools config helpers + ::utl::setProcessServiceFactory( xServiceManager ); + + // initialize the ucbhelper ucb, + // because the package implementation uses it + Sequence<Any> ucb_args( 2 ); + ucb_args[ 0 ] <<= OUSTR(UCB_CONFIGURATION_KEY1_LOCAL); + ucb_args[ 1 ] <<= OUSTR(UCB_CONFIGURATION_KEY2_OFFICE); + if (! ::ucbhelper::ContentBroker::initialize( xServiceManager, ucb_args )) + throw RuntimeException( OUSTR("cannot initialize UCB!"), 0 ); + + disposeGuard.setDeinitUCB(); + return xContext; +} + +//------------------------------------------------------------------------------ +Reference<XComponentContext> connectToOffice( + Reference<XComponentContext> const & xLocalComponentContext, + bool verbose ) +{ + Sequence<OUString> args( 3 ); + args[ 0 ] = OUSTR("-nologo"); + args[ 1 ] = OUSTR("-nodefault"); + + OUString pipeId( ::dp_misc::generateRandomPipeId() ); + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("-accept=pipe,name=") ); + buf.append( pipeId ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(";urp;") ); + args[ 2 ] = buf.makeStringAndClear(); + OUString appURL( getExecutableDir() + OUSTR("/soffice") ); + + if (verbose) + { + dp_misc::writeConsole( + OUSTR("Raising process: ") + + appURL + + OUSTR("\nArguments: -nologo -nodefault ") + + args[2] + + OUSTR("\n")); + } + + ::dp_misc::raiseProcess( appURL, args ); + + if (verbose) + dp_misc::writeConsole("Ok. Connecting..."); + + OSL_ASSERT( buf.getLength() == 0 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("uno:pipe,name=") ); + buf.append( pipeId ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + ";urp;StarOffice.ComponentContext") ); + Reference<XComponentContext> xRet( + ::dp_misc::resolveUnoURL( + buf.makeStringAndClear(), xLocalComponentContext ), + UNO_QUERY_THROW ); + if (verbose) + dp_misc::writeConsole("Ok.\n"); + + return xRet; +} + +} // anon namespace + +/** returns the path to the lock file used by unopkg. + @return the path. An empty string signifies an error. +*/ +OUString getLockFilePath() +{ + OUString ret; + OUString sBootstrap(RTL_CONSTASCII_USTRINGPARAM("${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}")); + rtl::Bootstrap::expandMacros(sBootstrap); + OUString sAbs; + if (::osl::File::E_None == ::osl::File::getAbsoluteFileURL( + sBootstrap, OUSTR(".lock"), sAbs)) + { + if (::osl::File::E_None == + ::osl::File::getSystemPathFromFileURL(sAbs, sBootstrap)) + { + ret = sBootstrap; + } + } + + return ret; +} +//============================================================================== +Reference<XComponentContext> getUNO( + DisposeGuard & disposeGuard, bool verbose, bool shared, bool bGui, + Reference<XComponentContext> & out_localContext) +{ + // do not create any user data (for the root user) in --shared mode: + if (shared) { + rtl::Bootstrap::set( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CFG_CacheUrl")), + rtl::OUString()); + } + + // hold lock during process runtime: + static ::desktop::Lockfile s_lockfile( false /* no IPC server */ ); + Reference<XComponentContext> xComponentContext( + bootstrapStandAlone( disposeGuard, verbose ) ); + out_localContext = xComponentContext; + if (::dp_misc::office_is_running()) { + xComponentContext.set( + connectToOffice( xComponentContext, verbose ) ); + } + else + { + if (! s_lockfile.check( 0 )) + { + String sMsg(ResId(RID_STR_CONCURRENTINSTANCE, *DeploymentResMgr::get())); + //Create this string before we call DeInitVCL, because this will kill + //the ResMgr + String sError(ResId(RID_STR_UNOPKG_ERROR, *DeploymentResMgr::get())); + + sMsg = sMsg + OUSTR("\n") + getLockFilePath(); + + if (bGui) + { + //We show a message box or print to the console that there + //is another instance already running + if ( ! InitVCL( Reference<lang::XMultiServiceFactory>( + xComponentContext->getServiceManager(), + UNO_QUERY_THROW ) )) + throw RuntimeException( OUSTR("Cannot initialize VCL!"), + NULL ); + { + WarningBox warn(NULL, WB_OK | WB_DEF_OK, sMsg); + warn.SetText(::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::PRODUCTNAME).get<OUString>()); + warn.SetIcon(0); + warn.Execute(); + } + DeInitVCL(); + } + + throw LockFileException( + OUSTR("\n") + sError + sMsg + OUSTR("\n")); + } + } + + return xComponentContext; +} + +//Determines if a folder does not contains a folder. +//Return false may also mean that the status could not be determined +//because some error occurred. +bool hasNoFolder(OUString const & folderUrl) +{ + bool ret = false; + OUString url = folderUrl; + ::rtl::Bootstrap::expandMacros(url); + ::osl::Directory dir(url); + osl::File::RC rc = dir.open(); + if (rc == osl::File::E_None) + { + bool bFolderExist = false; + osl::DirectoryItem i; + osl::File::RC rcNext = osl::File::E_None; + while ( (rcNext = dir.getNextItem(i)) == osl::File::E_None) + { + osl::FileStatus stat(FileStatusMask_Type); + if (i.getFileStatus(stat) == osl::File::E_None) + { + if (stat.getFileType() == osl::FileStatus::Directory) + { + bFolderExist = true; + break; + } + } + else + { + dp_misc::writeConsole( + OUSTR("unopkg: Error while investigating ") + url + OUSTR("\n")); + break; + } + i = osl::DirectoryItem(); + } + + if (rcNext == osl::File::E_NOENT || + rcNext == osl::File::E_None) + { + if (!bFolderExist) + ret = true; + } + else + { + dp_misc::writeConsole( + OUSTR("unopkg: Error while investigating ") + url + OUSTR("\n")); + } + + dir.close(); + } + else + { + dp_misc::writeConsole( + OUSTR("unopkg: Error while investigating ") + url + OUSTR("\n")); + } + return ret; +} + +void removeFolder(OUString const & folderUrl) +{ + OUString url = folderUrl; + ::rtl::Bootstrap::expandMacros(url); + ::osl::Directory dir(url); + ::osl::File::RC rc = dir.open(); + if (rc == osl::File::E_None) + { + ::osl::DirectoryItem i; + ::osl::File::RC rcNext = ::osl::File::E_None; + while ( (rcNext = dir.getNextItem(i)) == ::osl::File::E_None) + { + ::osl::FileStatus stat(FileStatusMask_Type | FileStatusMask_FileURL); + if (i.getFileStatus(stat) == ::osl::File::E_None) + { + ::osl::FileStatus::Type t = stat.getFileType(); + if (t == ::osl::FileStatus::Directory) + { + //remove folder + removeFolder(stat.getFileURL()); + } + else if (t == ::osl::FileStatus::Regular) + { + //remove file + ::osl::File::remove(stat.getFileURL()); + } + else + { + OSL_ASSERT(0); + } + } + else + { + dp_misc::writeConsole( + OUSTR("unopkg: Error while investigating ") + url + OUSTR("\n")); + break; + } + i = ::osl::DirectoryItem(); + } + dir.close(); + ::osl::Directory::remove(url); + } + else + { + dp_misc::writeConsole( + OUSTR("unopkg: Error while removing ") + url + OUSTR("\n")); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/pkgchk/unopkg/unopkg_shared.h b/desktop/source/pkgchk/unopkg/unopkg_shared.h new file mode 100644 index 000000000000..232fbf8f5260 --- /dev/null +++ b/desktop/source/pkgchk/unopkg/unopkg_shared.h @@ -0,0 +1,197 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "dp_misc.h" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/lang/XComponent.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/deployment/XPackage.hpp" +#include "tools/resmgr.hxx" +#include "rtl/ustring.hxx" +#include "unotools/configmgr.hxx" +#include "ucbhelper/contentbroker.hxx" + + +#define APP_NAME "unopkg" + +namespace css = ::com::sun::star; + +namespace unopkg { + + inline ::com::sun::star::lang::Locale toLocale( ::rtl::OUString const & slang ) + { + ::com::sun::star::lang::Locale locale; + sal_Int32 nIndex = 0; + locale.Language = slang.getToken( 0, '-', nIndex ); + locale.Country = slang.getToken( 0, '-', nIndex ); + locale.Variant = slang.getToken( 0, '-', nIndex ); + return locale; + } + + + struct OfficeLocale : + public rtl::StaticWithInit<const css::lang::Locale, OfficeLocale> { + const css::lang::Locale operator () () { + ::rtl::OUString slang; + if (! (::utl::ConfigManager::GetDirectConfigProperty( + ::utl::ConfigManager::LOCALE ) >>= slang)) + throw css::uno::RuntimeException( OUSTR("Cannot determine language!"), 0 ); + if (slang.getLength() == 0) + slang = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("en-US")); + return toLocale(slang); + } +}; + +struct DeploymentResMgr : public rtl::StaticWithInit< ResMgr *, DeploymentResMgr > +{ + ResMgr * operator () () { + return ResMgr::CreateResMgr( "deployment", OfficeLocale::get()); + } +}; + +struct OptionInfo +{ + char const * m_name; + sal_uInt32 m_name_length; + sal_Unicode m_short_option; + bool m_has_argument; +}; + +struct LockFileException : public css::uno::Exception +{ + LockFileException(::rtl::OUString const & sMessage) : + css::uno::Exception(sMessage, css::uno::Reference< css::uno::XInterface > ()) {} +}; + +//============================================================================== +::rtl::OUString toString( OptionInfo const * info ); + +//============================================================================== +OptionInfo const * getOptionInfo( + OptionInfo const * list, + ::rtl::OUString const & opt, sal_Unicode copt = '\0' ); + +//============================================================================== +bool isOption( OptionInfo const * option_info, sal_uInt32 * pIndex ); + +//============================================================================== +bool readArgument( + ::rtl::OUString * pValue, OptionInfo const * option_info, + sal_uInt32 * pIndex ); + +//============================================================================== +inline bool readOption( + bool * flag, OptionInfo const * option_info, sal_uInt32 * pIndex ) +{ + if (isOption( option_info, pIndex )) { + OSL_ASSERT( flag != 0 ); + *flag = true; + return true; + } + return false; +} +//============================================================================== + +/** checks if an argument is a bootstrap variable. These start with -env:. For example + -env:UNO_JAVA_JFW_USER_DATA=file:///d:/user +*/ +bool isBootstrapVariable(sal_uInt32 * pIndex); +//============================================================================== +::rtl::OUString const & getExecutableDir(); + +//============================================================================== +::rtl::OUString const & getProcessWorkingDir(); + +//============================================================================== +::rtl::OUString makeAbsoluteFileUrl( + ::rtl::OUString const & sys_path, ::rtl::OUString const & base_url, + bool throw_exc = true ); + +//############################################################################## + +//============================================================================== +class DisposeGuard +{ + css::uno::Reference<css::lang::XComponent> m_xComp; + bool m_bDeinitUCB; +public: + DisposeGuard(): m_bDeinitUCB(false) {} + inline ~DisposeGuard() + { + if (m_bDeinitUCB) + ::ucbhelper::ContentBroker::deinitialize(); + + if (m_xComp.is()) + m_xComp->dispose(); + } + + inline void reset( + css::uno::Reference<css::lang::XComponent> const & xComp ) + { + m_xComp = xComp; + } + + inline void setDeinitUCB() + { + m_bDeinitUCB = true; + } + +}; + +//============================================================================== +css::uno::Reference<css::ucb::XCommandEnvironment> createCmdEnv( + css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & logFile, + bool option_force_overwrite, + bool option_verbose, + bool option_suppressLicense); +//============================================================================== +void printf_packages( + ::std::vector< + css::uno::Reference<css::deployment::XPackage> > const & allExtensions, + ::std::vector<bool> const & vecUnaccepted, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + sal_Int32 level = 0 ); + +//############################################################################## + +//============================================================================== +css::uno::Reference<css::uno::XComponentContext> getUNO( + DisposeGuard & disposeGuard, bool verbose, bool shared, bool bGui, + css::uno::Reference<css::uno::XComponentContext> & out_LocalComponentContext); + +bool hasNoFolder(::rtl::OUString const & folderUrl); + +void removeFolder(::rtl::OUString const & folderUrl); + +} + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/pkgchk/unopkg/version.map b/desktop/source/pkgchk/unopkg/version.map new file mode 100644 index 000000000000..8591bb3b5847 --- /dev/null +++ b/desktop/source/pkgchk/unopkg/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: + unopkg_main; + + local: + *; +}; diff --git a/desktop/source/registration/com/sun/star/registration/Registration.java b/desktop/source/registration/com/sun/star/registration/Registration.java new file mode 100644 index 000000000000..6ac22c7c392e --- /dev/null +++ b/desktop/source/registration/com/sun/star/registration/Registration.java @@ -0,0 +1,339 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +package com.sun.star.registration; + +import com.sun.star.beans.NamedValue; +import com.sun.star.comp.loader.FactoryHelper; +import com.sun.star.frame.DispatchResultEvent; +import com.sun.star.frame.DispatchResultState; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XSingleServiceFactory; +import com.sun.star.registry.*; +import com.sun.star.servicetag.*; +import com.sun.star.system.*; +import com.sun.star.task.*; +import com.sun.star.uno.*; +import com.sun.star.uri.XExternalUriReferenceTranslator; +import com.sun.star.util.XStringSubstitution; + +import java.io.*; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Locale; +import java.util.Set; +import java.net.HttpURLConnection; + +public class Registration { + + public static XSingleServiceFactory __getServiceFactory(String implName, + XMultiServiceFactory multiFactory, XRegistryKey regKey) { + XSingleServiceFactory xSingleServiceFactory = null; + + if (implName.equals(Registration.class.getName())) { + xSingleServiceFactory = FactoryHelper.getServiceFactory(_Registration.class, _serviceName, multiFactory, regKey); + } + + return xSingleServiceFactory; + } + + public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) { + return FactoryHelper.writeRegistryServiceInfo(Registration.class.getName(), _serviceName, regKey); + } + + static final String _serviceName = "com.sun.star.comp.framework.DoRegistrationJob"; + + static public class _Registration implements XJob { + XComponentContext xComponentContext; + + XStringSubstitution xPathSubstService = null; + XExternalUriReferenceTranslator xUriTranslator = null; + + RegistrationData theRegistrationData = null; + + public _Registration(XComponentContext xComponentContext) { + this.xComponentContext = xComponentContext; + } + + private String resolvePath(String path) { + try { + if( xPathSubstService == null || xUriTranslator == null ) { + XMultiComponentFactory theServiceManager = xComponentContext.getServiceManager(); + if( xPathSubstService == null ) { + Object o = theServiceManager.createInstanceWithContext( + "com.sun.star.util.PathSubstitution", + xComponentContext ); + xPathSubstService = (XStringSubstitution) + UnoRuntime.queryInterface(XStringSubstitution.class, o); + } + + if( xUriTranslator == null ) { + Object o = theServiceManager.createInstanceWithContext( + "com.sun.star.uri.ExternalUriReferenceTranslator", + xComponentContext ); + xUriTranslator = (XExternalUriReferenceTranslator) + UnoRuntime.queryInterface(XExternalUriReferenceTranslator.class, o); + } + } + + String s = xPathSubstService.substituteVariables(path, true); + return xUriTranslator.translateToExternal(s); + } catch (java.lang.Exception e) { + return path; + } + } + + private void openBrowser(String url) { + try { + XMultiComponentFactory theServiceManager = xComponentContext.getServiceManager(); + + Object o = theServiceManager.createInstanceWithContext( + "com.sun.star.system.SystemShellExecute", + xComponentContext ); + + XSystemShellExecute xShellExecuteService = (XSystemShellExecute) + UnoRuntime.queryInterface(XSystemShellExecute.class, o); + + xShellExecuteService.execute( url, "", SystemShellExecuteFlags.DEFAULTS ); + } catch (java.lang.Exception e) { + } + } + + private ServiceTag getServiceTagFromRegistrationData(File xmlFile, String productURN) { + try { + RegistrationData storedRegData = RegistrationData.loadFromXML(new FileInputStream(xmlFile)); + Set<ServiceTag> storedServiceTags = storedRegData.getServiceTags(); + + Iterator<ServiceTag> tagIterator = storedServiceTags.iterator(); + while( tagIterator.hasNext() ) { + ServiceTag tag = tagIterator.next(); + if( tag.getProductURN().equals(productURN) ) { + theRegistrationData = storedRegData; + return tag; + } + } + + // product URN has changed, remove registration data file + xmlFile.delete(); + } catch (IOException e) { + // fall through intentionally + } catch (IllegalArgumentException e) { + // file is damaged (or a name clash appeared) + xmlFile.delete(); + } + return null; + } + + /* + * XJob + * + * NOTE: as this Job hets triggered by the the JobExecutor service from first start + * wizard and registration reminder code (because their frames do not implement + * XDispatchProvider), making this an XAsyncJob doesn't make sense as the + * JobExecutor waits for the jobFinished call on the listener passed. + */ + public Object execute(NamedValue[] args) + throws com.sun.star.lang.IllegalArgumentException, com.sun.star.uno.Exception { + + final NamedValue[] f_args = args; + + new Thread( + new Runnable () { + public void run() { + try { + executeImpl(f_args); + } catch(com.sun.star.uno.Exception e) { + } + } + } + ).start(); + + NamedValue ret[] = new NamedValue[1]; + ret[0] = new NamedValue( "Deactivate", new Boolean(false) ); + return ret; + } + + public synchronized void executeImpl(NamedValue[] args) + throws com.sun.star.lang.IllegalArgumentException, com.sun.star.uno.Exception { + + // extract the interesting part of the argument list + NamedValue[] theJobConfig = null; + NamedValue[] theEnvironment = null; + + int c = args.length; + for (int i=0; i<c; ++i) { + if (args[i].Name.equals("JobConfig")) + theJobConfig = (NamedValue[]) AnyConverter.toArray(args[i].Value); + else if (args[i].Name.equals("Environment")) + theEnvironment = (NamedValue[]) AnyConverter.toArray(args[i].Value); + } + + if (theEnvironment==null) + throw new com.sun.star.lang.IllegalArgumentException("no environment"); + + boolean saveConfig = false; + + String productName = ""; + String productVersion = ""; + String productURN = ""; + String productParent = ""; + String productParentURN = ""; + String productDefinedInstanceID = ""; + String productSource = ""; + String vendor = ""; + + String urlRegData = null; + String registrationURL = null; + + c = theJobConfig.length; + for (int i=0; i<c; ++i) { + if( theJobConfig[i].Name.equals("ProductName") ) { + productName = AnyConverter.toString(theJobConfig[i].Value); + } else if( theJobConfig[i].Name.equals("ProductVersion") ) { + productVersion = AnyConverter.toString(theJobConfig[i].Value); + } else if( theJobConfig[i].Name.equals("ProductURN") ) { + productURN = AnyConverter.toString(theJobConfig[i].Value); + } else if( theJobConfig[i].Name.equals("ProductParent") ) { + productParent = AnyConverter.toString(theJobConfig[i].Value); + } else if( theJobConfig[i].Name.equals("ProductParentURN") ) { + productParentURN = AnyConverter.toString(theJobConfig[i].Value); + } else if( theJobConfig[i].Name.equals("ProductSource") ) { + productSource = AnyConverter.toString(theJobConfig[i].Value); + } else if( theJobConfig[i].Name.equals("Vendor") ) { + vendor = AnyConverter.toString(theJobConfig[i].Value); + } else if( theJobConfig[i].Name.equals("RegistrationData") ) { + urlRegData = resolvePath(AnyConverter.toString(theJobConfig[i].Value)); + } else if( theJobConfig[i].Name.equals("RegistrationURL") ) { + registrationURL = AnyConverter.toString(theJobConfig[i].Value); + } else { + System.err.println( theJobConfig[i].Name + " = " + AnyConverter.toString(theJobConfig[i].Value) ); + } + } + + if (registrationURL==null) + throw new com.sun.star.lang.IllegalArgumentException("no registration url"); + + boolean local_only = false; + + c = theEnvironment.length; + for (int i=0; i<c; ++i) { + if( theEnvironment[i].Name.equals("EventName") ) { + if( ! AnyConverter.toString(theEnvironment[i].Value).equals("onRegisterNow") ) { + local_only = true; + } + } + } + + try { + + /* ensure only one thread accesses/writes registration.xml at a time + * regardless how many instances of this Job exist. + */ + synchronized( _serviceName ) { + + File xmlRegData = new File( new URI( urlRegData ) ); + + ServiceTag tag = getServiceTagFromRegistrationData(xmlRegData, productURN); + if( tag == null ) { + tag = ServiceTag.newInstance( + ServiceTag.generateInstanceURN(), + productName, + productVersion, + productURN, + productParent, + productParentURN, + productDefinedInstanceID, + vendor, + System.getProperty("os.arch"), + Installer.getZoneName(), + productSource); + + theRegistrationData = new RegistrationData(); + theRegistrationData.addServiceTag(tag); + theRegistrationData.storeToXML( new FileOutputStream( xmlRegData ) ); + } + + // Store the service tag in local registry, which might have been installed later + if( Registry.isSupported() ) { + // ignore communication failures with local service tag client + try { + if( Registry.getSystemRegistry().getServiceTag(tag.getInstanceURN()) == null ) { + Registry.getSystemRegistry().addServiceTag(tag); + } + } catch( java.io.IOException e) { + e.printStackTrace(); + } catch (java.lang.RuntimeException e) { + e.printStackTrace(); + } + } + } + + if( ! local_only ) { + registrationURL = registrationURL.replaceAll("\\$\\{registry_urn\\}", theRegistrationData.getRegistrationURN()); + registrationURL = registrationURL.replaceAll("\\$\\{locale\\}", Locale.getDefault().getLanguage()); + + HttpURLConnection con = (HttpURLConnection) new URL(registrationURL).openConnection(); + con.setDoInput(true); + con.setDoOutput(true); + con.setUseCaches(false); + con.setAllowUserInteraction(false); + con.setRequestMethod("POST"); + + con.setRequestProperty("Content-Type", "text/xml;charset=\"utf-8\""); + try { + con.connect(); + + OutputStream out = con.getOutputStream(); + theRegistrationData.storeToXML(out); + out.flush(); + out.close(); + + int returnCode = con.getResponseCode(); +// if (returnCode == HttpURLConnection.HTTP_OK); + } catch(java.lang.Exception e) { + // IOException and UnknownHostException + } + openBrowser(registrationURL); + } + } catch (java.net.MalformedURLException e) { + e.printStackTrace(); + throw new com.sun.star.lang.IllegalArgumentException( e.toString() ); + } catch (java.net.URISyntaxException e) { + e.printStackTrace(); + throw new com.sun.star.lang.IllegalArgumentException( e.toString() ); + } catch (java.io.IOException e) { + e.printStackTrace(); + throw new com.sun.star.uno.RuntimeException( e.toString() ); + } catch (java.lang.RuntimeException e) { + e.printStackTrace(); + throw new com.sun.star.uno.RuntimeException( e.toString() ); + } + } + } +} diff --git a/desktop/source/registration/com/sun/star/registration/makefile.mk b/desktop/source/registration/com/sun/star/registration/makefile.mk new file mode 100644 index 000000000000..9784166eb91b --- /dev/null +++ b/desktop/source/registration/com/sun/star/registration/makefile.mk @@ -0,0 +1,55 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +PRJNAME = setup_native +PRJ = ..$/..$/..$/..$/..$/.. +TARGET = productregistration +PACKAGE = com$/sun$/star$/registration + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +.IF "$(ENABLE_SVCTAGS)" == "YES" + +JARFILES = jurt.jar unoil.jar ridl.jar +JAVAFILES = \ + Registration.java + +JAVACLASSFILES= $(foreach,i,$(JAVAFILES) $(CLASSDIR)$/$(PACKAGE)$/$(i:b).class) + +JARTARGET = $(TARGET).jar +JARCOMPRESS = TRUE +JARCLASSDIRS = $(PACKAGE) com$/sun$/star$/servicetag +CUSTOMMANIFESTFILE = manifest +.ENDIF # "$(ENABLE_SVCTAGS)" == "YES" + +# --- Targets ------------------------------------------------------ + + +.INCLUDE : target.mk + diff --git a/desktop/source/registration/com/sun/star/registration/manifest b/desktop/source/registration/com/sun/star/registration/manifest new file mode 100644 index 000000000000..952aaa804e96 --- /dev/null +++ b/desktop/source/registration/com/sun/star/registration/manifest @@ -0,0 +1,2 @@ +RegistrationClassName: com.sun.star.registration.Registration +UNO-Type-Path: diff --git a/desktop/source/registration/com/sun/star/servicetag/BrowserSupport.java b/desktop/source/registration/com/sun/star/servicetag/BrowserSupport.java new file mode 100644 index 000000000000..c475b75dd35f --- /dev/null +++ b/desktop/source/registration/com/sun/star/servicetag/BrowserSupport.java @@ -0,0 +1,201 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +package com.sun.star.servicetag; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +import java.io.IOException; +import java.net.URI; + +/** + * BrowserSupport class. + * + * The implementation of the com.sun.servicetag API needs to be + * compiled with JDK 5 as well since the consumer of this API + * may require to support JDK 5 (e.g. NetBeans). + * + * The Desktop.browse() method can be backported in this class + * if needed. The current implementation only supports JDK 6. + */ +class BrowserSupport { + private static boolean isBrowseSupported = false; + private static Method browseMethod = null; + private static Object desktop = null; + private static volatile Boolean result = false; + + + private static void initX() { + if (desktop != null) { + return; + } + boolean supported = false; + Method browseM = null; + Object desktopObj = null; + try { + // Determine if java.awt.Desktop is supported + Class desktopCls = Class.forName("java.awt.Desktop", true, null); + Method getDesktopM = desktopCls.getMethod("getDesktop"); + browseM = desktopCls.getMethod("browse", URI.class); + + Class actionCls = Class.forName("java.awt.Desktop$Action", true, null); + final Method isDesktopSupportedMethod = desktopCls.getMethod("isDesktopSupported"); + Method isSupportedMethod = desktopCls.getMethod("isSupported", actionCls); + Field browseField = actionCls.getField("BROWSE"); + // isDesktopSupported calls getDefaultToolkit which can block + // infinitely, see 6636099 for details, to workaround we call + // in a thread and time it out, noting that the issue is specific + // to X11, it does not hurt for Windows. + Thread xthread = new Thread() { + public void run() { + try { + // support only if Desktop.isDesktopSupported() and + // Desktop.isSupported(Desktop.Action.BROWSE) return true. + result = (Boolean) isDesktopSupportedMethod.invoke(null); + } catch (IllegalAccessException e) { + // should never reach here + InternalError x = + new InternalError("Desktop.getDesktop() method not found"); + x.initCause(e); + } catch (InvocationTargetException e) { + // browser not supported + if (Util.isVerbose()) { + e.printStackTrace(); + } + } + } + }; + // set it to daemon, so that the vm will exit. + xthread.setDaemon(true); + xthread.start(); + try { + xthread.join(5 * 1000); + } catch (InterruptedException ie) { + // ignore the exception + } + if (result.booleanValue()) { + desktopObj = getDesktopM.invoke(null); + result = (Boolean) isSupportedMethod.invoke(desktopObj, browseField.get(null)); + supported = result.booleanValue(); + } + } catch (ClassNotFoundException e) { + // browser not supported + if (Util.isVerbose()) { + e.printStackTrace(); + } + } catch (NoSuchMethodException e) { + // browser not supported + if (Util.isVerbose()) { + e.printStackTrace(); + } + } catch (NoSuchFieldException e) { + // browser not supported + if (Util.isVerbose()) { + e.printStackTrace(); + } + } catch (IllegalAccessException e) { + // should never reach here + InternalError x = + new InternalError("Desktop.getDesktop() method not found"); + x.initCause(e); + throw x; + } catch (InvocationTargetException e) { + // browser not supported + if (Util.isVerbose()) { + e.printStackTrace(); + } + } + isBrowseSupported = supported; + browseMethod = browseM; + desktop = desktopObj; + } + + static boolean isSupported() { + initX(); + return isBrowseSupported; + } + + /** + * Launches the default browser to display a {@code URI}. + * If the default browser is not able to handle the specified + * {@code URI}, the application registered for handling + * {@code URIs} of the specified type is invoked. The application + * is determined from the protocol and path of the {@code URI}, as + * defined by the {@code URI} class. + * <p> + * This method calls the Desktop.getDesktop().browse() method. + * <p> + * @param uri the URI to be displayed in the user default browser + * + * @throws NullPointerException if {@code uri} is {@code null} + * @throws UnsupportedOperationException if the current platform + * does not support the {@link Desktop.Action#BROWSE} action + * @throws IOException if the user default browser is not found, + * or it fails to be launched, or the default handler application + * failed to be launched + * @throws IllegalArgumentException if the necessary permissions + * are not available and the URI can not be converted to a {@code URL} + */ + static void browse(URI uri) throws IOException { + if (uri == null) { + throw new NullPointerException("null uri"); + } + if (!isSupported()) { + throw new UnsupportedOperationException("Browse operation is not supported"); + } + + // Call Desktop.browse() method + try { + if (Util.isVerbose()) { + System.out.println("desktop: " + desktop + ":browsing..." + uri); + } + browseMethod.invoke(desktop, uri); + } catch (IllegalAccessException e) { + // should never reach here + InternalError x = + new InternalError("Desktop.getDesktop() method not found"); + x.initCause(e); + throw x; + } catch (InvocationTargetException e) { + Throwable x = e.getCause(); + if (x != null) { + if (x instanceof UnsupportedOperationException) { + throw (UnsupportedOperationException) x; + } else if (x instanceof IllegalArgumentException) { + throw (IllegalArgumentException) x; + } else if (x instanceof IOException) { + throw (IOException) x; + } else if (x instanceof SecurityException) { + throw (SecurityException) x; + } else { + // ignore + } + } + } + } +} diff --git a/desktop/source/registration/com/sun/star/servicetag/Installer.java b/desktop/source/registration/com/sun/star/servicetag/Installer.java new file mode 100644 index 000000000000..41d328ca0894 --- /dev/null +++ b/desktop/source/registration/com/sun/star/servicetag/Installer.java @@ -0,0 +1,943 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +package com.sun.star.servicetag; + +import java.io.*; +import java.util.HashSet; +import java.util.Locale; +import java.util.Properties; +import java.util.Set; +import java.util.List; +import java.util.ArrayList; +import static com.sun.star.servicetag.Util.*; + +/** + * Service Tag Installer for Java SE. + */ +public class Installer { + // System properties for testing + private static String SVCTAG_DIR_PATH = + "servicetag.dir.path"; + private static String SVCTAG_ENABLE_REGISTRATION = + "servicetag.registration.enabled"; + private final static String SUN_VENDOR = "Sun Microsystems"; + private final static String REGISTRATION_XML = "registration.xml"; + private final static String SERVICE_TAG_FILE = "servicetag"; + private final static String REGISTRATION_HTML_NAME = "register"; + + private final static Locale[] knownSupportedLocales = + new Locale[] { Locale.ENGLISH, + Locale.JAPANESE, + Locale.SIMPLIFIED_CHINESE}; + + private final static String javaHome = System.getProperty("java.home"); + private static File svcTagDir; + private static File serviceTagFile; + private static File regXmlFile; + private static RegistrationData registration; + private static boolean supportRegistration; + private static String registerHtmlParent; + private static Set<Locale> supportedLocales = new HashSet<Locale>(); + private static Properties swordfishProps = null; + private static String[] jreArchs = null; + static { + String dir = System.getProperty(SVCTAG_DIR_PATH); + if (dir == null) { + svcTagDir = new File(getJrePath(), "lib" + File.separator + SERVICE_TAG_FILE); + } else { + svcTagDir = new File(dir); + } + serviceTagFile = new File(svcTagDir, SERVICE_TAG_FILE); + regXmlFile = new File(svcTagDir, REGISTRATION_XML); + if (System.getProperty(SVCTAG_ENABLE_REGISTRATION) == null) { + supportRegistration = isJdk(); + } else { + supportRegistration = true; + } + } + + private Installer() { + } + + // Implementation of ServiceTag.getJavaServiceTag(String) method + static ServiceTag getJavaServiceTag(String source) throws IOException { + if (!System.getProperty("java.vendor").startsWith(SUN_VENDOR)) { + // Products bundling this implementation may run on + // Mac OS which is not a Sun JDK + return null; + } + boolean cleanup = false; + try { + // Check if we have the swordfish entries for this JRE version + if (loadSwordfishEntries() == null) { + return null; + } + + ServiceTag st = getJavaServiceTag(); + // Check if the service tag created by this bundle owner + if (st != null && st.getSource().equals(source)) { + // Install the system service tag if supported + // stclient may be installed after the service tag creation + if (Registry.isSupported()) { + installSystemServiceTag(); + } + return st; + } + + // in case any exception thrown during the cleanup + cleanup = true; + + // re-create a new one for this bundle owner + // first delete the registration data + deleteRegistrationData(); + cleanup = false; + + // create service tag and generate new register.html pages + return createServiceTag(source); + } finally { + if (cleanup) { + if (regXmlFile.exists()) { + regXmlFile.delete(); + } + if (serviceTagFile.exists()) { + serviceTagFile.delete(); + } + } + } + } + + /** + * Returns the Java SE registration data located in + * the <JRE>/lib/servicetag/registration.xml by default. + * + * @throws IllegalArgumentException if the registration data + * is of invalid format. + */ + private static synchronized RegistrationData getRegistrationData() + throws IOException { + if (registration != null) { + return registration; + } + if (regXmlFile.exists()) { + BufferedInputStream in = null; + try { + in = new BufferedInputStream(new FileInputStream(regXmlFile)); + registration = RegistrationData.loadFromXML(in); + } catch (IllegalArgumentException ex) { + System.err.println("Error: Bad registration data \"" + + regXmlFile + "\":" + ex.getMessage()); + throw ex; + } finally { + if (in != null) { + in.close(); + } + } + } else { + registration = new RegistrationData(); + } + return registration; + } + + /** + * Write the registration data to the registration.xml file. + * + * The offline registration page has to be regenerated with + * the new registration data. + * + * @throws java.io.IOException + */ + private static synchronized void writeRegistrationXml() + throws IOException { + if (!svcTagDir.exists()) { + // This check is for NetBeans or other products that + // bundles this com.sun.servicetag implementation for + // pre-6u5 release. + if (!svcTagDir.mkdir()) { + throw new IOException("Failed to create directory: " + svcTagDir); + } + } + + // regenerate the new offline registration page + deleteRegistrationHtmlPage(); + getRegistrationHtmlPage(); + + BufferedOutputStream out = null; + try { + out = new BufferedOutputStream(new FileOutputStream(regXmlFile)); + getRegistrationData().storeToXML(out); + } catch (IllegalArgumentException ex) { + System.err.println("Error: Bad registration data \"" + + regXmlFile + "\":" + ex.getMessage()); + throw ex; + } finally { + if (out != null) { + out.close(); + } + } + } + + /** + * Returns the instance urn(s) stored in the servicetag file + * or empty set if file not exists. + */ + private static Set<String> getInstalledURNs() throws IOException { + Set<String> urnSet = new HashSet<String>(); + if (serviceTagFile.exists()) { + BufferedReader in = null; + try { + in = new BufferedReader(new FileReader(serviceTagFile)); + String urn; + while ((urn = in.readLine()) != null) { + urn = urn.trim(); + if (urn.length() > 0) { + urnSet.add(urn); + } + } + } finally { + if (in != null) { + in.close(); + } + } + } + return urnSet; + } + + /** + * Return the Java SE service tag(s) if it exists. + * Typically only one Java SE service tag but it could have two for + * Solaris 32-bit and 64-bit on the same install directory. + * + * @return the service tag(s) for Java SE + */ + private static ServiceTag[] getJavaServiceTagArray() throws IOException { + RegistrationData regData = getRegistrationData(); + Set<ServiceTag> svcTags = regData.getServiceTags(); + Set<ServiceTag> result = new HashSet<ServiceTag>(); + + Properties props = loadSwordfishEntries(); + String jdkUrn = props.getProperty("servicetag.jdk.urn"); + String jreUrn = props.getProperty("servicetag.jre.urn"); + for (ServiceTag st : svcTags) { + if (st.getProductURN().equals(jdkUrn) || + st.getProductURN().equals(jreUrn)) { + result.add(st); + } + } + return result.toArray(new ServiceTag[0]); + } + + /** + * Returns the Java SE service tag for this running platform; + * or null if not exist. + * This method will return the 64-bit service tag if the JDK + * supports both 32-bit and 64-bit if already created. + */ + private static ServiceTag getJavaServiceTag() throws IOException { + String definedId = getProductDefinedId(); + for (ServiceTag st : getJavaServiceTagArray()) { + if (st.getProductDefinedInstanceID().equals(definedId)) { + return st; + } + } + return null; + } + + /** + * Create a service tag for Java SE and install in the system + * service tag registry if supported. + * + * A registration data <JRE>/lib/servicetag/registration.xml + * will be created to storeToXML the XML entry for Java SE service tag. + * If the system supports service tags, this method will install + * the Java SE service tag in the system service tag registry and + * its <tt>instance_urn</tt> will be stored to <JRE>/lib/servicetag/servicetag. + * + * If <JRE>/lib/servicetag/registration.xml exists but is not installed + * in the system service tag registry (i.e. servicetag doesn't exist), + * this method will install it as described above. + * + * If the system supports service tag, stclient will be used + * to create the Java SE service tag. + * + * A Solaris 32-bit and 64-bit JDK will be installed in the same + * directory but the registration.xml will have 2 service tags. + * The servicetag file will also contain 2 instance_urns for that case. + */ + private static ServiceTag createServiceTag(String svcTagSource) + throws IOException { + // determine if a new service tag is needed to be created + ServiceTag newSvcTag = null; + if (getJavaServiceTag() == null) { + newSvcTag = newServiceTag(svcTagSource); + } + + // Add the new service tag in the registration data + if (newSvcTag != null) { + RegistrationData regData = getRegistrationData(); + + // Add the service tag to the registration data in JDK/JRE + newSvcTag = regData.addServiceTag(newSvcTag); + + // add if there is a service tag for the OS + ServiceTag osTag = SolarisServiceTag.getServiceTag(); + if (osTag != null && regData.getServiceTag(osTag.getInstanceURN()) == null) { + regData.addServiceTag(osTag); + } + // write to the registration.xml + writeRegistrationXml(); + } + + // Install the system service tag if supported + if (Registry.isSupported()) { + installSystemServiceTag(); + } + return newSvcTag; + } + + private static void installSystemServiceTag() throws IOException { + // only install the service tag in the registry if + // it has permission to write the servicetag file. + if ((!serviceTagFile.exists() && !svcTagDir.canWrite()) || + (serviceTagFile.exists() && !serviceTagFile.canWrite())) { + return; + } + + Set<String> urns = getInstalledURNs(); + ServiceTag[] javaSvcTags = getJavaServiceTagArray(); + if (urns.size() < javaSvcTags.length) { + for (ServiceTag st : javaSvcTags) { + // Add the service tag in the system service tag registry + // if not installed + String instanceURN = st.getInstanceURN(); + if (!urns.contains(instanceURN)) { + Registry.getSystemRegistry().addServiceTag(st); + } + } + } + writeInstalledUrns(); + } + + private static ServiceTag newServiceTag(String svcTagSource) throws IOException { + // Load the swoRDFish information for the service tag creation + Properties props = loadSwordfishEntries(); + + // Determine the product URN and name + String productURN; + String productName; + + if (isJdk()) { + // <HOME>/jre exists which implies it's a JDK + productURN = props.getProperty("servicetag.jdk.urn"); + productName = props.getProperty("servicetag.jdk.name"); + } else { + // Otherwise, it's a JRE + productURN = props.getProperty("servicetag.jre.urn"); + productName = props.getProperty("servicetag.jre.name"); + } + + return ServiceTag.newInstance(ServiceTag.generateInstanceURN(), + productName, + System.getProperty("java.version"), + productURN, + props.getProperty("servicetag.parent.name"), + props.getProperty("servicetag.parent.urn"), + getProductDefinedId(), + SUN_VENDOR, + System.getProperty("os.arch"), + getZoneName(), + svcTagSource); + } + + /** + * Delete the registration data, the offline registration pages and + * the service tags in the system service tag registry if installed. + * + * The registration.xml and servicetag file will be removed. + */ + private static synchronized void deleteRegistrationData() + throws IOException { + try { + // delete the offline registration page + deleteRegistrationHtmlPage(); + + // Remove the service tag from the system ST registry if exists + Set<String> urns = getInstalledURNs(); + if (urns.size() > 0 && Registry.isSupported()) { + for (String u : urns) { + Registry.getSystemRegistry().removeServiceTag(u); + } + } + registration = null; + } finally { + // Delete the registration.xml and servicetag files if exists + if (regXmlFile.exists()) { + if (!regXmlFile.delete()) { + throw new IOException("Failed to delete " + regXmlFile); + } + } + if (serviceTagFile.exists()) { + if (!serviceTagFile.delete()) { + throw new IOException("Failed to delete " + serviceTagFile); + } + } + } + } + + /** + * Updates the registration data to contain one single service tag + * for the running Java runtime. + */ + private static synchronized void updateRegistrationData(String svcTagSource) + throws IOException { + RegistrationData regData = getRegistrationData(); + ServiceTag curSvcTag = newServiceTag(svcTagSource); + + ServiceTag[] javaSvcTags = getJavaServiceTagArray(); + Set<String> urns = getInstalledURNs(); + for (ServiceTag st : javaSvcTags) { + if (!st.getProductDefinedInstanceID().equals(curSvcTag.getProductDefinedInstanceID())) { + String instanceURN = st.getInstanceURN(); + regData.removeServiceTag(instanceURN); + + // remove it from the system service tag registry if exists + if (urns.contains(instanceURN) && Registry.isSupported()) { + Registry.getSystemRegistry().removeServiceTag(instanceURN); + } + } + } + writeRegistrationXml(); + writeInstalledUrns(); + } + + private static void writeInstalledUrns() throws IOException { + // if the Registry is not supported, + // remove the servicetag file + if (!Registry.isSupported() && serviceTagFile.exists()) { + serviceTagFile.delete(); + return; + } + + PrintWriter out = null; + try { + out = new PrintWriter(serviceTagFile); + + ServiceTag[] javaSvcTags = getJavaServiceTagArray(); + for (ServiceTag st : javaSvcTags) { + // Write the instance_run to the servicetag file + String instanceURN = st.getInstanceURN(); + out.println(instanceURN); + } + } finally { + if (out != null) { + out.close(); + } + } + } + + /** + * Load the values associated with the swoRDFish metadata entries + * for Java SE. The swoRDFish metadata entries are different for + * different release. + * + * @param version Version of Java SE + */ + private static synchronized Properties loadSwordfishEntries() throws IOException { + if (swordfishProps != null) { + return swordfishProps; + } + + // The version string for Java SE 6 is 1.6.0 + // We just need the minor number in the version string + int version = Util.getJdkVersion(); + + String filename = "/com/sun/servicetag/resources/javase_" + + version + "_swordfish.properties"; + InputStream in = Installer.class.getClass().getResourceAsStream(filename); + if (in == null) { + return null; + } + swordfishProps = new Properties(); + try { + swordfishProps.load(in); + } finally { + in.close(); + } + return swordfishProps; + } + + /** + * Returns the product defined instance ID for Java SE. + * It is a list of comma-separated name/value pairs: + * "id=<full-version> <arch> [<arch>]*" + * "dir=<java.home system property value>" + * + * where <full-version> is the full version string of the JRE, + * <arch> is the architecture that the runtime supports + * (i.e. "sparc", "sparcv9", "i386", "amd64" (ISA list)) + * + * For Solaris, it can be dual mode that can support both + * 32-bit and 64-bit. the "id" will be set to + * "1.6.0_03-b02 sparc sparcv9" + * + * The "dir" property is included in the service tag to enable + * the Service Tag software to determine if a service tag for + * Java SE is invalid and perform appropriate service tag + * cleanup if necessary. See RFE# 6574781 Service Tags Enhancement. + * + */ + private static String getProductDefinedId() { + StringBuilder definedId = new StringBuilder(); + definedId.append("id="); + definedId.append(System.getProperty("java.runtime.version")); + + String[] archs = getJreArchs(); + for (String name : archs) { + definedId.append(" " + name); + } + + String location = ",dir=" + javaHome; + if ((definedId.length() + location.length()) < 256) { + definedId.append(",dir="); + definedId.append(javaHome); + } else { + // if it exceeds the limit, we will not include the location + if (isVerbose()) { + System.err.println("Warning: Product defined instance ID exceeds the field limit:"); + } + } + + return definedId.toString(); + } + + /** + * Returns the architectures that the runtime supports + * (i.e. "sparc", "sparcv9", "i386", "amd64" (ISA list)) + * The directory name where libjava.so is located. + * + * On Windows, returns the "os.arch" system property value. + */ + private synchronized static String[] getJreArchs() { + if (jreArchs != null) { + return jreArchs; + } + + Set<String> archs = new HashSet<String>(); + + String os = System.getProperty("os.name"); + if (os.equals("SunOS") || os.equals("Linux")) { + // Traverse the directories under <JRE>/lib. + // If <JRE>/lib/<arch>/libjava.so exists, add <arch> + // to the product defined ID + File dir = new File(getJrePath() + File.separator + "lib"); + if (dir.isDirectory()) { + String[] children = dir.list(); + for (String name : children) { + File f = new File(dir, name + File.separator + "libjava.so"); + if (f.exists()) { + archs.add(name); + } + } + } + } else { + // Windows - append the os.arch + archs.add(System.getProperty("os.arch")); + } + jreArchs = archs.toArray(new String[0]); + return jreArchs; + } + + /** + * Return the zonename if zone is supported; otherwise, return + * "global". + */ + public static String getZoneName() throws IOException { + String zonename = "global"; + + String command = "/usr/bin/zonename"; + File f = new File(command); + // com.sun.servicetag package has to be compiled with JDK 5 as well + // JDK 5 doesn't support the File.canExecute() method. + // Risk not checking isExecute() for the zonename command is very low. + if (f.exists()) { + ProcessBuilder pb = new ProcessBuilder(command); + Process p = pb.start(); + String output = commandOutput(p); + if (p.exitValue() == 0) { + zonename = output.trim(); + } + + } + return zonename; + } + + private synchronized static String getRegisterHtmlParent() throws IOException { + if (registerHtmlParent == null) { + File htmlDir; // register.html is put under the JDK directory + if (getJrePath().endsWith(File.separator + "jre")) { + htmlDir = new File(getJrePath(), ".."); + } else { + // j2se non-image build + htmlDir = new File(getJrePath()); + } + + // initialize the supported locales + initSupportedLocales(htmlDir); + + // Determine the location of the offline registration page + String path = System.getProperty(SVCTAG_DIR_PATH); + if (path == null) { + // Default is <JDK>/register.html + registerHtmlParent = htmlDir.getCanonicalPath(); + } else { + File f = new File(path); + registerHtmlParent = f.getCanonicalPath(); + if (!f.isDirectory()) { + throw new InternalError("Path " + path + " set in \"" + + SVCTAG_DIR_PATH + "\" property is not a directory"); + } + } + } + return registerHtmlParent; + } + + /** + * Returns the File object of the offline registration page localized + * for the default locale in the JDK directory. + */ + static synchronized File getRegistrationHtmlPage() throws IOException { + if (!supportRegistration) { + // No register.html page generated if JRE + return null; + } + + String parent = getRegisterHtmlParent(); + + // check if the offline registration page is already generated + File f = new File(parent, REGISTRATION_HTML_NAME + ".html"); + if (!f.exists()) { + // Generate the localized version of the offline registration Page + generateRegisterHtml(parent); + } + + String name = REGISTRATION_HTML_NAME; + List<Locale> candidateLocales = getCandidateLocales(Locale.getDefault()); + for (Locale l : candidateLocales) { + if (supportedLocales.contains(l)) { + name = REGISTRATION_HTML_NAME + "_" + l.toString(); + break; + } + } + File htmlFile = new File(parent, name + ".html"); + if (isVerbose()) { + System.out.print("Offline registration page: " + htmlFile); + System.out.println((htmlFile.exists() ? + "" : " not exist. Use register.html")); + } + if (htmlFile.exists()) { + return htmlFile; + } else { + return new File(parent, + REGISTRATION_HTML_NAME + ".html"); + } + } + + private static List<Locale> getCandidateLocales(Locale locale) { + String language = locale.getLanguage(); + String country = locale.getCountry(); + String variant = locale.getVariant(); + + List<Locale> locales = new ArrayList<Locale>(3); + if (variant.length() > 0) { + locales.add(locale); + } + if (country.length() > 0) { + locales.add((locales.size() == 0) ? + locale : new Locale(language, country, "")); + } + if (language.length() > 0) { + locales.add((locales.size() == 0) ? + locale : new Locale(language, "", "")); + } + return locales; + } + + // Remove the offline registration pages + private static void deleteRegistrationHtmlPage() throws IOException { + String parent = getRegisterHtmlParent(); + if (parent == null) { + return; + } + + for (Locale locale : supportedLocales) { + String name = REGISTRATION_HTML_NAME; + if (!locale.equals(Locale.ENGLISH)) { + name += "_" + locale.toString(); + } + File f = new File(parent, name + ".html"); + if (f.exists()) { + if (!f.delete()) { + throw new IOException("Failed to delete " + f); + } + } + } + } + + private static void initSupportedLocales(File jdkDir) { + if (supportedLocales.isEmpty()) { + // initialize with the known supported locales + for (Locale l : knownSupportedLocales) { + supportedLocales.add(l); + } + } + + // Determine unknown supported locales if any + // by finding the localized version of README.html + // This prepares if a new locale in JDK is supported in + // e.g. in the OpenSource world + FilenameFilter ff = new FilenameFilter() { + public boolean accept(File dir, String name) { + String fname = name.toLowerCase(); + if (fname.startsWith("readme") && fname.endsWith(".html")) { + return true; + } + return false; + } + }; + + String[] readmes = jdkDir.list(ff); + for (String name : readmes) { + String basename = name.substring(0, name.length() - ".html".length()); + String[] ss = basename.split("_"); + switch (ss.length) { + case 1: + // English version + break; + case 2: + supportedLocales.add(new Locale(ss[1])); + break; + case 3: + supportedLocales.add(new Locale(ss[1], ss[2])); + break; + default: + // ignore + break; + } + } + if (isVerbose()) { + System.out.println("Supported locales: "); + for (Locale l : supportedLocales) { + System.out.println(l); + } + } + } + + private static final String JDK_HEADER_PNG_KEY = "@@JDK_HEADER_PNG@@"; + private static final String JDK_VERSION_KEY = "@@JDK_VERSION@@"; + private static final String REGISTRATION_URL_KEY = "@@REGISTRATION_URL@@"; + private static final String REGISTRATION_PAYLOAD_KEY = "@@REGISTRATION_PAYLOAD@@"; + + @SuppressWarnings("unchecked") + private static void generateRegisterHtml(String parent) throws IOException { + int version = Util.getJdkVersion(); + int update = Util.getUpdateVersion(); + String jdkVersion = "Version " + version; + if (update > 0) { + // product name is not translated + jdkVersion += " Update " + update; + } + RegistrationData regData = getRegistrationData(); + String registerURL = SunConnection.getRegistrationURL( + regData.getRegistrationURN()).toString(); + // Make sure it uses the canonical path before getting the URI. + File img = new File(svcTagDir.getCanonicalPath(), "jdk_header.png"); + String headerImageSrc = img.toURI().toString(); + + // Format the registration data in one single line + StringBuilder payload = new StringBuilder(); + String xml = regData.toString().replaceAll("\"", "%22"); + BufferedReader reader = new BufferedReader(new StringReader(xml)); + try { + String line = null; + while ((line = reader.readLine()) != null) { + payload.append(line.trim()); + } + } finally { + reader.close(); + } + + String resourceFilename = "/com/sun/servicetag/resources/register"; + for (Locale locale : supportedLocales) { + String name = REGISTRATION_HTML_NAME; + String resource = resourceFilename; + if (!locale.equals(Locale.ENGLISH)) { + name += "_" + locale.toString(); + resource += "_" + locale.toString(); + } + File f = new File(parent, name + ".html"); + InputStream in = null; + BufferedReader br = null; + PrintWriter pw = null; + try { + in = Installer.class.getClass().getResourceAsStream(resource + ".html"); + if (in == null) { + // if the resource file is missing + if (isVerbose()) { + System.out.println("Missing resouce file: " + resource + ".html"); + } + continue; + } + if (isVerbose()) { + System.out.println("Generating " + f + " from " + resource + ".html"); + } + + br = new BufferedReader(new InputStreamReader(in, "UTF-8")); + pw = new PrintWriter(f, "UTF-8"); + String line = null; + while ((line = br.readLine()) != null) { + String output = line; + if (line.contains(JDK_VERSION_KEY)) { + output = line.replace(JDK_VERSION_KEY, jdkVersion); + } else if (line.contains(JDK_HEADER_PNG_KEY)) { + output = line.replace(JDK_HEADER_PNG_KEY, headerImageSrc); + } else if (line.contains(REGISTRATION_URL_KEY)) { + output = line.replace(REGISTRATION_URL_KEY, registerURL); + } else if (line.contains(REGISTRATION_PAYLOAD_KEY)) { + output = line.replace(REGISTRATION_PAYLOAD_KEY, payload.toString()); + } + pw.println(output); + } + f.setReadOnly(); + pw.flush(); + } finally { + if (pw != null) { + pw.close(); + } + if (in != null) { + in.close(); + } + if (br!= null) { + br.close(); + } + } + } + } + + /** + * A utility class to create a service tag for Java SE. + * <p> + * <b>Usage:</b><br> + * <blockquote><tt> + * <JAVA_HOME>/bin/java com.sun.servicetag.Installer + * </tt></blockquote> + * <p> + */ + public static void main(String[] args) { + String source = "Manual"; + + // Parse the options (arguments starting with "-" ) + boolean delete = false; + boolean update = false; + boolean register = false; + int count = 0; + while (count < args.length) { + String arg = args[count]; + if (arg.trim().length() == 0) { + // skip empty arguments + count++; + continue; + } + + if (arg.equals("-source")) { + source = args[++count]; + } else if (arg.equals("-delete")) { + delete = true; + } else if (arg.equals("-register")) { + register = true; + } else { + usage(); + return; + } + count++; + } + try { + if (delete) { + deleteRegistrationData(); + } else { + ServiceTag[] javaSvcTags = getJavaServiceTagArray(); + String[] archs = getJreArchs(); + if (javaSvcTags.length > archs.length) { + // 64-bit has been uninstalled + // so remove the service tag + updateRegistrationData(source); + } else { + // create the service tag + createServiceTag(source); + } + } + + if (register) { + // Registration is only supported by JDK + // For testing purpose, override with a "servicetag.enable.registration" property + + RegistrationData regData = getRegistrationData(); + if (supportRegistration && !regData.getServiceTags().isEmpty()) { + SunConnection.register(regData); + } + } + System.exit(0); + } catch (IOException e) { + System.err.println("I/O Error: " + e.getMessage()); + if (isVerbose()) { + e.printStackTrace(); + } + } catch (IllegalArgumentException ex) { + if (isVerbose()) { + ex.printStackTrace(); + } + } catch (Exception e) { + System.err.println("Error: " + e.getMessage()); + if (isVerbose()) { + e.printStackTrace(); + } + } + System.exit(1); + } + + private static void usage() { + System.out.println("Usage:"); + System.out.print(" " + Installer.class.getName()); + System.out.println(" [-delete|-source <source>|-register]"); + System.out.println(" to create a service tag for the Java platform"); + System.out.println(""); + System.out.println("Internal Options:"); + System.out.println(" -source: to specify the source of the service tag to be created"); + System.out.println(" -delete: to delete the service tag "); + System.out.println(" -register: to register the JDK"); + System.out.println(" -help: to print this help message"); + } +} diff --git a/desktop/source/registration/com/sun/star/servicetag/LinuxSystemEnvironment.java b/desktop/source/registration/com/sun/star/servicetag/LinuxSystemEnvironment.java new file mode 100644 index 000000000000..f81d93589180 --- /dev/null +++ b/desktop/source/registration/com/sun/star/servicetag/LinuxSystemEnvironment.java @@ -0,0 +1,323 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + + +package com.sun.star.servicetag; + +// The Service Tags team maintains the latest version of the implementation +// for system environment data collection. JDK will include a copy of +// the most recent released version for a JDK release. We rename +// the package to com.sun.servicetag so that the Sun Connection +// product always uses the latest version from the com.sun.scn.servicetags +// package. JDK and users of the com.sun.servicetag API +// (e.g. NetBeans and SunStudio) will use the version in JDK. + +import java.io.*; +import java.util.*; + +/** + * Linux implementation of the SystemEnvironment class. + */ +class LinuxSystemEnvironment extends SystemEnvironment { + LinuxSystemEnvironment() { + setHostId(getLinuxHostId()); + + setSystemModel(getLinuxModel()); + setSystemManufacturer(getLinuxSystemManufacturer()); + setCpuManufacturer(getLinuxCpuManufacturer()); + setSerialNumber(getLinuxSN()); + setPhysMem(getLinuxPhysMem()); + setSockets(getLinuxSockets()); + setCores(getLinuxCores()); + setVirtCpus(getLinuxVirtCpus()); + setCpuName(getLinuxCpuName()); + setClockRate(getLinuxClockRate()); + } + private String dmiInfo = null; + private String kstatCpuInfo = null; + + private static final int SN = 1; + private static final int SYS = 2; + private static final int CPU = 3; + private static final int MODEL = 4; + + private String getLinuxHostId() { + String output = getCommandOutput("/usr/bin/hostid"); + // trim off the leading 0x + if (output.startsWith("0x")) { + output = output.substring(2); + } + return output; + } + + /** + * Tries to obtain and return the cpu manufacturer. + * @return The cpu manufacturer (an empty string if not found or an error occurred) + */ + private String getLinuxCpuManufacturer() { + String tmp = getLinuxPSNInfo(CPU); + if (tmp.length() > 0) { + return tmp; + } + + String contents = getFileContent("/proc/cpuinfo"); + for (String line : contents.split("\n")) { + if (line.contains("vendor_id")) { + String[] ss = line.split(":", 2); + if (ss.length > 1) { + return ss[1].trim(); + } + } + } + + // returns an empty string if it can't be found or an error happened + return getLinuxDMIInfo("dmi type 4", "manufacturer"); + } + + private String getLinuxModel() { + String tmp = getLinuxPSNInfo(MODEL); + if (tmp.length() > 0) { + return tmp + "::" + getCommandOutput("/bin/uname","-v"); + } + + tmp = getLinuxDMIInfo("dmi type 1", "product name"); + if (tmp.length() > 0) { + return tmp + "::" + getCommandOutput("/bin/uname","-v"); + } + + return getCommandOutput("/bin/uname","-i") + + "::" + getCommandOutput("/bin/uname","-v"); + } + + + /** + * Tries to obtain and return the system manufacturer. + * @return The system manufacturer (an empty string if not found or an error occurred) + */ + private String getLinuxSystemManufacturer() { + String tmp = getLinuxPSNInfo(SYS); + if (tmp.length() > 0) { + return tmp; + } + + // returns an empty string if it can't be found or an error happened + return getLinuxDMIInfo("dmi type 1", "manufacturer"); + } + + /** + * Tries to obtain and return the serial number of the system. + * @return The serial number (an empty string if not found or an error occurred) + */ + private String getLinuxSN() { + String tmp = getLinuxPSNInfo(SN); + if (tmp.length() > 0) { + return tmp; + } + + // returns an empty string if it can't be found or an error happened + return getLinuxDMIInfo("dmi type 1", "serial number"); + } + + private String getLinuxPSNInfo(int target) { + // try to read from the psn file if it exists + String contents = getFileContent("/var/run/psn"); + String[] ss = contents.split("\n"); + if (target <= ss.length) { + return ss[target-1]; + } + + // default case is to return "" + return ""; + } + + // reads from dmidecode with the given type and target + // returns an empty string if nothing was found or an error occurred + // + // Sample output segment: + // Handle 0x0001 + // DMI type 1, 25 bytes. + // System Information + // Manufacturer: System manufacturer + // Product Name: System Product Name + // Version: System Version + // Serial Number: System Serial Number + // UUID: 3091D719-B25B-D911-959D-6D1B12C7686E + // Wake-up Type: Power Switch + + private synchronized String getLinuxDMIInfo(String dmiType, String target) { + // only try to get dmidecode information once, after that, we can + // reuse the output + if (dmiInfo == null) { + Thread dmidecodeThread = new Thread() { + public void run() { + dmiInfo = getCommandOutput("/usr/sbin/dmidecode"); + } + }; + dmidecodeThread.start(); + + try { + dmidecodeThread.join(3000); + if (dmidecodeThread.isAlive()) { + dmidecodeThread.interrupt(); + dmiInfo = ""; + } + } catch (InterruptedException ie) { + dmidecodeThread.interrupt(); + } + } + + if (dmiInfo.length() == 0) { + return ""; + } + boolean dmiFlag = false; + for (String s : dmiInfo.split("\n")) { + String line = s.toLowerCase(); + if (dmiFlag) { + if (line.contains(target)) { + String key = target + ":"; + int indx = line.indexOf(key) + key.length(); + if (line.contains(key) && indx < line.length()) { + return line.substring(indx).trim(); + } + String[] ss = line.split(":"); + return ss[ss.length-1]; + } + } else if (line.contains(dmiType)) { + dmiFlag = true; + } + } + return ""; + } + + private String getLinuxClockRate() { + String contents = getFileContent("/proc/cpuinfo"); + String token = "cpu MHz"; + for (String line : contents.split("\n")) { + if (line.contains(token)) { + String[] key = line.split(":", 2); + if (key.length > 1) { + return key[1].trim(); + } + } + } + return ""; + } + + private String getLinuxCpuName() { + String contents = getFileContent("/proc/cpuinfo"); + String token = "model name"; + for (String line : contents.split("\n")) { + if (line.contains(token)) { + String[] key = line.split(":", 2); + if (key.length > 1) { + return key[1].trim(); + } + } + } + return ""; + } + + private String getLinuxVirtCpus() { + Set<String> set = new HashSet<String>(); + String contents = getFileContent("/proc/cpuinfo"); + String token = "processor"; + for (String line : contents.split("\n")) { + if (line.contains(token)) { + String[] key = line.split(":", 2); + if (key.length > 1) { + set.add(key[1].trim()); + } + } + } + return "" + set.size(); + } + + private String getLinuxCores() { + Set<String> set = new HashSet<String>(); + String contents = getFileContent("/proc/cpuinfo"); + String token = "core id"; + for (String line : contents.split("\n")) { + if (line.contains(token)) { + String[] key = line.split(":", 2); + if (key.length > 1) { + set.add(key[1].trim()); + } + } + } + if (set.size() == 0) { + return "1"; + } + return "" + set.size(); + } + + private String getLinuxPhysMem() { + String contents = getFileContent("/proc/meminfo"); + for (String line : contents.split("\n")) { + if (line.contains("MemTotal")) { + String[] total = line.split(":", 2); + if (total.length > 1) { + String[] mem = total[1].trim().split(" "); + if (mem.length >= 1) { + return mem[0].trim(); + } else { + return total[1].trim(); + } + } + } + } + + return ""; + } + + private String getLinuxSockets() { + Set<String> physIdSet = new HashSet<String>(); + Set<String> procSet = new HashSet<String>(); + String contents = getFileContent("/proc/cpuinfo"); + String physIdToken = "physical id"; + String procToken = "processor"; + + for (String line : contents.split("\n")) { + if (line.contains(physIdToken)) { + String[] key = line.split(":", 2); + if (key.length > 1) { + physIdSet.add(key[1].trim()); + } + } + + if (line.contains(procToken)) { + String[] key = line.split(":", 2); + if (key.length > 1) { + procSet.add(key[1].trim()); + } + } + } + if (physIdSet.size() != 0) { + return "" + physIdSet.size(); + } + return "" + procSet.size(); + } +} diff --git a/desktop/source/registration/com/sun/star/servicetag/RegistrationData.java b/desktop/source/registration/com/sun/star/servicetag/RegistrationData.java new file mode 100644 index 000000000000..9323e5de7e4e --- /dev/null +++ b/desktop/source/registration/com/sun/star/servicetag/RegistrationData.java @@ -0,0 +1,531 @@ + +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2008 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can obtain + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. + * Sun designates this particular file as subject to the "Classpath" exception + * as provided by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the License + * Header, with the fields enclosed by brackets [] replaced by your own + * identifying information: "Portions Copyrighted [year] + * [name of copyright owner]" + * + * Contributor(s): + * + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ + +package com.sun.star.servicetag; + +import java.io.*; +import java.net.UnknownHostException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import static com.sun.star.servicetag.RegistrationDocument.*; + +/** + * A {@code RegistrationData} object is a container of one or more + * {@link #getServiceTags service tags} that identify the + * components for product registration. + * Each {@code RegistrationData} object has a {@link #getRegistrationURN + * uniform resource name} (URN) as its identifier. + * <a name="EnvMap"></a> + * It also has an <i>environment map</i> with + * the following elements: + * <blockquote> + * <table border=0> + * <tr> + * <td><tt>hostname</tt></td> + * <td>Hostname of the system</td> + * <td>e.g. woody</td> + * </tr> + * <tr> + * <td><tt>hostId</tt></td> + * <td>Host ID of the system</td> + * <td>e.g. 83abc1ab</td> + * </tr> + * <tr> + * <td><tt>osName</tt></td> + * <td>Operating system name</td> + * <td> e.g. SunOS</td> + * </tr> + * <tr> + * <td><tt>osVersion</tt></td> + * <td>Operating system version</td> + * <td> e.g. 5.10</td> + * </tr> + * <tr> + * <td><tt>osArchitecture</tt></td> + * <td>Operating system architecture</td> + * <td> e.g. sparc</td> + * </tr> + * <tr> + * <td><tt>systemModel</tt></td> + * <td>System model</td> + * <td> e.g. SUNW,Sun-Fire-V440</td> + * </tr> + * <tr> + * <td><tt>systemManufacturer</tt></td> + * <td>System manufacturer</td> + * <td> e.g. Sun Microsystems</td> + * </tr> + * <tr> + * <td><tt>cpuManufacturer</tt></td> + * <td>CPU manufacturer</td> + * <td> e.g. Sun Microsystems</td> + * </tr> + * <tr> + * <td><tt>serialNumber</tt></td> + * <td>System serial number</td> + * <td> e.g. BEL078932</td> + * </tr> + * <tr> + * <td><tt>physmem</tt></td> + * <td>Physical memory for the system (in MB)</td> + * <td> e.g. 4096</td> + * </tr> + * </table> + * </blockquote> + * The <tt>hostname</tt> and <tt>osName</tt> element must have a non-empty value. + * If an element is not available on a system and their value will be + * empty. + * <p> + * <a name="XMLSchema"> + * <b>Registration XML Schema</b></a> + * <p> + * A {@code RegistrationData} object can be {@link #loadFromXML loaded} from + * and {@link #storeToXML stored} into an XML file in the format described + * by the + * <a href="https://sn-tools.central.sun.com/twiki/pub/ServiceTags/RegistrationRelayService/product_registration.xsd"> + * registration data schema</a>. The registration data schema is defined by the + * Service Tags Technology. + * <p> + * Typically the registration data is constructed at installation time + * and stored in an XML file for later service tag lookup or registration. + * + * <p> + * <b>Example Usage</b> + * <p> + * The examples below show how the {@code RegistrationData} can be + * used for product registration. + * Exception handling is not shown in these examples for clarity. + * <ol> + * <li>This example shows how the JDK creates a JDK service tag, installs it + * in the system service tag registry and adds it to the registration data. + * <br> + * <blockquote><pre> + * // create a service tag object with an instance_urn + * ServiceTag st = ServiceTag.newInstance(ServiceTag.generateInstanceURN(), + * ....); + * // Adds to the system service tag registry if supported + * if (Registry.isSupported()) { + * Registry.getSystemRegistry().addServiceTag(st); + * } + * + * // add to the registration data + * RegistrationData registration = new RegistrationData(); + * registration.addServiceTag(st); + * </pre></blockquote> + * </li> + * <li>At this point, the registration data is ready to + * send to Sun Connection for registration. This example shows how to register + * the JDK via the <i>Registration Relay Service</i>. + * <p> + * There are several registration services for Sun Connection. For example, + * the <a href="https://sn-tools.central.sun.com/twiki/bin/view/ServiceTags/RegistrationRelayService"> + * Registration Relay Service</a> is a web application interface that + * processes the registration data payload sent via HTTP post + * and hosts the registration user interface for a specified + * registration URL. Refer to the + * Registration Relay Service Specification for details. + * <p> + * <blockquote><pre> + * // Open the connection to the URL of the registration service + * HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); + * con.setDoInput(true); + * con.setDoOutput(true); + * con.setUseCaches(false); + * con.setAllowUserInteraction(false); + * con.setRequestMethod("POST"); + * con.setRequestProperty("Content-Type", "text/xml;charset=\"utf-8\""); + * con.connect(); + * + * // send the registration data to the registration service + * OutputStream out = con.getOutputStream(); + * registration.storeToXML(out); + * out.close(); + * </pre></blockquote> + * </li> + * <li>This example shows how to store the registration data in an XML file. + * for later service tag lookup or registration. + * <br> + * <blockquote><pre> + * BufferedOutputStream out = new BufferedOutputStream( + * new FileOutputStream(""<JAVA_HOME>/lib/servicetag/registration.xml")); + * registration.storeToXML(out); + * out.close(); + * </pre></blockquote> + * </li> + * <li>This example shows how to install service tags that are in the + * registration data in the system service tag registry when determined + * to be available. The system service tag registry might not have existed + * when the registration data was constructed. + * <br> + * <blockquote><pre> + * if (Registry.isSupported()) { + * Set<ServiceTag> svctags = registration.getServiceTags(); + * for (ServiceTag st : svctags) { + * Registry.getSystemRegistry().addServiceTag(st); + * } + * } + * </pre></blockquote> + * </li> + * </ol> + * + * @see <a href="https://sunconnection.sun.com/inventory">Sun Connection Inventory Channel</a> + */ +public class RegistrationData { + private final Map<String, String> environment; + private final Map<String, String> cpuInfo; + private final Map<String, ServiceTag> svcTagMap; + private final String urn; + + /** + * Creates a {@code RegistrationData} object with a generated + * {@link #getRegistrationURN registration URN}. + * The following keys in the {@link #getEnvironmentMap environment map} + * will be initialized for the configuration of the + * running system: + * <blockquote> + * <tt>hostname</tt>, <tt>osName</tt>, <tt>osVersion</tt> and + * <tt>osArchitecture</tt> + * </blockquote> + * and the value of other keys may be empty. + */ + public RegistrationData() { + this(Util.generateURN()); + } + + // package private + RegistrationData(String urn) { + this.urn = urn; + SystemEnvironment sysEnv = SystemEnvironment.getSystemEnvironment(); + this.environment = initEnvironment(sysEnv); + this.cpuInfo = initCpuInfo(sysEnv); + this.svcTagMap = new LinkedHashMap<String, ServiceTag>(); + } + + private Map<String, String> initEnvironment(SystemEnvironment sysEnv) { + Map<String, String> map = new LinkedHashMap<String, String>(); + map.put(ST_NODE_HOSTNAME, sysEnv.getHostname()); + map.put(ST_NODE_HOST_ID, sysEnv.getHostId()); + map.put(ST_NODE_OS_NAME, sysEnv.getOsName()); + map.put(ST_NODE_OS_VERSION, sysEnv.getOsVersion()); + map.put(ST_NODE_OS_ARCH, sysEnv.getOsArchitecture()); + map.put(ST_NODE_SYSTEM_MODEL, sysEnv.getSystemModel()); + map.put(ST_NODE_SYSTEM_MANUFACTURER, sysEnv.getSystemManufacturer()); + map.put(ST_NODE_CPU_MANUFACTURER, sysEnv.getCpuManufacturer()); + map.put(ST_NODE_SERIAL_NUMBER, sysEnv.getSerialNumber()); + map.put(ST_NODE_PHYS_MEM, sysEnv.getPhysMem()); + return map; + } + + private Map<String, String> initCpuInfo(SystemEnvironment sysEnv) { + Map<String, String> map = new LinkedHashMap<String, String>(); + map.put(ST_NODE_SOCKETS, sysEnv.getSockets()); + map.put(ST_NODE_CORES, sysEnv.getCores()); + map.put(ST_NODE_VIRT_CPUS, sysEnv.getVirtCpus()); + map.put(ST_NODE_CPU_NAME, sysEnv.getCpuName()); + map.put(ST_NODE_CLOCK_RATE, sysEnv.getClockRate()); + return map; + } + + /** + * Returns the uniform resource name of this registration data + * in this format: + * <tt>urn:st:<32-char {@link java.util.UUID uuid}></tt> + * + * @return the URN of this registration data. + */ + public String getRegistrationURN() { + return urn; + } + + /** + * Returns a map containing the environment information for this + * registration data. See the set of <a href="#EnvMap">keys</a> + * in the environment map. Subsequent update to the environment + * map via the {@link #setEnvironment setEnvironment} method will not be reflected + * in the returned map. + * + * @return an environment map for this registration data. + */ + public Map<String, String> getEnvironmentMap() { + return new LinkedHashMap<String,String>(environment); + } + + /** + * Returns a map containing the cpu information for this + * registration data. Subsequent update to the cpu info + * map via the {@link #setCpuInfo setCpuInfo} method will not be reflected + * in the returned map. + * + * @return a cpu info map for this registration data. + */ + public Map<String, String> getCpuInfoMap() { + return new LinkedHashMap<String,String>(cpuInfo); + } + + /** + * Sets an element of the specified {@code name} in the environment map + * with the given {@code value}. + * + * @throws IllegalArgumentException if {@code name} is not a valid key + * in the environment map, or {@code value} is not valid. + */ + public void setEnvironment(String name, String value) { + if (name == null) { + throw new NullPointerException("name is null"); + } + if (value == null) { + throw new NullPointerException("value is null"); + } + if (environment.containsKey(name)) { + if (name.equals(ST_NODE_HOSTNAME) || name.equals(ST_NODE_OS_NAME)) { + if (value.length() == 0) { + throw new IllegalArgumentException("\"" + + name + "\" requires non-empty value."); + } + } + environment.put(name, value); + } else { + throw new IllegalArgumentException("\"" + + name + "\" is not an environment element."); + } + } + + /** + * Sets an element of the specified {@code name} in the cpu info map + * with the given {@code value}. + * + * @throws IllegalArgumentException if {@code name} is not a valid key + * in the cpu info map, or {@code value} is not valid. + */ + public void setCpuInfo(String name, String value) { + if (name == null) { + throw new NullPointerException("name is null"); + } + if (value == null) { + throw new NullPointerException("value is null"); + } + if (cpuInfo.containsKey(name)) { + cpuInfo.put(name, value); + } else { + throw new IllegalArgumentException("\"" + + name + "\" is not an cpuinfo element."); + } + } + + /** + * Returns all service tags in this registration data. + * + * @return a {@link Set Set} of the service tags + * in this registration data. + */ + public Set<ServiceTag> getServiceTags() { + return new HashSet<ServiceTag>(svcTagMap.values()); + } + + /** + * Adds a service tag to this registration data. + * If the given service tag has an empty <tt>instance_urn</tt>, + * this method will generate a URN and place it in the copy + * of the service tag in this registration data. + * This method will return the {@code ServiceTag} object + * added to this registration data. + * + * @param st {@code ServiceTag} object to be added. + * @return a {@code ServiceTag} object added to this registration data. + * + * @throws IllegalArgumentException if + * a service tag of the same {@link ServiceTag#getInstanceURN + * <tt>instance_urn</tt>} already exists in the registry. + */ + public synchronized ServiceTag addServiceTag(ServiceTag st) { + ServiceTag svcTag = ServiceTag.newInstanceWithUrnTimestamp(st); + + String instanceURN = svcTag.getInstanceURN(); + if (svcTagMap.containsKey(instanceURN)) { + throw new IllegalArgumentException("Instance_urn = " + instanceURN + + " already exists in the registration data."); + } else { + svcTagMap.put(instanceURN, svcTag); + } + return svcTag; + } + + /** + * Returns a service tag of the given <tt>instance_urn</tt> in this registration + * data. + * + * @param instanceURN the <tt>instance_urn</tt> of the service tag + * @return the {@code ServiceTag} object of the given <tt>instance_urn</tt> + * if exists; otherwise return {@code null}. + */ + public synchronized ServiceTag getServiceTag(String instanceURN) { + if (instanceURN == null) { + throw new NullPointerException("instanceURN is null"); + } + return svcTagMap.get(instanceURN); + } + + /** + * Removes a service tag of the given <tt>instance_urn</tt> from this + * registration data. + * + * @param instanceURN the <tt>instance_urn</tt> of + * the service tag to be removed. + * + * @return the removed {@code ServiceTag} object; + * or {@code null} if the service tag does not exist in this + * registration data. + */ + public synchronized ServiceTag removeServiceTag(String instanceURN) { + if (instanceURN == null) { + throw new NullPointerException("instanceURN is null"); + } + + ServiceTag svcTag = null; + if (svcTagMap.containsKey(instanceURN)) { + svcTag = svcTagMap.remove(instanceURN); + } + return svcTag; + } + + /** + * Updates the <tt>product_defined_instance_id</tt> in the service tag + * of the given <tt>instance_urn</tt> in this registration data. + * + * @param instanceURN the <tt>instance_urn</tt> of the service tag to be updated. + * @param productDefinedInstanceID the value of the + * <tt>product_defined_instance_id</tt> to be set. + * + * @return the updated {@code ServiceTag} object; + * or {@code null} if the service tag does not exist in this + * registration data. + */ + public synchronized ServiceTag updateServiceTag(String instanceURN, + String productDefinedInstanceID) { + ServiceTag svcTag = getServiceTag(instanceURN); + if (svcTag == null) { + return null; + } + + svcTag = ServiceTag.newInstanceWithUrnTimestamp(svcTag); + // update the product defined instance ID field + svcTag.setProductDefinedInstanceID(productDefinedInstanceID); + svcTagMap.put(instanceURN, svcTag); + return svcTag; + } + + /** + * Reads the registration data from the XML document on the + * specified input stream. The XML document must be + * in the format described by the <a href="#XMLSchema"> + * registration data schema</a>. + * The specified stream is closed after this method returns. + * + * @param in the input stream from which to read the XML document. + * @return a {@code RegistrationData} object read from the input + * stream. + * + * @throws IllegalArgumentException if the input stream + * contains an invalid registration data. + * + * @throws IOException if an error occurred when reading from the input stream. + */ + public static RegistrationData loadFromXML(InputStream in) throws IOException { + try { + return RegistrationDocument.load(in); + } finally { + in.close(); + } + } + + /** + * Writes the registration data to the specified output stream + * in the format described by the <a href="#XMLSchema"> + * registration data schema</a> with "UTF-8" encoding. + * The specified stream remains open after this method returns. + * + * @param os the output stream on which to write the XML document. + * + * @throws IOException if an error occurred when writing to the output stream. + */ + public void storeToXML(OutputStream os) throws IOException { + RegistrationDocument.store(os, this); + os.flush(); + } + + /** + * Returns a newly allocated byte array containing the registration + * data in XML format. + * + * @return a newly allocated byte array containing the registration + * data in XML format. + */ + public byte[] toXML() { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + storeToXML(out); + return out.toByteArray(); + } catch (IOException e) { + // should not reach here + return new byte[0]; + } + } + + /** + * Returns a string representation of this registration data in XML + * format. + * + * @return a string representation of this registration data in XML + * format. + */ + @Override + public String toString() { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + storeToXML(out); + return out.toString("UTF-8"); + } catch (IOException e) { + // should not reach here + return "Error creating the return string."; + } + } +} diff --git a/desktop/source/registration/com/sun/star/servicetag/RegistrationDocument.java b/desktop/source/registration/com/sun/star/servicetag/RegistrationDocument.java new file mode 100644 index 000000000000..4bfa1aa16af6 --- /dev/null +++ b/desktop/source/registration/com/sun/star/servicetag/RegistrationDocument.java @@ -0,0 +1,440 @@ + +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2008 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can obtain + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. + * Sun designates this particular file as subject to the "Classpath" exception + * as provided by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the License + * Header, with the fields enclosed by brackets [] replaced by your own + * identifying information: "Portions Copyrighted [year] + * [name of copyright owner]" + * + * Contributor(s): + * + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ + +package com.sun.star.servicetag; + +import java.io.*; +import java.net.URL; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; +import org.xml.sax.InputSource; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; + +// For write operation +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +/** + * XML Support Class for Product Registration. + */ +class RegistrationDocument { + + private static final String REGISTRATION_DATA_SCHEMA = + "/com/sun/star/servicetag/resources/product_registration.xsd"; + private static final String REGISTRATION_DATA_VERSION = "1.0"; + private static final String SERVICE_TAG_VERSION = "1.0"; + final static String ST_NODE_REGISTRATION_DATA = "registration_data"; + final static String ST_ATTR_REGISTRATION_VERSION = "version"; + final static String ST_NODE_ENVIRONMENT = "environment"; + final static String ST_NODE_HOSTNAME = "hostname"; + final static String ST_NODE_HOST_ID = "hostId"; + final static String ST_NODE_OS_NAME = "osName"; + final static String ST_NODE_OS_VERSION = "osVersion"; + final static String ST_NODE_OS_ARCH = "osArchitecture"; + final static String ST_NODE_SYSTEM_MODEL = "systemModel"; + final static String ST_NODE_SYSTEM_MANUFACTURER = "systemManufacturer"; + final static String ST_NODE_CPU_MANUFACTURER = "cpuManufacturer"; + final static String ST_NODE_SERIAL_NUMBER = "serialNumber"; + final static String ST_NODE_PHYS_MEM = "physmem"; + final static String ST_NODE_CPU_INFO = "cpuinfo"; + final static String ST_NODE_SOCKETS = "sockets"; + final static String ST_NODE_CORES = "cores"; + final static String ST_NODE_VIRT_CPUS = "virtcpus"; + final static String ST_NODE_CPU_NAME = "name"; + final static String ST_NODE_CLOCK_RATE = "clockrate"; + final static String ST_NODE_REGISTRY = "registry"; + final static String ST_ATTR_REGISTRY_URN = "urn"; + final static String ST_ATTR_REGISTRY_VERSION = "version"; + final static String ST_NODE_SERVICE_TAG = "service_tag"; + final static String ST_NODE_INSTANCE_URN = "instance_urn"; + final static String ST_NODE_PRODUCT_NAME = "product_name"; + final static String ST_NODE_PRODUCT_VERSION = "product_version"; + final static String ST_NODE_PRODUCT_URN = "product_urn"; + final static String ST_NODE_PRODUCT_PARENT_URN = "product_parent_urn"; + final static String ST_NODE_PRODUCT_PARENT = "product_parent"; + final static String ST_NODE_PRODUCT_DEFINED_INST_ID = "product_defined_inst_id"; + final static String ST_NODE_PRODUCT_VENDOR = "product_vendor"; + final static String ST_NODE_PLATFORM_ARCH = "platform_arch"; + final static String ST_NODE_TIMESTAMP = "timestamp"; + final static String ST_NODE_CONTAINER = "container"; + final static String ST_NODE_SOURCE = "source"; + final static String ST_NODE_INSTALLER_UID = "installer_uid"; + + static RegistrationData load(InputStream in) throws IOException { + Document document = initializeDocument(in); + + // Gets the registration URN + Element root = getRegistrationDataRoot(document); + Element registryRoot = + getSingletonElementFromRoot(root, ST_NODE_REGISTRY); + String urn = registryRoot.getAttribute(ST_ATTR_REGISTRY_URN); + + // Construct a new RegistrationData object from the DOM tree + // Initialize the environment map and service tags + RegistrationData regData = new RegistrationData(urn); + addServiceTags(registryRoot, regData); + + Element envRoot = getSingletonElementFromRoot(root, ST_NODE_ENVIRONMENT); + buildEnvironmentMap(envRoot, regData); + + Element cpuInfo = getSingletonElementFromRoot(envRoot, ST_NODE_CPU_INFO); + buildCpuInfoMap(cpuInfo, regData); + return regData; + } + + static void store(OutputStream os, RegistrationData registration) + throws IOException { + // create a new document with the root node + Document document = initializeDocument(); + + // create the nodes for the environment map and the service tags + // in the registration data + addEnvironmentNodes(document, + registration.getEnvironmentMap(), + registration.getCpuInfoMap()); + addServiceTagRegistry(document, + registration.getRegistrationURN(), + registration.getServiceTags()); + transform(document, os); + } + + // initialize a document from an input stream + private static Document initializeDocument(InputStream in) throws IOException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + SchemaFactory sf = null; + try { + // Some Java versions (e.g., 1.5.0_06-b05) fail with a + // NullPointerException if SchemaFactory.newInstance is called with + // a null context class loader, so work around that here (and the + // class loader of this class hopefully is not the null bootstrap + // class loader): + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + if (cl == null) { + Thread.currentThread().setContextClassLoader( + RegistrationDocument.class.getClassLoader()); + } + try { + sf = SchemaFactory.newInstance( + XMLConstants.W3C_XML_SCHEMA_NS_URI); + } finally { + Thread.currentThread().setContextClassLoader(cl); + } + + Schema schema = null; + try { + // Even using the workaround above is not enough on some + // Java versions. Therefore try to workaround the validation + // completely! + URL xsdUrl = RegistrationDocument.class.getResource(REGISTRATION_DATA_SCHEMA); + schema = sf.newSchema(xsdUrl); + } + catch (NullPointerException nex) { + } + + Validator validator = null; + if (schema != null) + validator = schema.newValidator(); + + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.parse(new InputSource(in)); + + if (validator != null) + validator.validate(new DOMSource(doc)); + + return doc; + } catch (SAXException sxe) { + IllegalArgumentException e = new IllegalArgumentException("Error generated in parsing"); + e.initCause(sxe); + throw e; + } catch (ParserConfigurationException pce) { + // Parser with specific options can't be built + // should not reach here + InternalError x = new InternalError("Error in creating the new document"); + x.initCause(pce); + throw x; + } + } + + // initialize a new document for the registration data + private static Document initializeDocument() throws IOException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + try { + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.newDocument(); + + // initialize the document with the registration_data root + Element root = doc.createElement(ST_NODE_REGISTRATION_DATA); + doc.appendChild(root); + root.setAttribute(ST_ATTR_REGISTRATION_VERSION, REGISTRATION_DATA_VERSION); + + return doc; + } catch (ParserConfigurationException pce) { + // Parser with specified options can't be built + // should not reach here + InternalError x = new InternalError("Error in creating the new document"); + x.initCause(pce); + throw x; + } + } + + // Transform the current DOM tree with the given output stream. + private static void transform(Document document, OutputStream os) { + try { + // Use a Transformer for output + TransformerFactory tFactory = TransformerFactory.newInstance(); + tFactory.setAttribute("indent-number", new Integer(3)); + + Transformer transformer = tFactory.newTransformer(); + + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty(OutputKeys.METHOD, "xml"); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + transformer.setOutputProperty(OutputKeys.STANDALONE, "yes"); + transformer.transform(new DOMSource(document), + new StreamResult(new BufferedWriter(new OutputStreamWriter(os, "UTF-8")))); + } catch (UnsupportedEncodingException ue) { + // Should not reach here + InternalError x = new InternalError("Error generated during transformation"); + x.initCause(ue); + throw x; + } catch (TransformerConfigurationException tce) { + // Error generated by the parser + // Should not reach here + InternalError x = new InternalError("Error in creating the new document"); + x.initCause(tce); + throw x; + } catch (TransformerException te) { + // Error generated by the transformer + InternalError x = new InternalError("Error generated during transformation"); + x.initCause(te); + throw x; + } + } + + private static void addServiceTagRegistry(Document document, + String registryURN, + Set<ServiceTag> svcTags) { + // add service tag registry node and its attributes + Element reg = document.createElement(ST_NODE_REGISTRY); + reg.setAttribute(ST_ATTR_REGISTRY_URN, registryURN); + reg.setAttribute(ST_ATTR_REGISTRY_VERSION, SERVICE_TAG_VERSION); + + Element root = getRegistrationDataRoot(document); + root.appendChild(reg); + + // adds the elements for the service tags + for (ServiceTag st : svcTags) { + addServiceTagElement(document, reg, st); + } + } + + private static void addServiceTagElement(Document document, + Element registryRoot, + ServiceTag st) { + Element svcTag = document.createElement(ST_NODE_SERVICE_TAG); + registryRoot.appendChild(svcTag); + addChildElement(document, svcTag, + ST_NODE_INSTANCE_URN, st.getInstanceURN()); + addChildElement(document, svcTag, + ST_NODE_PRODUCT_NAME, st.getProductName()); + addChildElement(document, svcTag, + ST_NODE_PRODUCT_VERSION, st.getProductVersion()); + addChildElement(document, svcTag, + ST_NODE_PRODUCT_URN, st.getProductURN()); + addChildElement(document, svcTag, + ST_NODE_PRODUCT_PARENT_URN, st.getProductParentURN()); + addChildElement(document, svcTag, + ST_NODE_PRODUCT_PARENT, st.getProductParent()); + addChildElement(document, svcTag, + ST_NODE_PRODUCT_DEFINED_INST_ID, + st.getProductDefinedInstanceID()); + addChildElement(document, svcTag, + ST_NODE_PRODUCT_VENDOR, st.getProductVendor()); + addChildElement(document, svcTag, + ST_NODE_PLATFORM_ARCH, st.getPlatformArch()); + addChildElement(document, svcTag, + ST_NODE_TIMESTAMP, Util.formatTimestamp(st.getTimestamp())); + addChildElement(document, svcTag, + ST_NODE_CONTAINER, st.getContainer()); + addChildElement(document, svcTag, + ST_NODE_SOURCE, st.getSource()); + addChildElement(document, svcTag, + ST_NODE_INSTALLER_UID, + String.valueOf(st.getInstallerUID())); + } + + private static void addChildElement(Document document, Element root, + String element, String text) { + Element node = document.createElement(element); + node.appendChild(document.createTextNode(text)); + root.appendChild(node); + } + + // Constructs service tags from the document + private static void addServiceTags(Element registryRoot, + RegistrationData registration) { + NodeList children = registryRoot.getElementsByTagName(ST_NODE_SERVICE_TAG); + int length = (children == null ? 0 : children.getLength()); + for (int i = 0; i < length; i++) { + Element svcTagElement = (Element) children.item(i); + ServiceTag st = getServiceTag(svcTagElement); + registration.addServiceTag(st); + } + } + + // build environment map from the document + private static void buildEnvironmentMap(Element envRoot, + RegistrationData registration) { + registration.setEnvironment(ST_NODE_HOSTNAME, getTextValue(envRoot, ST_NODE_HOSTNAME)); + registration.setEnvironment(ST_NODE_HOST_ID, getTextValue(envRoot, ST_NODE_HOST_ID)); + registration.setEnvironment(ST_NODE_OS_NAME, getTextValue(envRoot, ST_NODE_OS_NAME)); + registration.setEnvironment(ST_NODE_OS_VERSION, getTextValue(envRoot, ST_NODE_OS_VERSION)); + registration.setEnvironment(ST_NODE_OS_ARCH, getTextValue(envRoot, ST_NODE_OS_ARCH)); + registration.setEnvironment(ST_NODE_SYSTEM_MODEL, getTextValue(envRoot, ST_NODE_SYSTEM_MODEL)); + registration.setEnvironment(ST_NODE_SYSTEM_MANUFACTURER, getTextValue(envRoot, ST_NODE_SYSTEM_MANUFACTURER)); + registration.setEnvironment(ST_NODE_CPU_MANUFACTURER, getTextValue(envRoot, ST_NODE_CPU_MANUFACTURER)); + registration.setEnvironment(ST_NODE_SERIAL_NUMBER, getTextValue(envRoot, ST_NODE_SERIAL_NUMBER)); + registration.setEnvironment(ST_NODE_PHYS_MEM, getTextValue(envRoot, ST_NODE_PHYS_MEM)); + } + + private static void buildCpuInfoMap(Element cpuInfoRoot, + RegistrationData registration) { + registration.setCpuInfo(ST_NODE_SOCKETS, getTextValue(cpuInfoRoot, ST_NODE_SOCKETS)); + registration.setCpuInfo(ST_NODE_CORES, getTextValue(cpuInfoRoot, ST_NODE_CORES)); + registration.setCpuInfo(ST_NODE_VIRT_CPUS, getTextValue(cpuInfoRoot, ST_NODE_VIRT_CPUS)); + registration.setCpuInfo(ST_NODE_CPU_NAME, getTextValue(cpuInfoRoot, ST_NODE_CPU_NAME)); + registration.setCpuInfo(ST_NODE_CLOCK_RATE, getTextValue(cpuInfoRoot, ST_NODE_CLOCK_RATE)); + } + + // add the nodes representing the environment map in the document + private static void addEnvironmentNodes(Document document, + Map<String, String> envMap, + Map<String, String> cpuInfoMap) { + Element root = getRegistrationDataRoot(document); + + Element env = document.createElement(ST_NODE_ENVIRONMENT); + root.appendChild(env); + Set<Map.Entry<String, String>> keys = envMap.entrySet(); + for (Map.Entry<String, String> entry : keys) { + addChildElement(document, env, entry.getKey(), entry.getValue()); + } + + Element cpuInfo = document.createElement(ST_NODE_CPU_INFO); + env.appendChild(cpuInfo); + keys = cpuInfoMap.entrySet(); + for (Map.Entry<String, String> entry : keys) { + addChildElement(document, cpuInfo, entry.getKey(), entry.getValue()); + } + } + + private static Element getRegistrationDataRoot(Document doc) { + Element root = doc.getDocumentElement(); + if (!root.getNodeName().equals(ST_NODE_REGISTRATION_DATA)) { + throw new IllegalArgumentException("Not a " + + ST_NODE_REGISTRATION_DATA + + " node \"" + root.getNodeName() + "\""); + } + return root; + } + + private static Element getSingletonElementFromRoot(Element root, String name) { + NodeList children = root.getElementsByTagName(name); + int length = (children == null ? 0 : children.getLength()); + if (length != 1) { + throw new IllegalArgumentException("Invalid number of " + name + + " nodes = " + length); + } + Element e = (Element) children.item(0); + if (!e.getNodeName().equals(name)) { + throw new IllegalArgumentException("Not a " + name + + " node \"" + e.getNodeName() + "\""); + } + return e; + } + + // Constructs one ServiceTag instance from a service tag element root + private static ServiceTag getServiceTag(Element svcTagElement) { + return new ServiceTag( + getTextValue(svcTagElement, ST_NODE_INSTANCE_URN), + getTextValue(svcTagElement, ST_NODE_PRODUCT_NAME), + getTextValue(svcTagElement, ST_NODE_PRODUCT_VERSION), + getTextValue(svcTagElement, ST_NODE_PRODUCT_URN), + getTextValue(svcTagElement, ST_NODE_PRODUCT_PARENT), + getTextValue(svcTagElement, ST_NODE_PRODUCT_PARENT_URN), + getTextValue(svcTagElement, ST_NODE_PRODUCT_DEFINED_INST_ID), + getTextValue(svcTagElement, ST_NODE_PRODUCT_VENDOR), + getTextValue(svcTagElement, ST_NODE_PLATFORM_ARCH), + getTextValue(svcTagElement, ST_NODE_CONTAINER), + getTextValue(svcTagElement, ST_NODE_SOURCE), + Util.getIntValue(getTextValue(svcTagElement, ST_NODE_INSTALLER_UID)), + Util.parseTimestamp(getTextValue(svcTagElement, ST_NODE_TIMESTAMP)) + ); + } + + private static String getTextValue(Element e, String tagName) { + String value = ""; + NodeList nl = e.getElementsByTagName(tagName); + if (nl != null && nl.getLength() > 0) { + Element el = (Element) nl.item(0); + Node node = el.getFirstChild(); + if (node != null) { + value = node.getNodeValue(); + } + } + return value; + } +} diff --git a/desktop/source/registration/com/sun/star/servicetag/Registry.java b/desktop/source/registration/com/sun/star/servicetag/Registry.java new file mode 100644 index 000000000000..d1b76071979b --- /dev/null +++ b/desktop/source/registration/com/sun/star/servicetag/Registry.java @@ -0,0 +1,554 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +package com.sun.star.servicetag; + +import java.io.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; + +import static com.sun.star.servicetag.Util.*; +import static com.sun.star.servicetag.RegistrationDocument.*; + +/** + * A service tag registry is a XML-based registry containing + * the list of {@link ServiceTag service tags} installed in the system. + * The {@code Registry} class provides interfaces + * to add, remove, update, and get a service tag from a service tag + * registry. + * This {@code Registry} class may not be supported + * on all systems. The {@link #isSupported} method + * can be called to determine if it is supported. + * <p> + * A registry may implement restrictions to only allow certain users + * to {@link #updateServiceTag update} and + * to {@link #removeServiceTag remove} a service tag record. Typically, + * only the owner of the service tag, the owner of the registry + * and superuser are authorized to update or remove a service tag in + * the registry. + * + * @see <a href="https://sn-tools.central.sun.com/twiki/bin/view/ServiceTags/ServiceTagDevGuideHelper"> + * Service Tag User Guide</a> + */ +public class Registry { + + private static final String STCLIENT_SOLARIS = "/usr/bin/stclient"; + private static final String STCLIENT_LINUX = "/opt/sun/servicetag/bin/stclient"; + // stclient exit value (see sthelper.h) + private static final int ST_ERR_NOT_AUTH = 245; + private static final int ST_ERR_REC_NOT_FOUND = 225; + + // The stclient output has to be an exported interface + private static final String INSTANCE_URN_DESC = "Product instance URN="; + private static boolean initialized = false; + private static boolean supportsHelperClass = true; // default + private static File stclient = null; + private static String stclientPath = null; + private static Registry registry = new Registry(); + + // System properties for testing + private static String SVCTAG_STCLIENT_CMD = "servicetag.stclient.cmd"; + private static String SVCTAG_STHELPER_SUPPORTED = "servicetag.sthelper.supported"; + + private Registry() { + } + + private synchronized static String getSTclient() { + if (!initialized) { + // the system property always overrides the default setting + if (System.getProperty(SVCTAG_STHELPER_SUPPORTED) != null) { + supportsHelperClass = Boolean.getBoolean(SVCTAG_STHELPER_SUPPORTED); + } + + // This is only used for testing + stclientPath = System.getProperty(SVCTAG_STCLIENT_CMD); + if (stclientPath != null) { + return stclientPath; + } + + // Initialization to determine the platform's stclient pathname + String os = System.getProperty("os.name"); + if (os.equals("SunOS")) { + stclient = new File(STCLIENT_SOLARIS); + } else if (os.equals("Linux")) { + stclient = new File(STCLIENT_LINUX); + } else if (os.startsWith("Windows")) { + stclient = getWindowsStClientFile(); + } else { + if (isVerbose()) { + System.out.println("Running on non-Sun JDK"); + } + } + initialized = true; + } + + // com.sun.servicetag package has to be compiled with JDK 5 as well + // JDK 5 doesn't support the File.canExecute() method. + // Risk not checking isExecute() for the stclient command is very low. + + if (stclientPath == null && stclient != null && stclient.exists()) { + stclientPath = stclient.getAbsolutePath(); + } + return stclientPath; + } + + /** + * Returns the system service tag registry. The {@code Registry} class + * may not be supported on some platforms; use the {@link #isSupported} + * method to determine if it is supported. + * + * @return the {@code Registry} object for the system service tag registry. + * + * @throws UnsupportedOperationException if the {@code Registry} class is + * not supported. + */ + public static Registry getSystemRegistry() { + if (isSupported()) { + return registry; + } else { + throw new UnsupportedOperationException("Registry class is not supported"); + } + } + + /** + * Returns {@code true} if the {@code Registry} class is supported on this system. + * + * @return {@code true} if the {@code Registry} class is supported; + * otherwise, return {@code false}. + */ + public static boolean isSupported() { + return (getSTclient() != null && supportsHelperClass); + } + + private static List<String> getCommandList() { + // Set up the arguments to call stclient + List<String> command = new ArrayList<String>(); + if (System.getProperty(SVCTAG_STCLIENT_CMD) != null) { + // This is for jtreg testing use. This will be set to something + // like: + // $JAVA_HOME/bin/java -cp $TEST_DIR \ + // -Dstclient.registry.path=$TEST_DIR/registry.xml \ + // SvcTagClient + // + // On Windows, the JAVA_HOME and TEST_DIR path could contain + // space e.g. c:\Program Files\Java\jdk1.6.0_05\bin\java. + // The SVCTAG_STCLIENT_CMD must be set with a list of + // space-separated parameters. If a parameter contains spaces, + // it must be quoted with '"'. + + String cmd = getSTclient(); + int len = cmd.length(); + int i = 0; + while (i < len) { + char separator = ' '; + if (cmd.charAt(i) == '"') { + separator = '"'; + i++; + } + // look for the separator or matched the closing '"' + int j; + for (j = i+1; j < len; j++) { + if (cmd.charAt(j) == separator) { + break; + } + } + + if (i == j-1) { + // add an empty parameter + command.add("\"\""); + } else { + // double quotes and space are not included + command.add(cmd.substring(i,j)); + } + + // skip spaces + for (i = j+1; i < len; i++) { + if (!Character.isSpaceChar(cmd.charAt(i))) { + break; + } + } + } + if (isVerbose()) { + System.out.println("Command list:"); + for (String s : command) { + System.out.println(s); + } + } + } else { + command.add(getSTclient()); + } + return command; + } + + // Returns null if the service tag record not found; + // or throw UnauthorizedAccessException or IOException + // based on the exitValue. + private static ServiceTag checkReturnError(int exitValue, + String output, + ServiceTag st) throws IOException { + switch (exitValue) { + case ST_ERR_REC_NOT_FOUND: + return null; + case ST_ERR_NOT_AUTH: + if (st != null) { + throw new UnauthorizedAccessException( + "Not authorized to access " + st.getInstanceURN() + + " installer_uid=" + st.getInstallerUID()); + } else { + throw new UnauthorizedAccessException( + "Not authorized:" + output); + } + default: + throw new IOException("stclient exits with error" + + " (" + exitValue + ")\n" + output); + } + } + + /** + * Adds a service tag to this registry. + * If the given service tag has an empty <tt>instance_urn</tt>, + * this helper class will generate a URN and place it in the + * copy of the service tag in this registry. + * This method will return the {@code ServiceTag} representing + * the service tag entry to this registry. + * + * @param st {@code ServiceTag} object + * @return a {@code ServiceTag} object representing the service tag + * entry to this registry. + * + * @throws IllegalArgumentException if a service tag of the same + * <tt>instance_urn</tt> already exists in this registry. + * + * @throws java.io.IOException if an I/O error occurs in this operation. + */ + public ServiceTag addServiceTag(ServiceTag st) throws IOException { + List<String> command = getCommandList(); + command.add("-a"); + if (st.getInstanceURN().length() > 0) { + ServiceTag sysSvcTag = getServiceTag(st.getInstanceURN()); + if (sysSvcTag != null) { + throw new IllegalArgumentException("Instance_urn = " + + st.getInstanceURN() + " already exists"); + } + command.add("-i"); + command.add(st.getInstanceURN()); + } + command.add("-p"); + command.add(st.getProductName()); + command.add("-e"); + command.add(st.getProductVersion()); + command.add("-t"); + command.add(st.getProductURN()); + if (st.getProductParentURN().length() > 0) { + command.add("-F"); + command.add(st.getProductParentURN()); + } + command.add("-P"); + command.add(st.getProductParent()); + if (st.getProductDefinedInstanceID().length() > 0) { + command.add("-I"); + command.add(st.getProductDefinedInstanceID()); + } + command.add("-m"); + command.add(st.getProductVendor()); + command.add("-A"); + command.add(st.getPlatformArch()); + command.add("-z"); + command.add(st.getContainer()); + command.add("-S"); + command.add(st.getSource()); + + BufferedReader in = null; + try { + ProcessBuilder pb = new ProcessBuilder(command); + Process p = pb.start(); + String output = commandOutput(p); + if (isVerbose()) { + System.out.println("Output from stclient -a command:"); + System.out.println(output); + } + String urn = ""; + if (p.exitValue() == 0) { + // Obtain the instance urn from the stclient output + in = new BufferedReader(new StringReader(output)); + String line = null; + while ((line = in.readLine()) != null) { + line = line.trim(); + if (line.startsWith(INSTANCE_URN_DESC)) { + urn = line.substring(INSTANCE_URN_DESC.length()); + break; + } + } + if (urn.length() == 0) { + throw new IOException("Error in creating service tag:\n" + + output); + } + return getServiceTag(urn); + } else { + return checkReturnError(p.exitValue(), output, st); + } + } finally { + if (in != null) { + in.close(); + } + } + } + + /** + * Removes a service tag of the given <tt>instance_urn</tt> from this + * registry. + * + * @param instanceURN the <tt>instance_urn</tt> of the service tag + * to be removed. + * + * @return the {@code ServiceTag} object removed from this registry; + * or {@code null} if the service tag does not exist in this registry. + * + * @throws UnauthorizedAccessException if the user is not authorized to + * remove the service tag of the given <tt>instance_urn</tt> + * from this registry. + * + * @throws java.io.IOException if an I/O error occurs in this operation. + */ + public ServiceTag removeServiceTag(String instanceURN) throws IOException { + ServiceTag st = getServiceTag(instanceURN); + if (st == null) { + return null; + } + + List<String> command = getCommandList(); + command.add("-d"); + command.add("-i"); + command.add(instanceURN); + + ProcessBuilder pb = new ProcessBuilder(command); + Process p = pb.start(); + String output = commandOutput(p); + if (isVerbose()) { + System.out.println("Output from stclient -d command:"); + System.out.println(output); + } + if (p.exitValue() == 0) { + return st; + } else { + return checkReturnError(p.exitValue(), output, st); + } + } + + /** + * Updates the <tt>product_defined_instance_id</tt> in the service tag + * of the specified <tt>instance_urn</tt> in this registry. + * + * @param instanceURN the <tt>instance_urn</tt> of the service tag to be updated. + * @param productDefinedInstanceID the value of the + * <tt>product_defined_instance_id</tt> to be set. + * + * @return the updated {@code ServiceTag} object; + * or {@code null} if the service tag does not exist in this + * registry. + * + * @throws UnauthorizedAccessException if the user is not authorized to + * update the service tag from this registry. + * + * @throws IOException if an I/O error occurs in this operation. + */ + public ServiceTag updateServiceTag(String instanceURN, + String productDefinedInstanceID) + throws IOException { + ServiceTag svcTag = getServiceTag(instanceURN); + if (svcTag == null) { + return null; + } + + List<String> command = getCommandList(); + command.add("-u"); + command.add("-i"); + command.add(instanceURN); + command.add("-I"); + if (productDefinedInstanceID.length() > 0) { + command.add(productDefinedInstanceID); + } else { + command.add("\"\""); + } + + ProcessBuilder pb = new ProcessBuilder(command); + Process p = pb.start(); + String output = commandOutput(p); + if (isVerbose()) { + System.out.println("Output from stclient -u command:"); + System.out.println(output); + } + + if (p.exitValue() == 0) { + return getServiceTag(instanceURN); + } else { + return checkReturnError(p.exitValue(), output, svcTag); + } + } + + /** + * Returns a {@code ServiceTag} object of the given <tt>instance_urn</tt> + * in this registry. + * + * @param instanceURN the <tt>instance_urn</tt> of the service tag + * @return a {@code ServiceTag} object of the given <tt>instance_urn</tt> + * in this registry; or {@code null} if not found. + * + * @throws java.io.IOException if an I/O error occurs in this operation. + */ + public ServiceTag getServiceTag(String instanceURN) throws IOException { + if (instanceURN == null) { + throw new NullPointerException("instanceURN is null"); + } + + List<String> command = getCommandList(); + command.add("-g"); + command.add("-i"); + command.add(instanceURN); + + ProcessBuilder pb = new ProcessBuilder(command); + Process p = pb.start(); + String output = commandOutput(p); + if (isVerbose()) { + System.out.println("Output from stclient -g command:"); + System.out.println(output); + } + if (p.exitValue() == 0) { + return parseServiceTag(output); + } else { + return checkReturnError(p.exitValue(), output, null); + } + } + + private ServiceTag parseServiceTag(String output) throws IOException { + BufferedReader in = null; + try { + Properties props = new Properties(); + // parse the service tag output from stclient + in = new BufferedReader(new StringReader(output)); + String line = null; + while ((line = in.readLine()) != null) { + if ((line = line.trim()).length() > 0) { + String[] ss = line.trim().split("=", 2); + if (ss.length == 2) { + props.setProperty(ss[0].trim(), ss[1].trim()); + } else { + props.setProperty(ss[0].trim(), ""); + } + } + } + + String urn = props.getProperty(ST_NODE_INSTANCE_URN); + String productName = props.getProperty(ST_NODE_PRODUCT_NAME); + String productVersion = props.getProperty(ST_NODE_PRODUCT_VERSION); + String productURN = props.getProperty(ST_NODE_PRODUCT_URN); + String productParent = props.getProperty(ST_NODE_PRODUCT_PARENT); + String productParentURN = props.getProperty(ST_NODE_PRODUCT_PARENT_URN); + String productDefinedInstanceID = + props.getProperty(ST_NODE_PRODUCT_DEFINED_INST_ID); + String productVendor = props.getProperty(ST_NODE_PRODUCT_VENDOR); + String platformArch = props.getProperty(ST_NODE_PLATFORM_ARCH); + String container = props.getProperty(ST_NODE_CONTAINER); + String source = props.getProperty(ST_NODE_SOURCE); + int installerUID = + Util.getIntValue(props.getProperty(ST_NODE_INSTALLER_UID)); + Date timestamp = + Util.parseTimestamp(props.getProperty(ST_NODE_TIMESTAMP)); + + return new ServiceTag(urn, + productName, + productVersion, + productURN, + productParent, + productParentURN, + productDefinedInstanceID, + productVendor, + platformArch, + container, + source, + installerUID, + timestamp); + } finally { + if (in != null) { + in.close(); + } + } + + } + + /** + * Returns the service tags of the specified + * <tt>product_urn</tt> in this registry. + * + * @param productURN the <tt>product_urn</tt> to look up + * @return a {@code Set} of {@code ServiceTag} objects + * of the specified <tt>product_urn</tt> in this registry. + * + * @throws java.io.IOException if an I/O error occurs in this operation. + */ + public Set<ServiceTag> findServiceTags(String productURN) throws IOException { + if (productURN == null) { + throw new NullPointerException("productURN is null"); + } + + List<String> command = getCommandList(); + command.add("-f"); + command.add("-t"); + command.add(productURN); + + BufferedReader in = null; + try { + ProcessBuilder pb = new ProcessBuilder(command); + Process p = pb.start(); + String output = commandOutput(p); + + Set<ServiceTag> instances = new HashSet<ServiceTag>(); + if (p.exitValue() == 0) { + // parse the service tag output from stclient + in = new BufferedReader(new StringReader(output)); + String line = null; + while ((line = in.readLine()) != null) { + String s = line.trim(); + if (s.startsWith("urn:st:")) { + instances.add(getServiceTag(s)); + } + } + } else { + checkReturnError(p.exitValue(), output, null); + } + return instances; + } finally { + if (in != null) { + in.close(); + } + } + } +} diff --git a/desktop/source/registration/com/sun/star/servicetag/ServiceTag.java b/desktop/source/registration/com/sun/star/servicetag/ServiceTag.java new file mode 100644 index 000000000000..cbaf44e1d0d9 --- /dev/null +++ b/desktop/source/registration/com/sun/star/servicetag/ServiceTag.java @@ -0,0 +1,636 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +package com.sun.star.servicetag; + +import java.util.Date; +import java.io.IOException; +import static com.sun.star.servicetag.RegistrationDocument.*; + +/** + * A service tag is an XML-based data structure that identifies a product or + * a component on a system. The service tag schema is defined by the + * Service Tags Technology. The location of the DTD file is platform dependent. + * On Solaris, see <tt>/usr/share/lib/xml/dtd/servicetag.dtd</tt>. + * <p> + * A valid {@code ServiceTag} instance must comply to the service tag schema + * and contain the following fields: + * <ul> + * <li>{@link #getInstanceURN <tt>instance_urn</tt>}</li> + * <li>{@link #getProductName <tt>product_name</tt>}</li> + * <li>{@link #getProductVersion <tt>product_version</tt>}</li> + * <li>{@link #getProductURN <tt>product_urn</tt>}</li> + * <li>{@link #getProductParent <tt>product_parent</tt>}</li> + * <li>{@link #getProductParentURN <tt>product_parent_urn</tt>}</li> + * <li>{@link #getProductDefinedInstanceID <tt>product_defined_inst_id</tt>}</li> + * <li>{@link #getProductVendor <tt>product_vendor</tt>}</li> + * <li>{@link #getPlatformArch <tt>platform_arch</tt>}</li> + * <li>{@link #getContainer <tt>container</tt>}</li> + * <li>{@link #getSource <tt>source</tt>}</li> + * <li>{@link #getInstallerUID <tt>installer_uid</tt>}</li> + * <li>{@link #getTimestamp <tt>timestamp</tt>}</li> + * </ul> + * + * The <tt>instance_urn</tt> can be specified when a {@code ServiceTag} + * object is created, or it can be generated when it is added to + * a {@link RegistrationData} object, or {@link Registry + * system service tag registry}. The <tt>installer_uid</tt> and + * <tt>timestamp</tt> are set when a {@code ServiceTag} object + * is added to a {@link RegistrationData} object, or {@link Registry + * system service tag registry}. + * + * @see <a href="https://sunconnection.sun.com/FAQ/sc_faq.html">Service Tags FAQ</a> + */ +public class ServiceTag { + + private String instanceURN; + private String productName; + private String productVersion; + private String productURN; + private String productParent; + private String productParentURN; + private String productDefinedInstanceID; + private String productVendor; + private String platformArch; + private String container; + private String source; + private int installerUID; + private Date timestamp; + + // Service Tag Field Lengths (defined in sthelper.h) + // Since the constants defined in sthelper.h includes the null-terminated + // character, so minus 1 from the sthelper.h defined values. + private final int MAX_URN_LEN = 256 - 1; + private final int MAX_PRODUCT_NAME_LEN = 256 - 1; + private final int MAX_PRODUCT_VERSION_LEN = 64 - 1; + private final int MAX_PRODUCT_PARENT_LEN = 256 - 1; + private final int MAX_PRODUCT_VENDOR_LEN = 64 - 1; + private final int MAX_PLATFORM_ARCH_LEN = 64 - 1; + private final int MAX_CONTAINER_LEN = 64 - 1; + private final int MAX_SOURCE_LEN = 64 - 1; + + // private constructors + private ServiceTag() { + } + // package private + ServiceTag(String instanceURN, + String productName, + String productVersion, + String productURN, + String productParent, + String productParentURN, + String productDefinedInstanceID, + String productVendor, + String platformArch, + String container, + String source, + int installerUID, + Date timestamp) { + setInstanceURN(instanceURN); + setProductName(productName); + setProductVersion(productVersion); + setProductURN(productURN); + setProductParentURN(productParentURN); + setProductParent(productParent); + setProductDefinedInstanceID(productDefinedInstanceID); + setProductVendor(productVendor); + setPlatformArch(platformArch); + setContainer(container); + setSource(source); + setInstallerUID(installerUID); + setTimestamp(timestamp); + } + + /** + * Creates a service tag object with no <tt>instance_urn</tt>. + * + * @param productName the name of the product. + * @param productVersion the version of the product. + * @param productURN the uniform resource name of the product + * @param productParent the name of the product's parent. + * @param productParentURN the uniform resource name of the product's parent. + * @param productDefinedInstanceID the instance identifier. + * @param productVendor the vendor of the product. + * @param platformArch the operating system architecture. + * @param container the container of the product. + * @param source the source of the product. + * + * @throws IllegalArgumentException if any value of the input fields + * does not conform to the service tag XML schema. + */ + public static ServiceTag newInstance(String productName, + String productVersion, + String productURN, + String productParent, + String productParentURN, + String productDefinedInstanceID, + String productVendor, + String platformArch, + String container, + String source) { + return new ServiceTag("", /* empty instance_urn */ + productName, + productVersion, + productURN, + productParent, + productParentURN, + productDefinedInstanceID, + productVendor, + platformArch, + container, + source, + -1, + null); + } + + /** + * Creates a service tag object with a specified <tt>instance_urn</tt>. + * + * @param instanceURN the uniform resource name of this instance. + * @param productName the name of the product. + * @param productVersion the version of the product. + * @param productURN the uniform resource name of the product + * @param productParent the name of the product's parent. + * @param productParentURN the uniform resource name of the product's parent. + * @param productDefinedInstanceID the instance identifier. + * @param productVendor the vendor of the product. + * @param platformArch the operating system architecture. + * @param container the container of the product. + * @param source the source of the product. + * + * @throws IllegalArgumentException if any value of the input fields + * does not conform to the service tag XML schema. + */ + public static ServiceTag newInstance(String instanceURN, + String productName, + String productVersion, + String productURN, + String productParent, + String productParentURN, + String productDefinedInstanceID, + String productVendor, + String platformArch, + String container, + String source) { + return new ServiceTag(instanceURN, + productName, + productVersion, + productURN, + productParent, + productParentURN, + productDefinedInstanceID, + productVendor, + platformArch, + container, + source, + -1, + null); + } + + // Creates a copy of the ServiceTag instance + // with instance_urn and timestamp initialized + static ServiceTag newInstanceWithUrnTimestamp(ServiceTag st) { + String instanceURN = + (st.getInstanceURN().length() == 0 ? Util.generateURN() : + st.getInstanceURN()); + ServiceTag svcTag = new ServiceTag(instanceURN, + st.getProductName(), + st.getProductVersion(), + st.getProductURN(), + st.getProductParent(), + st.getProductParentURN(), + st.getProductDefinedInstanceID(), + st.getProductVendor(), + st.getPlatformArch(), + st.getContainer(), + st.getSource(), + st.getInstallerUID(), + new Date()); + return svcTag; + } + + /** + * Returns a uniform resource name (URN) in this format: + * <blockquote> + * "<tt>urn:st:<32-char {@link java.util.UUID uuid}></tt>" + * </blockquote> + * @return a URN. + */ + public static String generateInstanceURN() { + return Util.generateURN(); + } + + /** + * Returns the uniform resource name of this service tag instance. + * + * @return the <tt>instance_urn</tt> of this service tag. + */ + public String getInstanceURN() { + return instanceURN; + } + + /** + * Returns the name of the product. + * + * @return the product name. + */ + public String getProductName() { + return productName; + } + + /** + * Returns the version of the product. + * + * @return the product version. + */ + public String getProductVersion() { + return productVersion; + } + + /** + * Returns the uniform resource name of the product. + * + * @return the product URN. + */ + public String getProductURN() { + return productURN; + } + + /** + * Returns the uniform resource name of the product's parent. + * + * @return the product's parent URN. + */ + public String getProductParentURN() { + return productParentURN; + } + + /** + * Returns the name of the product's parent. + * + * @return the product's parent name. + */ + public String getProductParent() { + return productParent; + } + + /** + * Returns the identifier defined for this product instance. + * + * @return the identifier defined for this product instance. + */ + public String getProductDefinedInstanceID() { + return productDefinedInstanceID; + } + + /** + * Returns the vendor of the product. + * + * @return the product vendor. + */ + public String getProductVendor() { + return productVendor; + } + + /** + * Returns the platform architecture on which the product + * is running on. + * + * @return the platform architecture on which the product is running on. + */ + public String getPlatformArch() { + return platformArch; + } + + /** + * Returns the timestamp. This timestamp is set when this service tag + * is added to or updated in a {@code RegistrationData} object or + * the system service tag registry. + * This method may return {@code null}. + * + * @return timestamp when this service tag + * is added to or updated in a {@code RegistrationData} object or + * the system service tag registry, or {@code null}. + */ + public Date getTimestamp() { + if (timestamp != null) { + return (Date) timestamp.clone(); + } else { + return null; + } + } + + + /** + * Returns the container of the product. + * + * @return the container of the product. + */ + public String getContainer() { + return container; + } + + /** + * Returns the source of this service tag. + * + * @return source of this service tag. + */ + public String getSource() { + return source; + } + + /** + * Returns the UID. The UID is set when this service tag + * is added to or updated in the system service tag registry. + * This is platform dependent whose default value is {@code -1}. + * When this service tag is added to a {@code RegistrationData}, + * the UID is not set. + * + * @return the UID of whom this service tag + * is added to or updated in the system service tag registry, + * or {@code -1}. + */ + public int getInstallerUID() { + return installerUID; + } + + // The following setter methods are used to validate the + // input field when constructing a ServiceTag instance + + private void setInstanceURN(String instanceURN) { + if (instanceURN == null) { + throw new NullPointerException("Parameter instanceURN cannot be null"); + } + if (instanceURN.length() > MAX_URN_LEN) { + throw new IllegalArgumentException("instanceURN \"" + instanceURN + + "\" exceeds maximum length " + MAX_URN_LEN); + } + this.instanceURN = instanceURN; + } + + private void setProductName(String productName) { + if (productName == null) { + throw new NullPointerException("Parameter productName cannot be null"); + } + if (productName.length() == 0) { + throw new IllegalArgumentException("product name cannot be empty"); + } + if (productName.length() > MAX_PRODUCT_NAME_LEN) { + throw new IllegalArgumentException("productName \"" + productName + + "\" exceeds maximum length " + MAX_PRODUCT_NAME_LEN); + } + this.productName = productName; + } + + private void setProductVersion(String productVersion) { + if (productVersion == null) { + throw new NullPointerException("Parameter productVersion cannot be null"); + } + + if (productVersion.length() == 0) { + throw new IllegalArgumentException("product version cannot be empty"); + } + if (productVersion.length() > MAX_PRODUCT_VERSION_LEN) { + throw new IllegalArgumentException("productVersion \"" + + productVersion + "\" exceeds maximum length " + + MAX_PRODUCT_VERSION_LEN); + } + this.productVersion = productVersion; + } + + private void setProductURN(String productURN) { + if (productURN == null) { + throw new NullPointerException("Parameter productURN cannot be null"); + } + if (productURN.length() == 0) { + throw new IllegalArgumentException("product URN cannot be empty"); + } + if (productURN.length() > MAX_URN_LEN) { + throw new IllegalArgumentException("productURN \"" + productURN + + "\" exceeds maximum length " + MAX_URN_LEN); + } + this.productURN = productURN; + } + + private void setProductParentURN(String productParentURN) { + if (productParentURN == null) { + throw new NullPointerException("Parameter productParentURN cannot be null"); + } + // optional field - can be empty + if (productParentURN.length() > MAX_URN_LEN) { + throw new IllegalArgumentException("productParentURN \"" + + productParentURN + "\" exceeds maximum length " + + MAX_URN_LEN); + } + this.productParentURN = productParentURN; + } + + private void setProductParent(String productParent) { + if (productParent == null) { + throw new NullPointerException("Parameter productParent cannot be null"); + } + if (productParent.length() == 0) { + throw new IllegalArgumentException("product parent cannot be empty"); + } + if (productParent.length() > MAX_PRODUCT_PARENT_LEN) { + throw new IllegalArgumentException("productParent \"" + + productParent + "\" exceeds maximum length " + + MAX_PRODUCT_PARENT_LEN); + } + this.productParent = productParent; + } + + void setProductDefinedInstanceID(String productDefinedInstanceID) { + if (productDefinedInstanceID == null) { + throw new NullPointerException("Parameter productDefinedInstanceID cannot be null"); + } + if (productDefinedInstanceID.length() > MAX_URN_LEN) { + throw new IllegalArgumentException("productDefinedInstanceID \"" + + productDefinedInstanceID + "\" exceeds maximum length " + + MAX_URN_LEN); + } + // optional field - can be empty + this.productDefinedInstanceID = productDefinedInstanceID; + } + + private void setProductVendor(String productVendor) { + if (productVendor == null) { + throw new NullPointerException("Parameter productVendor cannot be null"); + } + if (productVendor.length() == 0) { + throw new IllegalArgumentException("product vendor cannot be empty"); + } + if (productVendor.length() > MAX_PRODUCT_VENDOR_LEN) { + throw new IllegalArgumentException("productVendor \"" + + productVendor + "\" exceeds maximum length " + + MAX_PRODUCT_VENDOR_LEN); + } + this.productVendor = productVendor; + } + + private void setPlatformArch(String platformArch) { + if (platformArch == null) { + throw new NullPointerException("Parameter platformArch cannot be null"); + } + if (platformArch.length() == 0) { + throw new IllegalArgumentException("platform architecture cannot be empty"); + } + if (platformArch.length() > MAX_PLATFORM_ARCH_LEN) { + throw new IllegalArgumentException("platformArch \"" + + platformArch + "\" exceeds maximum length " + + MAX_PLATFORM_ARCH_LEN); + } + this.platformArch = platformArch; + } + + private void setTimestamp(Date timestamp) { + // can be null + this.timestamp = timestamp; + } + + private void setContainer(String container) { + if (container == null) { + throw new NullPointerException("Parameter container cannot be null"); + } + if (container.length() == 0) { + throw new IllegalArgumentException("container cannot be empty"); + } + if (container.length() > MAX_CONTAINER_LEN) { + throw new IllegalArgumentException("container \"" + + container + "\" exceeds maximum length " + + MAX_CONTAINER_LEN); + } + this.container = container; + } + + private void setSource(String source) { + if (source == null) { + throw new NullPointerException("Parameter source cannot be null"); + } + if (source.length() == 0) { + throw new IllegalArgumentException("source cannot be empty"); + } + if (source.length() > MAX_SOURCE_LEN) { + throw new IllegalArgumentException("source \"" + source + + "\" exceeds maximum length " + MAX_SOURCE_LEN); + } + this.source = source; + } + + private void setInstallerUID(int installerUID) { + this.installerUID = installerUID; + } + + /** + * Compares this service tag to the specified object. + * The result is {@code true} if and only if the argument is + * not {@code null} and is a {@code ServiceTag} object whose + * <tt>instance_urn</tt> is the same as the + * <tt>instance_urn</tt> of this service tag. + * + * @return {@code true} if this service tag is the same as + * the specified object. + */ + @Override + public boolean equals(Object obj) { + if (obj == null || !(obj instanceof ServiceTag)) { + return false; + } + ServiceTag st = (ServiceTag) obj; + if (st == this) { + return true; + } + return st.getInstanceURN().equals(getInstanceURN()); + } + + /** + * Returns the hash code value for this service tag. + * @return the hash code value for this service tag. + */ + @Override + public int hashCode() { + int hash = 7; + hash = 19 * hash + (this.instanceURN != null ? this.instanceURN.hashCode() : 0); + return hash; + } + + /** + * Returns the string representation of this service tag. + * The format is implementation specific. + * + * @return the string representation of this service tag. + */ + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(ST_NODE_INSTANCE_URN).append("=").append(instanceURN).append("\n"); + sb.append(ST_NODE_PRODUCT_NAME).append("=").append(productName).append("\n"); + sb.append(ST_NODE_PRODUCT_VERSION).append("=").append(productVersion).append("\n"); + sb.append(ST_NODE_PRODUCT_URN).append("=").append(productURN).append("\n"); + sb.append(ST_NODE_PRODUCT_PARENT_URN).append("=").append(productParentURN).append("\n"); + sb.append(ST_NODE_PRODUCT_PARENT).append("=").append(productParent).append("\n"); + sb.append(ST_NODE_PRODUCT_DEFINED_INST_ID).append("=").append(productDefinedInstanceID).append("\n"); + sb.append(ST_NODE_PRODUCT_VENDOR).append("=").append(productVendor).append("\n"); + sb.append(ST_NODE_PLATFORM_ARCH).append("=").append(platformArch).append("\n"); + sb.append(ST_NODE_TIMESTAMP).append("=").append(Util.formatTimestamp(timestamp)).append("\n"); + sb.append(ST_NODE_CONTAINER).append("=").append(container).append("\n"); + sb.append(ST_NODE_SOURCE).append("=").append(source).append("\n"); + sb.append(ST_NODE_INSTALLER_UID).append("=").append(String.valueOf(installerUID)).append("\n"); + return sb.toString(); + } + + + /** + * Returns the {@link ServiceTag} instance for the running Java + * platform. The {@link ServiceTag#setSource source} field + * of the {@code ServiceTag} will be set to the given {@code source}. + * This method will return {@code null} if there is no service tag + * for the running Java platform. + * <p> + * This method is designed for Sun software that bundles the JDK + * or the JRE to use. It is recommended that the {@code source} + * string contains information about the bundling software + * such as the name and the version of the software bundle, + * for example, + * <blockquote> + * <tt>NetBeans IDE 6.0 with JDK 6 Update 5 Bundle</tt> + * </blockquote> + * in a NetBeans/JDK bundle. + * <p> + * At the first time to call this method the application + * is required to have the write permission to the installed + * directory of this running JDK or JRE instance. + * + * @param source the source that bundles the JDK or the JRE. + * @return a {@code ServiceTag} object for the Java platform, + * or {@code null} if not supported. + * @throws IOException if an error occurs in this operation. + */ + public static ServiceTag getJavaServiceTag(String source) throws IOException { + return Installer.getJavaServiceTag(source); + } + +} diff --git a/desktop/source/registration/com/sun/star/servicetag/SolarisServiceTag.java b/desktop/source/registration/com/sun/star/servicetag/SolarisServiceTag.java new file mode 100644 index 000000000000..8378c78e76a0 --- /dev/null +++ b/desktop/source/registration/com/sun/star/servicetag/SolarisServiceTag.java @@ -0,0 +1,64 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +package com.sun.star.servicetag; + +import java.io.IOException; +import java.util.Set; + +/** + * Utility class to obtain the service tag for the Solaris Operating System. + */ +class SolarisServiceTag { + private final static String[] SolarisProductURNs = new String[] { + "urn:uuid:a7a38948-2bd5-11d6-98ce-9d3ac1c0cfd7", /* Solaris 8 */ + "urn:uuid:4f82caac-36f3-11d6-866b-85f428ef944e", /* Solaris 9 */ + "urn:uuid:a19de03b-48bc-11d9-9607-080020a9ed93", /* Solaris 9 sparc */ + "urn:uuid:4c35c45b-4955-11d9-9607-080020a9ed93", /* Solaris 9 x86 */ + "urn:uuid:5005588c-36f3-11d6-9cec-fc96f718e113", /* Solaris 10 */ + "urn:uuid:6df19e63-7ef5-11db-a4bd-080020a9ed93" /* Solaris 11 */ + }; + + /** + * Returns null if not found. + * + * There is only one service tag for the operating system. + */ + static ServiceTag getServiceTag() throws IOException { + if (Registry.isSupported()) { + Registry streg = Registry.getSystemRegistry(); + for (String parentURN : SolarisProductURNs) { + Set<ServiceTag> instances = streg.findServiceTags(parentURN); + for (ServiceTag st : instances) { + // there should have only one service tag for the OS + return st; + } + } + } + return null; + } +} diff --git a/desktop/source/registration/com/sun/star/servicetag/SolarisSystemEnvironment.java b/desktop/source/registration/com/sun/star/servicetag/SolarisSystemEnvironment.java new file mode 100644 index 000000000000..a9c094d1afac --- /dev/null +++ b/desktop/source/registration/com/sun/star/servicetag/SolarisSystemEnvironment.java @@ -0,0 +1,421 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +package com.sun.star.servicetag; + +// The Service Tags team maintains the latest version of the implementation +// for system environment data collection. JDK will include a copy of +// the most recent released version for a JDK release. We rename +// the package to com.sun.servicetag so that the Sun Connection +// product always uses the latest version from the com.sun.scn.servicetags +// package. JDK and users of the com.sun.servicetag API +// (e.g. NetBeans and SunStudio) will use the version in JDK. + +import java.io.*; +import java.util.Set; +import java.util.HashSet; + +/** + * Solaris implementation of the SystemEnvironment class. + */ +class SolarisSystemEnvironment extends SystemEnvironment { + private static final int SN = 1; + private static final int SYS = 2; + private static final int CPU = 3; + private static final int MODEL = 4; + private String kstatCpuInfo = null; + + SolarisSystemEnvironment() { + setHostId(getCommandOutput("/usr/bin/hostid")); + setSystemModel(getSolarisModel()); + setSystemManufacturer(getSolarisSystemManufacturer()); + setCpuManufacturer(getSolarisCpuManufacturer()); + setSerialNumber(getSolarisSN()); + setPhysMem(getSolarisPhysMem()); + setSockets(getSolarisSockets()); + setCores(getSolarisCores()); + setVirtCpus(getSolarisVirtCpus()); + setCpuName(getSolarisCpuName()); + setClockRate(getSolarisClockRate()); + } + + private String getSolarisClockRate() { + String data = getSolarisKstatCpuInfo(); + + String lines[] = data.split("\n"); + String token = "clock_MHz"; + for (int i=0; i<lines.length; i++) { + String line = lines[i].trim(); + if (line.startsWith(token)) { + return line.substring(line.indexOf(token) + token.length()).trim(); + } + } + return ""; + } + + private String getSolarisCpuName() { + String data = getSolarisKstatCpuInfo(); + + String lines[] = data.split("\n"); + String token = "brand"; + for (int i=0; i<lines.length; i++) { + String line = lines[i].trim(); + if (line.startsWith(token)) { + return line.substring(line.indexOf(token) + token.length()).trim(); + } + } + return ""; + } + + private String getSolarisVirtCpus() { + String data = getSolarisKstatCpuInfo(); + + int cnt = 0; + String lines[] = data.split("\n"); + String token = " cpu_info "; + for (int i=0; i<lines.length; i++) { + String line = lines[i].trim(); + if (line.indexOf(token) != -1) { + cnt++; + } + } + return "" + cnt; + } + + private String getSolarisCores() { + String data = getSolarisKstatCpuInfo(); + + Set<String> set = new HashSet<String>(); + String lines[] = data.split("\n"); + String coreIdToken = "core_id"; + String coreId = ""; + String chipIdToken = "chip_id"; + String chipId = ""; + for (int i=0; i<lines.length; i++) { + String line = lines[i].trim(); + if (line.startsWith(chipIdToken)) { + chipId = line.substring(line.indexOf(chipIdToken) + chipIdToken.length()).trim(); + } + if (line.startsWith(coreIdToken)) { + coreId = line.substring(line.indexOf(coreIdToken) + coreIdToken.length()).trim(); + set.add(chipId + "," + coreId); + } + } + return "" + set.size(); + } + + private String getSolarisPhysMem() { + String data = getCommandOutput("/usr/sbin/prtconf"); + + int cnt = 0; + String lines[] = data.split("\n"); + String token = "Memory size:"; + for (int i=0; i<lines.length; i++) { + String line = lines[i].trim(); + if (line.startsWith(token)) { + line = line.substring(line.indexOf(token) + token.length()).trim(); + if (line.indexOf(" ") != -1) { + return line.substring(0, line.indexOf(" ")).trim(); + } + } + } + return ""; + } + + private String getSolarisSockets() { + String data = getSolarisKstatCpuInfo(); + + Set<String> set = new HashSet<String>(); + String lines[] = data.split("\n"); + String token = "chip_id"; + for (int i=0; i<lines.length; i++) { + String line = lines[i].trim(); + if (line.startsWith(token)) { + String id = line.substring(line.indexOf(token) + token.length()).trim(); + set.add(id); + } + } + return "" + set.size(); + } + + private synchronized String getSolarisKstatCpuInfo() { + // only try to get kstat cpu_info information once, after that, we can + // reuse the output + if (kstatCpuInfo == null) { + Thread thread = new Thread() { + public void run() { + kstatCpuInfo = getCommandOutput("/usr/bin/kstat", "cpu_info"); + } + }; + thread.start(); + + try { + thread.join(2000); + if (thread.isAlive()) { + thread.interrupt(); + kstatCpuInfo = ""; + } + } catch (InterruptedException ie) { + thread.interrupt(); + } + } + return kstatCpuInfo; + } + + private String getSolarisModel() { + String tmp = getFileContent("/var/run/psn"); + if (tmp.length() > 0) { + String[] lines = tmp.split("\n"); + if (MODEL <= lines.length) { + return lines[MODEL-1] + "::" + + getCommandOutput("/usr/bin/uname", "-v"); + } + } + + if ("sparc".equalsIgnoreCase(System.getProperty("os.arch"))) { + return getCommandOutput("/usr/bin/uname", "-i") + "::" + + getCommandOutput("/usr/bin/uname", "-v"); + } else { + String model = getSmbiosData("1", "Product: "); + if (model == null || model.trim().equals("")) { + model = getCommandOutput("/usr/bin/uname", "-i"); + } + if (model == null) { + model = ""; + } + return model.trim() + "::" + + getCommandOutput("/usr/bin/uname", "-v"); + } + } + + /** + * Tries to obtain the cpu manufacturer. + * @return The cpu manufacturer (an empty string if not found or an error occurred) + */ + private String getSolarisCpuManufacturer() { + String tmp = getFileContent("/var/run/psn"); + if (tmp.length() > 0) { + String[] lines = tmp.split("\n"); + if (CPU <= lines.length) { + return lines[CPU-1]; + } + } + + // not fully accurate, this could be another manufacturer (fujitsu for example) + if ("sparc".equalsIgnoreCase(System.getProperty("os.arch"))) { + return "Sun Microsystems, Inc"; + } + + // if we're here, then we'll try smbios (type 4) + return getSmbiosData("4", "Manufacturer: "); + } + + /** + * Tries to obtain the system manufacturer. + * @return The system manufacturer (an empty string if not found or an error occurred) + */ + private String getSolarisSystemManufacturer() { + String tmp = getFileContent("/var/run/psn"); + if (tmp.length() > 0) { + String[] lines = tmp.split("\n"); + if (SYS <= lines.length) { + return lines[SYS-1]; + } + } + + // not fully accurate, this could be another manufacturer (fujitsu for example) + if ("sparc".equalsIgnoreCase(System.getProperty("os.arch"))) { + if (getCommandOutput("/usr/bin/uname", "-m").equals("sun4us")) { + return "Fujitsu"; + } + return "Sun Microsystems, Inc"; + } + + // if we're here, then we'll try smbios (type 1) + return getSmbiosData("1", "Manufacturer: "); + } + + /** + * Tries to obtain the serial number. + * @return The serial number (empty string if not found or an error occurred) + */ + private String getSolarisSN() { + // try to read from the psn file if it exists + String tmp = getFileContent("/var/run/psn"); + if (tmp.length() > 0) { + String[] lines = tmp.split("\n"); + if (SN <= lines.length) { + return lines[SN-1]; + } + } + + // if we're here, then we'll try sneep + String tmpSN = getSneepSN(); + if (tmpSN.length() > 0) { + return tmpSN; + } + + // if we're here, then we'll try smbios (type 1) + tmpSN = getSmbiosData("1", "Serial Number: "); + if (tmpSN.length() > 0) { + return tmpSN; + } + + // if we're here, then we'll try smbios (type 3) + tmpSN = getSmbiosData("3", "Serial Number: "); + if (tmpSN.length() > 0) { + return tmpSN; + } + + if ("sparc".equalsIgnoreCase(System.getProperty("os.arch"))) { + tmpSN = getSNViaPrtfruX(); + if (tmpSN.length() > 0) { + return tmpSN; + } + tmpSN = getSNViaPrtfru(); + if (tmpSN.length() > 0) { + return tmpSN; + } + } + + // give up and return + return ""; + } + + // Sample smbios output segment: + // ID SIZE TYPE + // 1 150 SMB_TYPE_SYSTEM (system information) + // + // Manufacturer: Sun Microsystems + // Product: Sun Fire X4600 + // Version: To Be Filled By O.E.M. + // Serial Number: 00:14:4F:45:0C:2A + private String getSmbiosData(String type, String target) { + String output = getCommandOutput("/usr/sbin/smbios", "-t", type); + for (String s : output.split("\n")) { + if (s.contains(target)) { + int indx = s.indexOf(target) + target.length(); + if (indx < s.length()) { + String tmp = s.substring(indx).trim(); + String lowerCaseStr = tmp.toLowerCase(); + if (!lowerCaseStr.startsWith("not available") + && !lowerCaseStr.startsWith("to be filled by o.e.m")) { + return tmp; + } + } + } + } + + return ""; + } + + private String getSneepSN() { + String basedir = getCommandOutput("pkgparam","SUNWsneep","BASEDIR"); + File f = new File(basedir + "/bin/sneep"); + if (f.exists()) { + String sneepSN = getCommandOutput(basedir + "/bin/sneep"); + if (sneepSN.equalsIgnoreCase("unknown")) { + return ""; + } else { + return sneepSN; + } + } else { + return ""; + } + } + + private String getSNViaPrtfruX() { + String data = getCommandOutput("/usr/sbin/prtfru", "-x"); + + boolean FRUTREE_FLAG = false; + boolean FRUNAME_FLAG = false; + boolean MB_LABEL_FLAG = false; + boolean SYSTEM_BOARD_FLAG = false; + + String lines[] = data.split("\n"); + for (int i=0; i<lines.length; i++) { + String line = lines[i]; + if (SYSTEM_BOARD_FLAG) { + String tok = "<Sun_Serial_No value=\""; + int index = line.indexOf(tok); + if (index != -1) { + String val = line.substring(index+tok.length()); + String vals[] = val.split("\""); + if (vals.length > 0) { + return vals[0].trim(); + } + break; + } + } + + if (line.indexOf("</ContainerData>") != -1) { + FRUTREE_FLAG = false; + FRUNAME_FLAG = false; + SYSTEM_BOARD_FLAG = false; + } + + if (FRUNAME_FLAG && line.indexOf("<Container name=\"system-board\">") != -1 ) { + SYSTEM_BOARD_FLAG = true; + } + + if (FRUTREE_FLAG && line.indexOf("<Fru name=\"chassis\">") != -1 ) { + FRUNAME_FLAG = true; + } + + if (line.indexOf("<Location name=\"frutree\">") != -1) { + FRUTREE_FLAG = true; + } + } + + return ""; + } + + private String getSNViaPrtfru() { + String data = getCommandOutput("/usr/sbin/prtfru"); + boolean CHASSIS_FLAG = false; + + String lines[] = data.split("\n"); + for (int i=0; i<lines.length; i++) { + String line = lines[i]; + if (CHASSIS_FLAG) { + String tok = "/ManR/Sun_Serial_No:"; + int index = line.indexOf(tok); + if (index != -1) { + String val = line.substring(index+tok.length()); + return val.trim(); + } + } + + if (line.indexOf("/frutree/chassis/system-board (container)") != -1) { + CHASSIS_FLAG = true; + } else if (line.indexOf("/frutree/chassis/MB?Label=MB/system-board (container)") != -1) { + CHASSIS_FLAG = true; + } + } + return ""; + } +} diff --git a/desktop/source/registration/com/sun/star/servicetag/SunConnection.java b/desktop/source/registration/com/sun/star/servicetag/SunConnection.java new file mode 100644 index 000000000000..9b9c7595acc6 --- /dev/null +++ b/desktop/source/registration/com/sun/star/servicetag/SunConnection.java @@ -0,0 +1,292 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +package com.sun.star.servicetag; + +import java.io.*; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.io.OutputStreamWriter; +import java.util.Locale; +import javax.net.ssl.HttpsURLConnection; + +/** + * Sun Connection Class for Product Registration. + * + * Registration Web Application Interface + * 1) POST the product registry to the output stream of the registration + * relay service. + * 2) Open the webapp URL from a browser with the following parameters: + * registry-urn + * product=jdk + * locale=<locale-lang> + * + * @see https://sn-tools.central.sun.com/twiki/pub/ServiceTags/RegistrationRelayService/ + * + */ +class SunConnection { + + private static String JDK_REGISTRATION_URL = + "https://inventory.sun.com/RegistrationWeb/register"; + private static String SANDBOX_TESTING_URL = + "https://connection-tst.sun.com/RegistrationWeb/register"; + + // System properties for testing + private static String SVCTAG_REGISTER_TESTING = "servicetag.register.testing"; + private static String SVCTAG_REGISTRATION_URL = "servicetag.registration.url"; + private static String SVCTAG_CONNECTION_TIMEOUT = "servicetag.connection.timeout"; + + private SunConnection() { + } + + /** + * Returns a URL for JDK registration interfacing with the Sun Connection + * registration relay service in this form: + * <registration-url>/<registry_urn>?product=jdk&locale=<locale-lang> + * + * The <registration-url> can be overridden by an environment + * variable or a system property. + * + * 1) "servicetag.register.testing" system property to switch to the + * Sun Connection registration sandbox testing. + * 2) "servicetag.registration.url" system property to override + * the URL + * 3) Default production URL + * + */ + static URL getRegistrationURL(String registrationURN) { + String url = System.getProperty(SVCTAG_REGISTRATION_URL); + if (url == null) { + if (System.getProperty(SVCTAG_REGISTER_TESTING) != null) { + url = SANDBOX_TESTING_URL; + } else { + url = JDK_REGISTRATION_URL; + } + } + + // trim whitespaces + url = url.trim(); + if (url.length() == 0) { + throw new InternalError("Empty registration url set"); + } + + // Add the registry_urn in the URL's query + String registerURL = rewriteURL(url, registrationURN); + try { + return new URL(registerURL); + } catch (MalformedURLException ex) { + // should never reach here + InternalError x = + new InternalError(ex.getMessage()); + x.initCause(ex); + throw x; + } + } + + private static String rewriteURL(String url, String registryURN) { + StringBuilder sb = new StringBuilder(url.trim()); + int len = sb.length(); + if (sb.charAt(len-1) != '/') { + sb.append('/'); + } + sb.append(registryURN); + sb.append("?"); + sb.append("product=jdk"); + sb.append("&"); + sb.append("locale=").append(Locale.getDefault().getLanguage()); + return sb.toString(); + } + + /** + * Registers all products in the given product registry. If it fails + * to post the service tag registry, open the browser with the offline + * registration page. + * + * @param regData registration data to be posted to the Sun Connection + * for registration. + * + * @throws IOException if I/O error occurs in this operation + */ + public static void register(RegistrationData regData) throws IOException { + // Gets the URL for SunConnection registration relay service + URL url = getRegistrationURL(regData.getRegistrationURN()); + + // Post the Product Registry to Sun Connection + boolean succeed = postRegistrationData(url, regData); + if (succeed) { + // service tags posted successfully + // now prompt for registration + openBrowser(url); + } else { + // open browser with the offline registration page + openOfflineRegisterPage(); + } + } + + /** + * Opens a browser for JDK product registration. + * @param url Registration Webapp URL + */ + private static void openBrowser(URL url) throws IOException { + if (!BrowserSupport.isSupported()) { + if (Util.isVerbose()) { + System.out.println("Browser is not supported"); + } + return; + } + + try { + BrowserSupport.browse(url.toURI()); + } catch (URISyntaxException ex) { + InternalError x = new InternalError("Error in registering: " + ex.getMessage()); + x.initCause(ex); + throw x; + } catch (IllegalArgumentException ex) { + if (Util.isVerbose()) { + ex.printStackTrace(); + } + } catch (UnsupportedOperationException ex) { + // ignore if not supported + if (Util.isVerbose()) { + ex.printStackTrace(); + } + } + } + + /** + * POST service tag registry to Sun Connection + * @param loc the URL of the webapp to handle the POST request + * @param streg the Service Tag registry + * @return true if posting succeeds; otherwise, false. + */ + private static boolean postRegistrationData(URL url, + RegistrationData registration) { + try { + HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); + con.setDoInput(true); + con.setDoOutput(true); + con.setUseCaches(false); + con.setAllowUserInteraction(false); + + // default 10 seconds timeout + String timeout = System.getProperty(SVCTAG_CONNECTION_TIMEOUT, "10"); + con.setConnectTimeout(Util.getIntValue(timeout) * 1000); + + if (Util.isVerbose()) { + System.out.println("Connecting to post registration data at " + url); + } + + con.setRequestMethod("POST"); + con.setRequestProperty("Content-Type", "text/xml;charset=\"utf-8\""); + con.connect(); + + OutputStream out = con.getOutputStream(); + registration.storeToXML(out); + out.flush(); + out.close(); + + int returnCode = con.getResponseCode(); + if (Util.isVerbose()) { + System.out.println("POST return status = " + returnCode); + printReturnData(con, returnCode); + } + return (returnCode == HttpURLConnection.HTTP_OK); + } catch (MalformedURLException me) { + // should never reach here + InternalError x = new InternalError("Error in registering: " + me.getMessage()); + x.initCause(me); + throw x; + } catch (Exception ioe) { + // SocketTimeoutException, IOException or UnknownHostException + if (Util.isVerbose()) { + ioe.printStackTrace(); + } + return false; + } + } + + /** + * Opens the offline registratioin page in the browser. + * + */ + private static void openOfflineRegisterPage() + throws IOException { + if (!BrowserSupport.isSupported()) { + if (Util.isVerbose()) { + System.out.println("Browser is not supported"); + } + return; + } + + File registerPage = Installer.getRegistrationHtmlPage(); + try { + BrowserSupport.browse(registerPage.toURI()); + } catch (FileNotFoundException ex) { + // should never reach here + InternalError x = + new InternalError("Error in launching " + registerPage + ": " + ex.getMessage()); + x.initCause(ex); + throw x; + } catch (IllegalArgumentException ex) { + if (Util.isVerbose()) { + ex.printStackTrace(); + } + } catch (UnsupportedOperationException ex) { + // ignore if not supported + if (Util.isVerbose()) { + ex.printStackTrace(); + } + } + } + + private static void printReturnData(HttpURLConnection con, int returnCode) + throws IOException { + BufferedReader reader = null; + try { + if (returnCode < 400) { + reader = new BufferedReader( + new InputStreamReader(con.getInputStream())); + } else { + reader = new BufferedReader( + new InputStreamReader(con.getErrorStream())); + } + StringBuilder sb = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + sb.append(line).append("\n"); + } + System.out.println("Response is : "); + System.out.println(sb.toString()); + } finally { + if (reader != null) { + reader.close(); + } + } + } +} diff --git a/desktop/source/registration/com/sun/star/servicetag/SysnetRegistryHelper.java b/desktop/source/registration/com/sun/star/servicetag/SysnetRegistryHelper.java new file mode 100644 index 000000000000..0f03d0d621b6 --- /dev/null +++ b/desktop/source/registration/com/sun/star/servicetag/SysnetRegistryHelper.java @@ -0,0 +1,376 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +package com.sun.star.servicetag; + +import java.io.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; + +import static com.sun.star.servicetag.Util.*; +import static com.sun.star.servicetag.RegistrationDocument.*; + +/** + * Class containing additional methods that are not yet + * in the JDK Registry class. Note that all methods in this class + * will be superceeded by the JDK classes. + */ +public class SysnetRegistryHelper { + + private static final String STCLIENT_SOLARIS = "/usr/bin/stclient"; + private static final String STCLIENT_LINUX = "/opt/sun/servicetag/bin/stclient"; + // stclient exit value (see sthelper.h) + private static final int ST_ERR_NOT_AUTH = 245; + private static final int ST_ERR_REC_NOT_FOUND = 225; + + // The stclient output has to be an exported interface + private static final String INSTANCE_URN_OPEN_ELEMENT = "<instance_urn>"; + private static final String INSTANCE_URN_CLOSE_ELEMENT = "</instance_urn>"; + private static final String REGISTRY_URN = "<registry urn=\""; + private static final String INSTANCE_URN_DESC = "Product instance URN="; + private static boolean initialized = false; + private static boolean supportsHelperClass = true; // default + private static File stclient = null; + private static String stclientPath = null; + + // System properties for testing + private static String SVCTAG_STCLIENT_CMD = "servicetag.stclient.cmd"; + private static String SVCTAG_STHELPER_SUPPORTED = "servicetag.sthelper.supported"; + + private synchronized static String getSTclient() { + if (!initialized) { + // the system property always overrides the default setting + if (System.getProperty(SVCTAG_STHELPER_SUPPORTED) != null) { + supportsHelperClass = Boolean.getBoolean(SVCTAG_STHELPER_SUPPORTED); + } + + // This is only used for testing + stclientPath = System.getProperty(SVCTAG_STCLIENT_CMD); + if (stclientPath != null) { + return stclientPath; + } + + // Initialization to determine the platform's stclient pathname + String os = System.getProperty("os.name"); + if (os.equals("SunOS")) { + stclient = new File(STCLIENT_SOLARIS); + } else if (os.equals("Linux")) { + stclient = new File(STCLIENT_LINUX); + } else if (os.startsWith("Windows")) { + stclient = getWindowsStClientFile(); + } else { + if (isVerbose()) { + System.out.println("Running on non-Sun JDK"); + } + } + initialized = true; + } + + // com.sun.servicetag package has to be compiled with JDK 5 as well + // JDK 5 doesn't support the File.canExecute() method. + // Risk not checking isExecute() for the stclient command is very low. + + if (stclientPath == null && stclient != null && stclient.exists()) { + stclientPath = stclient.getAbsolutePath(); + } + return stclientPath; + } + + private static List<String> getCommandList() { + // Set up the arguments to call stclient + List<String> command = new ArrayList<String>(); + if (System.getProperty(SVCTAG_STCLIENT_CMD) != null) { + // This is for jtreg testing use. This will be set to something + // like: + // $JAVA_HOME/bin/java -cp $TEST_DIR \ + // -Dstclient.registry.path=$TEST_DIR/registry.xml \ + // SvcTagClient + // + // On Windows, the JAVA_HOME and TEST_DIR path could contain + // space e.g. c:\Program Files\Java\jdk1.6.0_05\bin\java. + // The SVCTAG_STCLIENT_CMD must be set with a list of + // space-separated parameters. If a parameter contains spaces, + // it must be quoted with '"'. + + String cmd = getSTclient(); + int len = cmd.length(); + int i = 0; + while (i < len) { + char separator = ' '; + if (cmd.charAt(i) == '"') { + separator = '"'; + i++; + } + // look for the separator or matched the closing '"' + int j; + for (j = i+1; j < len; j++) { + if (cmd.charAt(j) == separator) { + break; + } + } + + if (i == j-1) { + // add an empty parameter + command.add("\"\""); + } else { + // double quotes and space are not included + command.add(cmd.substring(i,j)); + } + + // skip spaces + for (i = j+1; i < len; i++) { + if (!Character.isSpaceChar(cmd.charAt(i))) { + break; + } + } + } + if (isVerbose()) { + System.out.println("Command list:"); + for (String s : command) { + System.out.println(s); + } + } + } else { + command.add(getSTclient()); + } + return command; + } + + // Returns null if the service tag record not found; + // or throw UnauthorizedAccessException or IOException + // based on the exitValue. + private static ServiceTag checkReturnError(int exitValue, + String output, + ServiceTag st) throws IOException { + switch (exitValue) { + case ST_ERR_REC_NOT_FOUND: + return null; + case ST_ERR_NOT_AUTH: + if (st != null) { + throw new UnauthorizedAccessException( + "Not authorized to access " + st.getInstanceURN() + + " installer_uid=" + st.getInstallerUID()); + } else { + throw new UnauthorizedAccessException( + "Not authorized:" + output); + } + default: + throw new IOException("stclient exits with error" + + " (" + exitValue + ")\n" + output); + } + } + + /** + * Returns a {@code ServiceTag} object of the given <tt>instance_urn</tt> + * in this registry. + * + * @param instanceURN the <tt>instance_urn</tt> of the service tag + * @return a {@code ServiceTag} object of the given <tt>instance_urn</tt> + * in this registry; or {@code null} if not found. + * + * @throws java.io.IOException if an I/O error occurs in this operation. + */ + private static ServiceTag getServiceTag(String instanceURN) throws IOException { + if (instanceURN == null) { + throw new NullPointerException("instanceURN is null"); + } + + List<String> command = getCommandList(); + command.add("-g"); + command.add("-i"); + command.add(instanceURN); + + ProcessBuilder pb = new ProcessBuilder(command); + Process p = pb.start(); + String output = commandOutput(p); + if (isVerbose()) { + System.out.println("Output from stclient -g command:"); + System.out.println(output); + } + if (p.exitValue() == 0) { + return parseServiceTag(output); + } else { + return checkReturnError(p.exitValue(), output, null); + } + } + + private static ServiceTag parseServiceTag(String output) throws IOException { + BufferedReader in = null; + try { + Properties props = new Properties(); + // parse the service tag output from stclient + in = new BufferedReader(new StringReader(output)); + String line = null; + while ((line = in.readLine()) != null) { + if ((line = line.trim()).length() > 0) { + String[] ss = line.trim().split("=", 2); + if (ss.length == 2) { + props.setProperty(ss[0].trim(), ss[1].trim()); + } else { + props.setProperty(ss[0].trim(), ""); + } + } + } + + String urn = props.getProperty(ST_NODE_INSTANCE_URN); + String productName = props.getProperty(ST_NODE_PRODUCT_NAME); + String productVersion = props.getProperty(ST_NODE_PRODUCT_VERSION); + String productURN = props.getProperty(ST_NODE_PRODUCT_URN); + String productParent = props.getProperty(ST_NODE_PRODUCT_PARENT); + String productParentURN = props.getProperty(ST_NODE_PRODUCT_PARENT_URN); + String productDefinedInstanceID = + props.getProperty(ST_NODE_PRODUCT_DEFINED_INST_ID); + String productVendor = props.getProperty(ST_NODE_PRODUCT_VENDOR); + String platformArch = props.getProperty(ST_NODE_PLATFORM_ARCH); + String container = props.getProperty(ST_NODE_CONTAINER); + String source = props.getProperty(ST_NODE_SOURCE); + int installerUID = + Util.getIntValue(props.getProperty(ST_NODE_INSTALLER_UID)); + Date timestamp = + Util.parseTimestamp(props.getProperty(ST_NODE_TIMESTAMP)); + + return new ServiceTag(urn, + productName, + productVersion, + productURN, + productParent, + productParentURN, + productDefinedInstanceID, + productVendor, + platformArch, + container, + source, + installerUID, + timestamp); + } finally { + if (in != null) { + in.close(); + } + } + + } + + /** + * Returns the urn of this registry. + * + * @return a {@code String} for the urn of this registry. + * + * @throws java.io.IOException if an I/O error occurs in this operation. + */ + // Once JDK makes this method available, we'll deprecate this method + // @deprecated Use the JDK version when available. + public static String getRegistryURN() throws IOException { + List<String> command = getCommandList(); + command.add("-x"); + + BufferedReader in = null; + try { + ProcessBuilder pb = new ProcessBuilder(command); + Process p = pb.start(); + String output = commandOutput(p); + + String registryURN = null; + if (p.exitValue() == 0) { + // parse the service tag output from stclient + in = new BufferedReader(new StringReader(output)); + String line = null; + while ((line = in.readLine()) != null) { + String s = line.trim(); + if (s.indexOf(REGISTRY_URN) != -1) { + s = s.substring(s.indexOf(REGISTRY_URN) + + REGISTRY_URN.length()); + if (s.indexOf("\"") != -1) { + s = s.substring(0, s.indexOf("\"")); + registryURN = s; + break; + } + } + } + } else { + checkReturnError(p.exitValue(), output, null); + } + return registryURN; + } finally { + if (in != null) { + in.close(); + } + } + } + + /** + * Returns all the service tags in this registry. + * + * @return a {@code Set} of {@code ServiceTag} objects + * in this registry. + * + * @throws java.io.IOException if an I/O error occurs in this operation. + */ + // Once JDK makes this method available, we'll deprecate this method + // @deprecated Use the JDK version when available. + public static Set<ServiceTag> getServiceTags() throws IOException { + List<String> command = getCommandList(); + command.add("-x"); + + BufferedReader in = null; + try { + ProcessBuilder pb = new ProcessBuilder(command); + Process p = pb.start(); + String output = commandOutput(p); + + Set<ServiceTag> instances = new HashSet<ServiceTag>(); + if (p.exitValue() == 0) { + // parse the service tag output from stclient + in = new BufferedReader(new StringReader(output)); + String line = null; + while ((line = in.readLine()) != null) { + String s = line.trim(); + if (s.indexOf(INSTANCE_URN_OPEN_ELEMENT) != -1 + && s.indexOf(INSTANCE_URN_CLOSE_ELEMENT) != -1) { + s = s.substring(s.indexOf(INSTANCE_URN_OPEN_ELEMENT) + + INSTANCE_URN_OPEN_ELEMENT.length(), + s.indexOf(INSTANCE_URN_CLOSE_ELEMENT)); + try { + instances.add(getServiceTag(s)); + } catch (Exception e) { + } + } + } + } else { + checkReturnError(p.exitValue(), output, null); + } + return instances; + } finally { + if (in != null) { + in.close(); + } + } + } +} diff --git a/desktop/source/registration/com/sun/star/servicetag/SystemEnvironment.java b/desktop/source/registration/com/sun/star/servicetag/SystemEnvironment.java new file mode 100644 index 000000000000..013c1251bc78 --- /dev/null +++ b/desktop/source/registration/com/sun/star/servicetag/SystemEnvironment.java @@ -0,0 +1,436 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +package com.sun.star.servicetag; + +// The Service Tags team maintains the latest version of the implementation +// for system environment data collection. JDK will include a copy of +// the most recent released version for a JDK release. We rename +// the package to com.sun.servicetag so that the Sun Connection +// product always uses the latest version from the com.sun.scn.servicetags +// package. JDK and users of the com.sun.servicetag API +// (e.g. NetBeans and SunStudio) will use the version in JDK. + +import java.io.*; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * SystemEnvironment class collects the environment data with the + * best effort from the underlying platform. + */ +public class SystemEnvironment { + private String hostname; + private String hostId; + private String osName; + private String osVersion; + private String osArchitecture; + private String systemModel; + private String systemManufacturer; + private String cpuManufacturer; + private String serialNumber; + private String physmem; + private String sockets; + private String cores; + private String virtcpus; + private String cpuname; + private String clockrate; + private static SystemEnvironment sysEnv = null; + + public static synchronized SystemEnvironment getSystemEnvironment() { + if (sysEnv == null) { + String os = System.getProperty("os.name"); + if (os.equals("SunOS")) { + sysEnv = new SolarisSystemEnvironment(); + } else if (os.equals("Linux")) { + sysEnv = new LinuxSystemEnvironment(); + } else if (os.startsWith("Windows")) { + sysEnv = new WindowsSystemEnvironment(); + } else { + sysEnv = new SystemEnvironment(); + } + } + return sysEnv; + } + + // package-private + SystemEnvironment() { + try { + this.hostname = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException ex) { + this.hostname = "Unknown host"; + } + this.hostId = ""; + this.osName = System.getProperty("os.name"); + this.osVersion = System.getProperty("os.version"); + this.osArchitecture = System.getProperty("os.arch"); + this.systemModel = ""; + this.systemManufacturer = ""; + this.cpuManufacturer = ""; + this.serialNumber = ""; + this.physmem = "0"; + this.sockets = "0"; + this.cores = "0"; + this.virtcpus = "0"; + this.cpuname = ""; + this.clockrate = "0"; + } + + + /** + * Sets the hostname. + * @param hostname The hostname to set. + */ + public void setHostname(String hostname) { + this.hostname = hostname; + } + + /** + * Sets the OS name. + * @param osName The osName to set. + */ + public void setOsName(String osName) { + this.osName = osName; + } + + /** + * Sets the OS version. + * @param osVersion The osVersion to set. + */ + public void setOsVersion(String osVersion) { + this.osVersion = osVersion; + } + + /** + * Sets the OS architecture. + * @param osArchitecture The osArchitecture to set. + */ + public void setOsArchitecture(String osArchitecture) { + this.osArchitecture = osArchitecture; + } + + /** + * Sets the system model. + * @param systemModel The systemModel to set. + */ + public void setSystemModel(String systemModel) { + this.systemModel = systemModel; + } + + /** + * Sets the system manufacturer. + * @param systemManufacturer The systemManufacturer to set. + */ + public void setSystemManufacturer(String systemManufacturer) { + this.systemManufacturer = systemManufacturer; + } + + /** + * Sets the cpu manufacturer. + * @param cpuManufacturer The cpuManufacturer to set. + */ + public void setCpuManufacturer(String cpuManufacturer) { + this.cpuManufacturer = cpuManufacturer; + } + + /** + * Sets the serial number. + * @param serialNumber The serialNumber to set. + */ + public void setSerialNumber(String serialNumber) { + this.serialNumber = serialNumber; + } + + /** + * Sets the physmem + * @param physmem The physmem to set. + */ + public void setPhysMem(String physmem) { + if (physmem.length() == 0) + physmem = "0"; + this.physmem = physmem; + } + + /** + * Sets the sockets + * @param sockets The sockets to set. + */ + public void setSockets(String sockets) { + if (sockets.length() == 0) + sockets = "0"; + this.sockets = sockets; + } + + /** + * Sets the cores + * @param cores The cores to set. + */ + public void setCores(String cores) { + if (cores.length() == 0) + cores ="0"; + this.cores = cores; + } + + /** + * Sets the virtcpus + * @param virtcpus The virtcpus to set. + */ + public void setVirtCpus(String virtcpus) { + if (virtcpus.length() == 0) + virtcpus = "0"; + this.virtcpus = virtcpus; + } + + /** + * Sets the cpuname + * @param cpuname The cpuname to set. + */ + public void setCpuName(String cpuname) { + this.cpuname = cpuname; + } + + /** + * Sets the clockrate + * @param clockrate The clockrate to set. + */ + public void setClockRate(String clockrate) { + if (clockrate.length() == 0) + this.clockrate = "0"; + else + { + Float f = Float.parseFloat(clockrate); + Integer nClockrate = f.intValue(); + this.clockrate = nClockrate.toString(); + } + } + + /** + * Sets the hostid. Truncates to a max length of 16 chars. + * @param hostId The hostid to set. + */ + public void setHostId(String hostId) { + if (hostId == null || hostId.equals("null")) { + hostId = ""; + } + if (hostId.length() > 16) { + hostId = hostId.substring(0,16); + } + this.hostId = hostId; + } + + /** + * Returns the hostname. + * @return The hostname. + */ + public String getHostname() { + return hostname; + } + + /** + * Returns the osName. + * @return The osName. + */ + public String getOsName() { + return osName; + } + + /** + * Returns the osVersion. + * @return The osVersion. + */ + public String getOsVersion() { + return osVersion; + } + + /** + * Returns the osArchitecture. + * @return The osArchitecture. + */ + public String getOsArchitecture() { + return osArchitecture; + } + + /** + * Returns the systemModel. + * @return The systemModel. + */ + public String getSystemModel() { + return systemModel; + } + + /** + * Returns the systemManufacturer. + * @return The systemManufacturer. + */ + public String getSystemManufacturer() { + return systemManufacturer; + } + + /** + * Returns the serialNumber. + * @return The serialNumber. + */ + public String getSerialNumber() { + return serialNumber; + } + + public String getPhysMem() { + return physmem; + } + + public String getSockets() { + return sockets; + } + + public String getCores() { + return cores; + } + + public String getVirtCpus() { + return virtcpus; + } + + public String getCpuName() { + return cpuname; + } + + public String getClockRate() { + return clockrate; + } + + /** + * Returns the hostId. + * @return The hostId. + */ + public String getHostId() { + return hostId; + } + + /** + * Returns the cpuManufacturer. + * @return The cpuManufacturer. + */ + public String getCpuManufacturer() { + return cpuManufacturer; + } + + protected String getCommandOutput(String... command) { + StringBuilder sb = new StringBuilder(); + BufferedReader br = null; + Process p = null; + try { + ProcessBuilder pb = new ProcessBuilder(command); + p = pb.start(); + p.waitFor(); + + if (p.exitValue() == 0) { + br = new BufferedReader(new InputStreamReader(p.getInputStream())); + String line = null; + while ((line = br.readLine()) != null) { + line = line.trim(); + if (line.length() > 0) { + if (sb.length() > 0) { + sb.append("\n"); + } + sb.append(line); + } + } + } + return sb.toString(); + } catch (InterruptedException ie) { + // in case the command hangs + if (p != null) { + p.destroy(); + } + return ""; + } catch (Exception e) { + // ignore exception + return ""; + } finally { + if (p != null) { + try { + p.getErrorStream().close(); + } catch (IOException e) { + // ignore + } + try { + p.getInputStream().close(); + } catch (IOException e) { + // ignore + } + try { + p.getOutputStream().close(); + } catch (IOException e) { + // ignore + } + p = null; + } + if (br != null) { + try { + br.close(); + } catch (IOException e) { + // ignore + } + } + } + } + + protected String getFileContent(String filename) { + File f = new File(filename); + if (!f.exists()) { + return ""; + } + + StringBuilder sb = new StringBuilder(); + BufferedReader br = null; + try { + br = new BufferedReader(new FileReader(f)); + String line = null; + while ((line = br.readLine()) != null) { + line = line.trim(); + if (line.length() > 0) { + if (sb.length() > 0) { + sb.append("\n"); + } + sb.append(line); + } + } + return sb.toString(); + } catch (Exception e) { + // ignore exception + return ""; + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException e) { + // ignore + } + } + } + } +} diff --git a/desktop/source/registration/com/sun/star/servicetag/UnauthorizedAccessException.java b/desktop/source/registration/com/sun/star/servicetag/UnauthorizedAccessException.java new file mode 100644 index 000000000000..a6d41e07b3cf --- /dev/null +++ b/desktop/source/registration/com/sun/star/servicetag/UnauthorizedAccessException.java @@ -0,0 +1,55 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +package com.sun.star.servicetag; + +/** + * Thrown if the user is not authorized to + * {@link Registry#updateServiceTag update} or + * {@link Registry#removeServiceTag remove} + * a service tag from a {@link Registry}. + */ +public class UnauthorizedAccessException extends RuntimeException { + + /** + * Constructs an <code>UnauthorizedAccessException</code> object + * without detail message. + */ + public UnauthorizedAccessException() { + } + + + /** + * Constructs an <code>UnauthorizedAccessException</code> object + * with the specified detail message. + * + * @param msg the detail message. + */ + public UnauthorizedAccessException(String msg) { + super(msg); + } +} diff --git a/desktop/source/registration/com/sun/star/servicetag/Util.java b/desktop/source/registration/com/sun/star/servicetag/Util.java new file mode 100644 index 000000000000..c1cb14f7c2d5 --- /dev/null +++ b/desktop/source/registration/com/sun/star/servicetag/Util.java @@ -0,0 +1,293 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +package com.sun.star.servicetag; + +import java.io.*; +import java.util.Date; +import java.text.SimpleDateFormat; +import java.text.ParseException; +import java.util.TimeZone; +import java.util.UUID; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +// Utility class for com.sun.servicetag package +class Util { + private static boolean verbose = (System.getProperty("servicetag.verbose") != null); + private static String jrepath = null; + + // for debugging and tracing + static boolean isVerbose() { + return verbose; + } + + /** + * Gets the pathname of JRE in the running platform + * This can be a JDK or JRE. + */ + static synchronized String getJrePath() { + if (jrepath == null) { + // Determine the JRE path by checking the existence of + // <HOME>/jre/lib and <HOME>/lib. + String javaHome = System.getProperty("java.home"); + jrepath = javaHome + File.separator + "jre"; + File f = new File(jrepath, "lib"); + if (!f.exists()) { + // java.home usually points to the JRE path + jrepath = javaHome; + } + } + return jrepath; + } + + /** + * Tests if the running platform is a JDK. + */ + static boolean isJdk() { + // <HOME>/jre exists which implies it's a JDK + return getJrePath().endsWith(File.separator + "jre"); + } + + /** + * Generates the URN string of "urn:st" namespace + */ + static String generateURN() { + return "urn:st:" + UUID.randomUUID().toString(); + } + + static int getIntValue(String value) { + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("\"" + value + "\"" + + " expected to be an integer"); + } + } + + /** + * Formats the Date into a timestamp string in YYYY-MM-dd HH:mm:ss GMT. + * @param timestamp Date + * @return a string representation of the timestamp + * in the YYYY-MM-dd HH:mm:ss GMT format. + */ + static String formatTimestamp(Date timestamp) { + if (timestamp == null) { + return "[No timestamp]"; + } + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); + df.setTimeZone(TimeZone.getTimeZone("GMT")); + return df.format(timestamp); + } + + /** + * Parses a timestamp string in YYYY-MM-dd HH:mm:ss GMT format. + * @param timestamp Timestamp in the YYYY-MM-dd HH:mm:ss GMT format. + * @return Date + */ + static Date parseTimestamp(String timestamp) { + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); + df.setTimeZone(TimeZone.getTimeZone("GMT")); + try { + return df.parse(timestamp); + } catch (ParseException e) { + // should not reach here + e.printStackTrace(); + return new Date(); + } + } + + static String commandOutput(Process p) throws IOException { + Reader r = null; + Reader err = null; + try { + r = new InputStreamReader(p.getInputStream()); + err = new InputStreamReader(p.getErrorStream()); + String output = commandOutput(r); + String errorMsg = commandOutput(err); + p.waitFor(); + return output + errorMsg.trim(); + } catch (InterruptedException e) { + if (isVerbose()) { + e.printStackTrace(); + } + return e.getMessage(); + } finally { + if (r != null) { + r.close(); + } + if (err != null) { + err.close(); + } + } + } + + static String commandOutput(Reader r) throws IOException { + StringBuilder sb = new StringBuilder(); + int c; + while ((c = r.read()) > 0) { + if (c != '\r') { + sb.append((char) c); + } + } + return sb.toString(); + } + + static int getJdkVersion() { + parseVersion(); + return jdkVersion; + } + + static int getUpdateVersion() { + parseVersion(); + return jdkUpdate; + } + + private static int jdkVersion = 0; + private static int jdkUpdate = 0; + private static synchronized void parseVersion() { + if (jdkVersion > 0) { + return; + } + + // parse java.runtime.version + // valid format of the version string is: + // n.n.n[_uu[c]][-<identifer>]-bxx + String cs = System.getProperty("java.runtime.version"); + if (cs.length() >= 5 && + Character.isDigit(cs.charAt(0)) && cs.charAt(1) == '.' && + Character.isDigit(cs.charAt(2)) && cs.charAt(3) == '.' && + Character.isDigit(cs.charAt(4))) { + jdkVersion = Character.digit(cs.charAt(2), 10); + cs = cs.substring(5, cs.length()); + if (cs.charAt(0) == '_' && cs.length() >= 3 && + Character.isDigit(cs.charAt(1)) && + Character.isDigit(cs.charAt(2))) { + int nextChar = 3; + try { + String uu = cs.substring(1, 3); + jdkUpdate = Integer.valueOf(uu).intValue(); + } catch (NumberFormatException e) { + // not conforming to the naming convention + return; + } + } + } else { + throw new InternalError("Invalid java.runtime.version" + cs); + } + } + + /** + * Returns this java string as a null-terminated byte array + */ + private static byte[] stringToByteArray(String str) { + return (str + "\u0000").getBytes(); + } + + /** + * Converts a null-terminated byte array to java string + */ + private static String byteArrayToString(byte[] array) { + return new String(array, 0, array.length -1); + } + + /** + * Gets the stclient path using a well known location from + * the Windows platform Registry, otherwise it will return null. + */ + static File getWindowsStClientFile() { + File out = null; + String regKey = "software\\microsoft\\windows\\currentversion\\app paths\\stclient.exe"; + String keyName = "" ; // use the default key + String path = getRegistryKey(regKey, keyName); + + if (path != null && (new File(path)).exists()) { + out = new File(path); + } + if (isVerbose()) { + System.out.println("stclient=" + out); + } + return out; + } + + /** + * This uses reflection to access a private java windows registry + * interface, any changes to that Class must be appropriately adjusted. + * Returns a null if unsuccessful. + */ + private static String getRegistryKey(String regKey, String keyName) { + String out = null; + try { + Class<?> clazz = Class.forName("java.util.prefs.WindowsPreferences"); + + // Get the registry methods + Method winRegOpenKeyM = clazz.getDeclaredMethod("WindowsRegOpenKey", + int.class, byte[].class, int.class); + winRegOpenKeyM.setAccessible(true); + + Method winRegCloseKeyM = clazz.getDeclaredMethod("WindowsRegCloseKey", + int.class); + winRegCloseKeyM.setAccessible(true); + + Method winRegQueryValueM = clazz.getDeclaredMethod("WindowsRegQueryValueEx", + int.class, byte[].class); + winRegQueryValueM.setAccessible(true); + + // Get all the constants we need + int HKLM = getValueFromStaticField("HKEY_LOCAL_MACHINE", clazz); + int KEY_READ = getValueFromStaticField("KEY_READ", clazz); + int ERROR_CODE = getValueFromStaticField("ERROR_CODE", clazz); + int NATIVE_HANDLE = getValueFromStaticField("NATIVE_HANDLE", clazz); + int ERROR_SUCCESS = getValueFromStaticField("ERROR_SUCCESS", clazz); + + // Convert keys + byte[] reg = stringToByteArray(regKey); + byte[] key = stringToByteArray(keyName); + + // Open the registry + int[] result = (int[]) winRegOpenKeyM.invoke(null, HKLM, reg, KEY_READ); + + if (result[ERROR_CODE] == ERROR_SUCCESS) { + byte[] stvalue = (byte[]) winRegQueryValueM.invoke(null, + result[NATIVE_HANDLE], key); + out = byteArrayToString(stvalue); + winRegCloseKeyM.invoke(null, result[NATIVE_HANDLE]); + } + } catch (Exception ex) { + if (isVerbose()) { + ex.printStackTrace(); + } + } + return out; + } + + private static int getValueFromStaticField(String fldName, Class<?> klass) throws Exception { + Field f = klass.getDeclaredField(fldName); + f.setAccessible(true); + return f.getInt(null); + } +} diff --git a/desktop/source/registration/com/sun/star/servicetag/WindowsSystemEnvironment.java b/desktop/source/registration/com/sun/star/servicetag/WindowsSystemEnvironment.java new file mode 100644 index 000000000000..fd500a8ac810 --- /dev/null +++ b/desktop/source/registration/com/sun/star/servicetag/WindowsSystemEnvironment.java @@ -0,0 +1,232 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +package com.sun.star.servicetag; + +// The Service Tags team maintains the latest version of the implementation +// for system environment data collection. JDK will include a copy of +// the most recent released version for a JDK release. We rename +// the package to com.sun.servicetag so that the Sun Connection +// product always uses the latest version from the com.sun.scn.servicetags +// package. JDK and users of the com.sun.servicetag API +// (e.g. NetBeans and SunStudio) will use the version in JDK. + +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.HashSet; +import java.util.Set; + +/** + * Windows implementation of the SystemEnvironment class. + */ +class WindowsSystemEnvironment extends SystemEnvironment { + WindowsSystemEnvironment() { + super(); + + // run a call to make sure things are initialized + // ignore the first call result as the system may + // give inconsistent data on the first invocation ever + getWmicResult("computersystem", "get", "model"); + + setSystemModel(getWmicResult("computersystem", "get", "model")); + setSystemManufacturer(getWmicResult("computersystem", "get", "manufacturer")); + setSerialNumber(getWmicResult("bios", "get", "serialnumber")); + + String cpuMfr = getWmicResult("cpu", "get", "manufacturer"); + // this isn't as good an option, but if we couldn't get anything + // from wmic, try the processor_identifier + if (cpuMfr.length() == 0) { + String procId = System.getenv("processor_identifer"); + if (procId != null) { + String[] s = procId.split(","); + cpuMfr = s[s.length - 1].trim(); + } + } + setCpuManufacturer(cpuMfr); + + setSockets(getWindowsSockets()); + setCores(getWindowsCores()); + setVirtCpus(getWindowsVirtCpus()); + setPhysMem(getWindowsPhysMem()); + setCpuName(getWmicResult("cpu", "get", "Name")); + setClockRate(getWmicResult("cpu", "get", "MaxClockSpeed")); + + // try to remove the temp file that gets created from running wmic cmds + try { + // look in the current working directory + File f = new File("TempWmicBatchFile.bat"); + if (f.exists()) { + f.delete(); + } + } catch (Exception e) { + // ignore the exception + } + } + + private String getWindowsVirtCpus() { + String res = getWmicResult("cpu", "get", "NumberOfLogicalProcessors"); + if (res == null || res.equals("")) { + res = "1"; + } + return res; + } + + private String getWindowsCores() { + String res = getWmicResult("cpu", "get", "NumberOfCores"); + if (res == null || res.equals("")) { + res = "1"; + } + return res; + } + + private String getWindowsSockets() { + String res = getFullWmicResult("cpu", "get", "DeviceID"); + Set<String> set = new HashSet<String>(); + for (String line : res.split("\n")) { + line = line.trim(); + if (line.equals("")) { + continue; + } + set.add(line); + } + if (set.size() == 0) { + return "1"; + } + return "" + set.size(); + } + + private String getWindowsPhysMem() { + String mem = getWmicResult("computersystem", "get", "TotalPhysicalMemory"); + long l = Long.parseLong(mem); + return "" + ((long) (l / (1024*1024))); + } + + + /** + * This method invokes wmic outside of the normal environment + * collection routines. + * + * An initial call to wmic can be costly in terms of time. + * + * <code> + * Details of why the first call is costly can be found at: + * + * http://support.microsoft.com/kb/290216/en-us + * + * "When you run the Wmic.exe utility for the first time, the utility + * compiles its .mof files into the repository. To save time during + * Windows installation, this operation takes place as necessary." + * </code> + */ + private String getWmicResult(String alias, String verb, String property) { + String res = ""; + BufferedReader in = null; + try { + ProcessBuilder pb = new ProcessBuilder("cmd", "/C", "WMIC", alias, verb, property); + Process p = pb.start(); + // need this for executing windows commands (at least + // needed for executing wmic command) + BufferedWriter bw = new BufferedWriter( + new OutputStreamWriter(p.getOutputStream())); + bw.write(13); + bw.flush(); + bw.close(); + + p.waitFor(); + if (p.exitValue() == 0) { + in = new BufferedReader(new InputStreamReader(p.getInputStream())); + String line = null; + while ((line = in.readLine()) != null) { + line = line.trim(); + if (line.length() == 0) { + continue; + } + res = line; + } + // return the *last* line read + return res; + } + + } catch (Exception e) { + // ignore the exception + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + // ignore + } + } + } + return res.trim(); + } + + private String getFullWmicResult(String alias, String verb, String property) { + String res = ""; + BufferedReader in = null; + try { + ProcessBuilder pb = new ProcessBuilder("cmd", "/C", "WMIC", alias, verb, property); + Process p = pb.start(); + // need this for executing windows commands (at least + // needed for executing wmic command) + BufferedWriter bw = new BufferedWriter( + new OutputStreamWriter(p.getOutputStream())); + bw.write(13); + bw.flush(); + bw.close(); + + p.waitFor(); + if (p.exitValue() == 0) { + in = new BufferedReader(new InputStreamReader(p.getInputStream())); + String line = null; + while ((line = in.readLine()) != null) { + line = line.trim(); + if (line.length() == 0) { + continue; + } + if (line.toLowerCase().indexOf(property.toLowerCase()) != -1) { + continue; + } + res += line + "\n"; + } + } + + } catch (Exception e) { + // ignore the exception + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + // ignore + } + } + } + return res; + } +} diff --git a/desktop/source/registration/com/sun/star/servicetag/makefile.mk b/desktop/source/registration/com/sun/star/servicetag/makefile.mk new file mode 100644 index 000000000000..784964652950 --- /dev/null +++ b/desktop/source/registration/com/sun/star/servicetag/makefile.mk @@ -0,0 +1,79 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +PRJNAME = setup_native +PRJ = ..$/..$/..$/..$/..$/.. +TARGET = servicetag +PACKAGE = com$/sun$/star$/servicetag + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +.IF "$(ENABLE_SVCTAGS)" == "YES" + +JARFILES = jurt.jar unoil.jar ridl.jar +JAVAFILES = \ + BrowserSupport.java \ + Installer.java \ + LinuxSystemEnvironment.java \ + RegistrationData.java \ + RegistrationDocument.java \ + Registry.java \ + ServiceTag.java \ + SolarisServiceTag.java \ + SolarisSystemEnvironment.java \ + SunConnection.java \ + SysnetRegistryHelper.java \ + SystemEnvironment.java \ + UnauthorizedAccessException.java \ + Util.java \ + WindowsSystemEnvironment.java + +JAVACLASSFILES= $(foreach,i,$(JAVAFILES) $(CLASSDIR)$/$(PACKAGE)$/$(i:b).class) + +JARTARGET = $(TARGET).jar +JARCOMPRESS = TRUE +JARCLASSDIRS = $(PACKAGE) + +JAVARES= $(CLASSDIR)$/$(PACKAGE)$/resources$/product_registration.xsd + +.ENDIF # "$(ENABLE_SVCTAGS)" == "YES" + +# --- Targets ------------------------------------------------------ + + +.INCLUDE : target.mk + +.IF "$(ENABLE_SVCTAGS)" == "YES" +ALLTAR: $(JAVARES) + +$(JAVARES) : $$(@:d:d:f)$/$$(@:f) + $(MKDIRHIER) $(@:d) + $(COPY) $< $@ + +.ENDIF # "$(ENABLE_SVCTAGS)" == "YES" diff --git a/desktop/source/registration/com/sun/star/servicetag/resources/product_registration.xsd b/desktop/source/registration/com/sun/star/servicetag/resources/product_registration.xsd new file mode 100644 index 000000000000..6681a563a01e --- /dev/null +++ b/desktop/source/registration/com/sun/star/servicetag/resources/product_registration.xsd @@ -0,0 +1,366 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> + +<xs:element name="registration_data"> + <xs:complexType> + <xs:sequence> + <xs:element name="environment" + minOccurs="1" + maxOccurs="1"> + <xs:complexType> + <xs:sequence> + <xs:element ref="hostname" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="hostId" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="osName" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="osVersion" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="osArchitecture" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="systemModel" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="systemManufacturer" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="cpuManufacturer" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="serialNumber" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="physmem" + minOccurs='0' + maxOccurs='1'/> + <xs:element name="cpuinfo" + minOccurs='0' + maxOccurs='1'> + <xs:complexType> + <xs:sequence> + <xs:element ref="sockets" + minOccurs='0' + maxOccurs='1'/> + <xs:element ref="cores" + minOccurs='0' + maxOccurs='1'/> + <xs:element ref="virtcpus" + minOccurs='0' + maxOccurs='1'/> + <xs:element ref="name" + minOccurs='0' + maxOccurs='1'/> + <xs:element ref="clockrate" + minOccurs='0' + maxOccurs='1'/> + </xs:sequence> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="registry" + minOccurs="1" + maxOccurs="1"> + <xs:complexType> + <xs:sequence> + <xs:element name="service_tag" + minOccurs="0" + maxOccurs="1024"> + <xs:complexType> + <xs:sequence> + <xs:element ref="instance_urn" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="product_name" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="product_version" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="product_urn" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="product_parent_urn" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="product_parent" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="product_defined_inst_id" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="product_vendor" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="platform_arch" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="timestamp" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="container" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="source" + minOccurs='1' + maxOccurs='1'/> + <xs:element ref="installer_uid" + minOccurs='1' + maxOccurs='1'/> + </xs:sequence> + </xs:complexType> + </xs:element> + </xs:sequence> + <xs:attribute name="urn" + type="xs:string" + use="required"/> + <xs:attribute name="version" + type="xs:string" + use="required"/> + </xs:complexType> + </xs:element> + </xs:sequence> + <xs:attribute name="version" + type="xs:string" + use="required"/> + </xs:complexType> +</xs:element> + + <!-- definition of simple elements --> + <xs:element name="hostname"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="1"/> + <xs:maxLength value="255"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="hostId"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="0"/> + <xs:maxLength value="16"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="osName"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="1"/> + <xs:maxLength value="256"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="osVersion"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="0"/> + <xs:maxLength value="50"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="osArchitecture"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="0"/> + <xs:maxLength value="256"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="systemModel"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="0"/> + <xs:maxLength value="50"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="systemManufacturer"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="0"/> + <xs:maxLength value="50"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="cpuManufacturer"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="0"/> + <xs:maxLength value="50"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="serialNumber"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="0"/> + <xs:maxLength value="256"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="instance_urn"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="1"/> + <xs:maxLength value="255"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="product_name"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:maxLength value="255"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="product_version"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:maxLength value="63"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="product_urn"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="1"/> + <xs:maxLength value="255"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="product_parent_urn"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="0"/> + <xs:maxLength value="255"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="product_parent"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="0"/> + <xs:maxLength value="255"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="product_defined_inst_id"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="0"/> + <xs:maxLength value="255"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="product_vendor"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="0"/> + <xs:maxLength value="63"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="platform_arch"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="0"/> + <xs:maxLength value="63"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="timestamp"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:maxLength value="24"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="container"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:maxLength value="63"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="source"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:maxLength value="63"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="installer_uid"> + <xs:simpleType> + <xs:restriction base="xs:integer"> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="physmem"> + <xs:simpleType> + <xs:restriction base="xs:integer"/> + </xs:simpleType> + </xs:element> + + <xs:element name="sockets"> + <xs:simpleType> + <xs:restriction base="xs:integer"/> + </xs:simpleType> + </xs:element> + + <xs:element name="cores"> + <xs:simpleType> + <xs:restriction base="xs:integer"/> + </xs:simpleType> + </xs:element> + + <xs:element name="virtcpus"> + <xs:simpleType> + <xs:restriction base="xs:integer"/> + </xs:simpleType> + </xs:element> + + <xs:element name="name"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:maxLength value="128"/> + </xs:restriction> + </xs:simpleType> + </xs:element> + + <xs:element name="clockrate"> + <xs:simpleType> + <xs:restriction base="xs:integer"/> + </xs:simpleType> + </xs:element> + +</xs:schema> diff --git a/desktop/source/so_comp/evaluation.cxx b/desktop/source/so_comp/evaluation.cxx new file mode 100644 index 000000000000..664c0dadb269 --- /dev/null +++ b/desktop/source/so_comp/evaluation.cxx @@ -0,0 +1,208 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "evaluation.hxx" +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/util/Date.hpp> +#include <rtl/ustrbuf.hxx> +#include <uno/environment.h> +#include <cppuhelper/factory.hxx> +#include <unotools/configmgr.hxx> +#include <vcl/msgbox.hxx> +#include <tools/resmgr.hxx> +#include <tools/resid.hxx> +#include "../app/desktop.hrc" + + +using namespace rtl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::registry; + +namespace desktop { + +static SOEvaluation* pSOEval=0; + +const char* SOEvaluation::interfaces[] = +{ + "com.sun.star.beans.XExactName", + "com.sun.star.beans.XMaterialHolder", + "com.sun.star.lang.XComponent", + "com.sun.star.lang.XServiceInfo", + NULL, +}; + +const char* SOEvaluation::implementationName = "com.sun.star.comp.desktop.Evaluation"; +const char* SOEvaluation::serviceName = "com.sun.star.office.Evaluation"; + +OUString SOEvaluation::GetImplementationName() +{ + return OUString::createFromAscii(implementationName); +} + +Sequence< OUString > SOEvaluation::GetSupportedServiceNames() +{ + sal_Int32 nSize = (sizeof( interfaces ) / sizeof( const char *)) - 1; + Sequence< OUString > aResult( nSize ); + + for( sal_Int32 i = 0; i < nSize; i++ ) + aResult[i] = OUString::createFromAscii( interfaces[i] ); + return aResult; +} + +Reference< XInterface > SAL_CALL SOEvaluation::CreateInstance( + const Reference< XMultiServiceFactory >& rSMgr ) +{ + static osl::Mutex aMutex; + if ( pSOEval == 0 ) + { + osl::MutexGuard guard( aMutex ); + if ( pSOEval == 0 ) + return (XComponent*) ( new SOEvaluation( rSMgr ) ); + } + return (XComponent*)0; +} + +SOEvaluation::SOEvaluation( const Reference< XMultiServiceFactory >& xFactory ) : + m_aListeners( m_aMutex ), + m_xServiceManager( xFactory ) +{ +} + +SOEvaluation::~SOEvaluation() +{ +} + +// XComponent +void SAL_CALL SOEvaluation::dispose() throw ( RuntimeException ) +{ + EventObject aObject; + aObject.Source = (XComponent*)this; + m_aListeners.disposeAndClear( aObject ); +} + +void SAL_CALL SOEvaluation::addEventListener( const Reference< XEventListener > & aListener) throw ( RuntimeException ) +{ + m_aListeners.addInterface( aListener ); +} + +void SAL_CALL SOEvaluation::removeEventListener( const Reference< XEventListener > & aListener ) throw ( RuntimeException ) +{ + m_aListeners.removeInterface( aListener ); +} + +// XExactName +rtl::OUString SAL_CALL SOEvaluation::getExactName( const rtl::OUString& rApproximateName ) throw ( RuntimeException ) +{ + // get the tabreg service for an evaluation version + // without this service office shouldn't run at all + OUString aTitle = rApproximateName; + OUString aEval; + sal_Bool bExpired = sal_True; + Reference < XMaterialHolder > xHolder( m_xServiceManager->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.tab.tabreg" ) ) ), UNO_QUERY ); + if ( xHolder.is() ) + { + // get a sequence of strings for the defined locales + // a registered version doesn't provide data + bExpired = sal_False; + Any aData = xHolder->getMaterial(); + Sequence < NamedValue > aSeq; + if ( aData >>= aSeq ) + { + // this is an evaluation version, because it provides "material" + bExpired = sal_True; + for (int i=0; i<aSeq.getLength(); i++ ) + { + NamedValue& rValue = aSeq[i]; + if ( rValue.Name.equalsAscii("expired") ) + rValue.Value >>= bExpired; + else if (rValue.Name.equalsAscii("title") ) + rValue.Value >>= aEval; + } + // append eval string to title + aTitle += OUString::createFromAscii(" ") + aEval; + if ( bExpired ) + throw RuntimeException(); + } + } + + return aTitle; +} + +// XMaterialHolder +Any SAL_CALL SOEvaluation::getMaterial() throw( RuntimeException ) +{ + // Time bomb implementation. Return empty Any to do nothing or + // provide a com::sun::star::util::Date with the time bomb date. + Any a; + + // change here to force recompile 00002 +#ifdef TIMEBOMB + // Code for extracting/providing time bomb date! + int nDay = TIMEBOMB % 100; + int nMonth = ( TIMEBOMB % 10000 ) / 100; + int nYear = TIMEBOMB / 10000; + com::sun::star::util::Date aDate( nDay, nMonth, nYear ); + a <<= aDate; +#endif + return a; +} + +// XServiceInfo +::rtl::OUString SAL_CALL SOEvaluation::getImplementationName() +throw ( RuntimeException ) +{ + return SOEvaluation::GetImplementationName(); +} + +sal_Bool SAL_CALL SOEvaluation::supportsService( const ::rtl::OUString& rServiceName ) +throw ( RuntimeException ) +{ + sal_Int32 nSize = (sizeof( interfaces ) / sizeof( const char *))-1; + + for( sal_Int32 i = 0; i < nSize; i++ ) + if ( rServiceName.equalsAscii( interfaces[i] )) + return sal_True; + return sal_False; +} + +Sequence< ::rtl::OUString > SAL_CALL SOEvaluation::getSupportedServiceNames() +throw ( RuntimeException ) +{ + return SOEvaluation::GetSupportedServiceNames(); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/so_comp/evaluation.hxx b/desktop/source/so_comp/evaluation.hxx new file mode 100644 index 000000000000..a34cc65253e8 --- /dev/null +++ b/desktop/source/so_comp/evaluation.hxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +/* makefile.mk changed 20030409, LO */ + +#ifndef _SOCOMP_EVALUATION_HXX_ +#define _SOCOMP_EVALUATION_HXX_ + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/beans/XExactName.hpp> +#include <com/sun/star/beans/XMaterialHolder.hpp> +#include <cppuhelper/implbase4.hxx> +#include <cppuhelper/interfacecontainer.h> + +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <osl/mutex.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; + +namespace desktop { + +class SOEvaluation : public ::cppu::WeakImplHelper4< XExactName, XMaterialHolder, XComponent, XServiceInfo > +{ + ::osl::Mutex m_aMutex; + ::cppu::OInterfaceContainerHelper m_aListeners; + Reference< XMultiServiceFactory > m_xServiceManager; + +public: + SOEvaluation( const Reference < XMultiServiceFactory >& xFactory ); + virtual ~SOEvaluation(); + + static Reference< XSingleServiceFactory > GetSOEvaluationFactory( Reference< XMultiServiceFactory > & xSMgr ); + static ::rtl::OUString GetImplementationName(); + static Sequence< rtl::OUString > GetSupportedServiceNames(); + + // XComponent + virtual void SAL_CALL dispose() throw ( RuntimeException ); + virtual void SAL_CALL addEventListener( const Reference< XEventListener > & aListener) throw ( RuntimeException ); + virtual void SAL_CALL removeEventListener(const Reference< XEventListener > & aListener) throw ( RuntimeException ); + + // XExactName + virtual rtl::OUString SAL_CALL getExactName( const rtl::OUString& rApproximateName ) throw ( RuntimeException ); + + // XMaterialHolder + virtual Any SAL_CALL getMaterial() throw ( RuntimeException ); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() throw ( RuntimeException ); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& rServiceName ) throw ( RuntimeException ); + virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw ( RuntimeException ); + + static const char* interfaces[]; + static const char* implementationName; + static const char* serviceName; + static Reference<XInterface> SAL_CALL CreateInstance( + const Reference< XMultiServiceFactory >&); + + + +}; +} +#endif // _SOCOMP_EVALUATION_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/so_comp/makefile.mk b/desktop/source/so_comp/makefile.mk new file mode 100644 index 000000000000..590f99518c68 --- /dev/null +++ b/desktop/source/so_comp/makefile.mk @@ -0,0 +1,77 @@ +#************************************************************************* +# +# 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=socomp +LIBTARGET=NO + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Define time bomb date. Not active for OOo -------------------- +# --- Change something in evaluation.cxx!!! (e.g. line 313) +# --- You must use the yyyymmdd format!!! -------------------------- +#CDEFS+=-DTIMEBOMB=20050930 + +# --- Files -------------------------------------------------------- + +SLOFILES = $(SLO)$/evaluation.obj \ + $(SLO)$/oemjob.obj \ + $(SLO)$/services.obj + +SHL1DEPN= makefile.mk +SHL1OBJS= $(SLOFILES) + + +SHL1TARGET= $(TARGET) +SHL1IMPLIB= i$(TARGET) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +DEF1NAME=$(SHL1TARGET) + +SHL1STDLIBS= \ + $(FWELIB) \ + $(VCLLIB) \ + $(SVLLIB) \ + $(SVTOOLLIB) \ + $(COMPHELPERLIB) \ + $(UNOTOOLSLIB) \ + $(TOOLSLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/desktop/source/so_comp/oemjob.cxx b/desktop/source/so_comp/oemjob.cxx new file mode 100644 index 000000000000..22bad75af489 --- /dev/null +++ b/desktop/source/so_comp/oemjob.cxx @@ -0,0 +1,283 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "oemjob.hxx" +#include <rtl/bootstrap.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/file.hxx> +#include <unotools/bootstrap.hxx> +#include <tools/config.hxx> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <com/sun/star/beans/NamedValue.hpp> + +using namespace rtl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::util; + +namespace desktop{ + +char const OEM_PRELOAD_SECTION[] = "Bootstrap"; +char const OEM_PRELOAD[] = "Preload"; +char const STR_TRUE[] = "1"; +char const STR_FALSE[] = "0"; + +const char* OEMPreloadJob::interfaces[] = +{ + "com.sun.star.task.XJob", + NULL, +}; +const char* OEMPreloadJob::implementationName = "com.sun.star.comp.desktop.OEMPreloadJob"; +const char* OEMPreloadJob::serviceName = "com.sun.star.office.OEMPreloadJob"; + +OUString OEMPreloadJob::GetImplementationName() +{ + return OUString::createFromAscii(implementationName); +} + +Sequence< OUString > OEMPreloadJob::GetSupportedServiceNames() +{ + sal_Int32 nSize = (sizeof( interfaces ) / sizeof( const char *)) - 1; + Sequence< OUString > aResult( nSize ); + + for( sal_Int32 i = 0; i < nSize; i++ ) + aResult[i] = OUString::createFromAscii( interfaces[i] ); + return aResult; +} + +Reference< XInterface > SAL_CALL OEMPreloadJob::CreateInstance( + const Reference< XMultiServiceFactory >& rSMgr ) +{ + static osl::Mutex aMutex; + osl::MutexGuard guard( aMutex ); + return (XComponent*) ( new OEMPreloadJob( rSMgr ) ); +} + +OEMPreloadJob::OEMPreloadJob( const Reference< XMultiServiceFactory >& xFactory ) : + m_aListeners( m_aMutex ), + m_xServiceManager( xFactory ) +{ +} + +OEMPreloadJob::~OEMPreloadJob() +{ +} + +// XComponent +void SAL_CALL OEMPreloadJob::dispose() throw ( RuntimeException ) +{ + EventObject aObject; + aObject.Source = (XComponent*)this; + m_aListeners.disposeAndClear( aObject ); +} + +void SAL_CALL OEMPreloadJob::addEventListener( const Reference< XEventListener > & aListener) throw ( RuntimeException ) +{ + m_aListeners.addInterface( aListener ); +} + +void SAL_CALL OEMPreloadJob::removeEventListener( const Reference< XEventListener > & aListener ) throw ( RuntimeException ) +{ + m_aListeners.removeInterface( aListener ); +} + +// XServiceInfo +::rtl::OUString SAL_CALL OEMPreloadJob::getImplementationName() +throw ( RuntimeException ) +{ + return OEMPreloadJob::GetImplementationName(); +} + +sal_Bool SAL_CALL OEMPreloadJob::supportsService( const ::rtl::OUString& rServiceName ) +throw ( RuntimeException ) +{ + sal_Int32 nSize = sizeof( interfaces ) / sizeof( const char *); + + for( sal_Int32 i = 0; i < nSize; i++ ) + if ( rServiceName.equalsAscii( interfaces[i] )) + return sal_True; + return sal_False; +} + +Sequence< ::rtl::OUString > SAL_CALL OEMPreloadJob::getSupportedServiceNames() +throw ( RuntimeException ) +{ + return OEMPreloadJob::GetSupportedServiceNames(); +} + +// XJob +Any SAL_CALL OEMPreloadJob::execute(const Sequence<NamedValue>&) +throw ( RuntimeException ) +{ + sal_Bool bCont = sal_False; + // are we an OEM version at all? + if (checkOEMPreloadFlag()) + { + // create OEM preload service dialog + Reference <XExecutableDialog> xDialog( m_xServiceManager->createInstance( + OUString::createFromAscii("org.openoffice.comp.preload.OEMPreloadWizard")), + UNO_QUERY ); + if ( xDialog.is() ){ + // execute OEM preload dialog and check return value + if ( xDialog->execute() == ExecutableDialogResults::OK ) { + // user accepted. + // make sure the job does not get called again. + bCont = sal_True; + disableOEMPreloadFlag(); + } else { + // user declined... + // terminate. + /* + Reference< XDesktop > xDesktop( m_xServiceManager->createInstance( + OUString::createFromAscii("com.sun.star.frame.Desktop")), + UNO_QUERY ); + xDesktop->terminate(); + */ + /* + OUString aName; + OUString aEnvType; + Reference<XFrame> rFrame; + Reference<XModel> rModel; + Reference<XCloseable> rClose; + for (int i=0; i<args.getLength(); i++) + { + if (args[i].Name.equalsAscii("EnvType")) + args[i].Value >>= aEnvType; + else if (args[i].Name.equalsAscii("Frame")) { + args[i].Value >>= rFrame; + rClose = Reference<XCloseable>(rFrame, UNO_QUERY); + } + else if (args[i].Name.equalsAscii("Model")) { + args[i].Value >>= rModel; + rClose = Reference<XCloseable>(rModel, UNO_QUERY); + } + } + if (rClose.is()) rClose->close(sal_True); + */ + bCont = sal_False; + } + } + } else { + // don't try again + bCont = sal_True; + } + /* + NamedValue nv; + nv.Name = OUString::createFromAscii("Deactivate"); + nv.Value <<= bDeactivate; + Sequence<NamedValue> s(1); + s[0] = nv; + */ + Any r; + r <<= bCont; + return r; +} + + +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 locateIniFile() +{ + OUString aUserDataPath; + OUString aSofficeIniFileURL; + + // Retrieve the default file URL for the soffice.ini/rc + 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; +} + +// check whether the OEMPreload flag was set in soffice.ini/.rc +sal_Bool OEMPreloadJob::checkOEMPreloadFlag() +{ + OUString aSofficeIniFileURL; + aSofficeIniFileURL = locateIniFile(); + Config aConfig(aSofficeIniFileURL); + aConfig.SetGroup( OEM_PRELOAD_SECTION ); + ByteString sResult = aConfig.ReadKey( OEM_PRELOAD ); + if ( sResult == STR_TRUE ) + return sal_True; + else + return sal_False; +} + +void OEMPreloadJob::disableOEMPreloadFlag() +{ + OUString aSofficeIniFileURL = locateIniFile(); + if ( aSofficeIniFileURL.getLength() > 0 ) + { + Config aConfig(aSofficeIniFileURL); + aConfig.SetGroup( OEM_PRELOAD_SECTION ); + aConfig.WriteKey( OEM_PRELOAD, STR_FALSE ); + aConfig.Flush(); + } +} + +} // namespace desktop + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/so_comp/oemjob.hxx b/desktop/source/so_comp/oemjob.hxx new file mode 100644 index 000000000000..26c1f0943de9 --- /dev/null +++ b/desktop/source/so_comp/oemjob.hxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 _SOCOMP_OEMJOB_HXX_ +#define _SOCOMP_OEMJOB_HXX_ + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/task/XJob.hpp> +#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/interfacecontainer.h> + +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <osl/mutex.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::task; + +namespace desktop{ + +class OEMPreloadJob : public ::cppu::WeakImplHelper3< XJob, XComponent, XServiceInfo > +{ + +private: + ::osl::Mutex m_aMutex; + ::cppu::OInterfaceContainerHelper m_aListeners; + Reference< XMultiServiceFactory > m_xServiceManager; + + sal_Bool checkOEMPreloadFlag(); + void disableOEMPreloadFlag(); + +public: + OEMPreloadJob( const Reference < XMultiServiceFactory >& xFactory ); + virtual ~OEMPreloadJob(); + + static ::rtl::OUString GetImplementationName(); + static Sequence< rtl::OUString > GetSupportedServiceNames(); + + + // XComponent + virtual void SAL_CALL dispose() throw ( RuntimeException ); + virtual void SAL_CALL addEventListener( const Reference< XEventListener > & aListener) throw ( RuntimeException ); + virtual void SAL_CALL removeEventListener(const Reference< XEventListener > & aListener) throw ( RuntimeException ); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() throw ( RuntimeException ); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& rServiceName ) throw ( RuntimeException ); + virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw ( RuntimeException ); + + //XJob + virtual Any SAL_CALL execute(const Sequence<NamedValue>& args)throw ( RuntimeException ); + + + static const char* interfaces[]; + static const char* implementationName; + static const char* serviceName; + static Reference<XInterface> SAL_CALL CreateInstance( + const Reference< XMultiServiceFactory >&); + + +}; +} + +#endif // _SOCOMP_OEMJOB_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/so_comp/services.cxx b/desktop/source/so_comp/services.cxx new file mode 100644 index 000000000000..c79f36820cb0 --- /dev/null +++ b/desktop/source/so_comp/services.cxx @@ -0,0 +1,163 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "evaluation.hxx" +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/util/Date.hpp> +#include <uno/environment.h> +#include <cppuhelper/factory.hxx> +#include <unotools/configmgr.hxx> + +#include "oemjob.hxx" +#include "evaluation.hxx" + +#include <string.h> + +using namespace rtl; +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 ::desktop; + +static const char* pServices[] = +{ + SOEvaluation::serviceName, + OEMPreloadJob::serviceName, + NULL +}; + +static const char* pImplementations[] = +{ + SOEvaluation::implementationName, + OEMPreloadJob::implementationName, + NULL +}; + +typedef Reference<XInterface>(* fProvider)(const Reference<XMultiServiceFactory>&); + +static const fProvider pInstanceProviders[] = +{ + SOEvaluation::CreateInstance, + OEMPreloadJob::CreateInstance, + NULL +}; + + +static const char** pSupportedServices[] = +{ + SOEvaluation::interfaces, + OEMPreloadJob::interfaces, + NULL +}; + +static Sequence<OUString> +getSupportedServiceNames(int p) { + const char **names = pSupportedServices[p]; + Sequence<OUString> aSeq; + for(int i = 0; names[i] != NULL; i++) { + aSeq.realloc(i+1); + aSeq[i] = OUString::createFromAscii(names[i]); + } + return aSeq; +} + +extern "C" +{ +void SAL_CALL +component_getImplementationEnvironment( + const sal_Char** ppEnvironmentTypeName, + uno_Environment**) +{ + *ppEnvironmentTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ; +} + +sal_Bool SAL_CALL +component_writeInfo( + void* pServiceManager, + void* pRegistryKey) +{ + Reference<XMultiServiceFactory> xMan( + reinterpret_cast< XMultiServiceFactory* >( pServiceManager ) ) ; + Reference<XRegistryKey> xKey( + reinterpret_cast< XRegistryKey* >( pRegistryKey ) ) ; + + // iterate over service names and register them... + OUString aImpl; + const char* pServiceName = NULL; + const char* pImplName = NULL; + for (int i = 0; (pServices[i]!=NULL)&&(pImplementations[i]!=NULL); i++) { + pServiceName= pServices[i]; + pImplName = pImplementations[i]; + aImpl = OUString::createFromAscii("/") + + OUString::createFromAscii(pImplName) + + OUString::createFromAscii("/UNO/SERVICES"); + Reference<XRegistryKey> xNewKey = xKey->createKey(aImpl); + xNewKey->createKey(OUString::createFromAscii(pServiceName)); + } + return sal_True; +} + +void* SAL_CALL +component_getFactory( + const sal_Char* pImplementationName, + void* pServiceManager, + void*) +{ + // Set default return value for this operation - if it failed. + if ( pImplementationName && pServiceManager ) + { + Reference< XSingleServiceFactory > xFactory; + Reference< XMultiServiceFactory > xServiceManager( + reinterpret_cast< XMultiServiceFactory* >( pServiceManager ) ) ; + + // search implementation + for (int i = 0; (pImplementations[i]!=NULL); i++) { + if ( strcmp(pImplementations[i], pImplementationName ) == 0 ) { + // found implementation + xFactory = Reference<XSingleServiceFactory>(cppu::createSingleFactory( + xServiceManager, OUString::createFromAscii(pImplementationName), + pInstanceProviders[i], getSupportedServiceNames(i))); + if ( xFactory.is() ) { + // Factory is valid - service was found. + xFactory->acquire(); + return xFactory.get(); + } + } + } // for() + } + // Return with result of this operation. + return NULL; +} +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/splash/makefile.mk b/desktop/source/splash/makefile.mk new file mode 100644 index 000000000000..01f1287bc7be --- /dev/null +++ b/desktop/source/splash/makefile.mk @@ -0,0 +1,73 @@ +#************************************************************************* +# +# 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=spl +LIBTARGET=NO + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +SLOFILES = $(SLO)$/splash.obj \ + $(SLO)$/services_spl.obj + +SHL1DEPN= makefile.mk +SHL1OBJS= $(SLOFILES) \ + $(SLO)$/migration.obj \ + $(SLO)$/cfgfilter.obj + + +SHL1TARGET=$(TARGET)$(DLLPOSTFIX) +SHL1IMPLIB=i$(TARGET) + +SHL1VERSIONMAP=$(SOLARENV)/src/component.map +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +DEF1NAME=$(SHL1TARGET) + +SHL1STDLIBS= \ + $(VCLLIB) \ + $(SVLLIB) \ + $(SVTOOLLIB) \ + $(COMPHELPERLIB) \ + $(UNOTOOLSLIB) \ + $(TOOLSLIB) \ + $(UCBHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(SFXLIB) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/desktop/source/splash/services_spl.cxx b/desktop/source/splash/services_spl.cxx new file mode 100644 index 000000000000..adcf9c1a5fd1 --- /dev/null +++ b/desktop/source/splash/services_spl.cxx @@ -0,0 +1,155 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/util/Date.hpp> +#include <uno/environment.h> +#include <cppuhelper/factory.hxx> +#include <unotools/configmgr.hxx> + +#include "splash.hxx" + + +using namespace rtl; +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 ::desktop; + +static const char* pServices[] = +{ + SplashScreen::serviceName, + NULL +}; + +static const char* pImplementations[] = +{ + SplashScreen::implementationName, + NULL +}; + +typedef Reference<XInterface>(* fProvider)(const Reference<XMultiServiceFactory>&); + +static const fProvider pInstanceProviders[] = +{ + SplashScreen::getInstance, + NULL +}; + + +static const char** pSupportedServices[] = +{ + SplashScreen::interfaces, + NULL +}; + +static Sequence<OUString> +getSupportedServiceNames(int p) { + const char **names = pSupportedServices[p]; + Sequence<OUString> aSeq; + for(int i = 0; names[i] != NULL; i++) { + aSeq.realloc(i+1); + aSeq[i] = OUString::createFromAscii(names[i]); + } + return aSeq; +} + +extern "C" +{ +void SAL_CALL +component_getImplementationEnvironment( + const sal_Char** ppEnvironmentTypeName, + uno_Environment**) +{ + *ppEnvironmentTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ; +} + +sal_Bool SAL_CALL +component_writeInfo( + void* pServiceManager, + void* pRegistryKey) +{ + Reference<XMultiServiceFactory> xMan( + reinterpret_cast< XMultiServiceFactory* >( pServiceManager ) ) ; + Reference<XRegistryKey> xKey( + reinterpret_cast< XRegistryKey* >( pRegistryKey ) ) ; + + // iterate over service names and register them... + OUString aImpl; + const char* pServiceName = NULL; + const char* pImplName = NULL; + for (int i = 0; (pServices[i]!=NULL)&&(pImplementations[i]!=NULL); i++) { + pServiceName= pServices[i]; + pImplName = pImplementations[i]; + aImpl = OUString::createFromAscii("/") + + OUString::createFromAscii(pImplName) + + OUString::createFromAscii("/UNO/SERVICES"); + Reference<XRegistryKey> xNewKey = xKey->createKey(aImpl); + xNewKey->createKey(OUString::createFromAscii(pServiceName)); + } + return sal_True; +} + +void* SAL_CALL +component_getFactory( + const sal_Char* pImplementationName, + void* pServiceManager, + void*) +{ + // Set default return value for this operation - if it failed. + if ( pImplementationName && pServiceManager ) + { + Reference< XSingleServiceFactory > xFactory; + Reference< XMultiServiceFactory > xServiceManager( + reinterpret_cast< XMultiServiceFactory* >( pServiceManager ) ) ; + + // search implementation + for (int i = 0; (pImplementations[i]!=NULL); i++) { + if ( strcmp(pImplementations[i], pImplementationName ) == 0 ) { + // found implementation + xFactory = Reference<XSingleServiceFactory>(cppu::createSingleFactory( + xServiceManager, OUString::createFromAscii(pImplementationName), + pInstanceProviders[i], getSupportedServiceNames(i))); + if ( xFactory.is() ) { + // Factory is valid - service was found. + xFactory->acquire(); + return xFactory.get(); + } + } + } // for() + } + // Return with result of this operation. + return NULL; +} +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/splash/splash.cxx b/desktop/source/splash/splash.cxx new file mode 100644 index 000000000000..57e96829e1ed --- /dev/null +++ b/desktop/source/splash/splash.cxx @@ -0,0 +1,593 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "splash.hxx" +#include <stdio.h> +#include <unotools/bootstrap.hxx> +#include <tools/urlobj.hxx> +#include <tools/stream.hxx> +#include <sfx2/sfx.hrc> +#include <vcl/svapp.hxx> +#include <vcl/salnativewidgets.hxx> + +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <rtl/bootstrap.hxx> +#include <rtl/logfile.hxx> +#include <rtl/locale.hxx> +#include <rtl/strbuf.hxx> +#include <rtl/math.hxx> +#include <vcl/graph.hxx> +#include <svtools/filter.hxx> + +#define NOT_LOADED ((long)-1) + +using namespace ::rtl; +using namespace ::com::sun::star::registry; + +namespace desktop +{ + +SplashScreen::SplashScreen(const Reference< XMultiServiceFactory >& rSMgr) + : IntroWindow() + , _vdev(*((IntroWindow*)this)) + , _cProgressFrameColor(sal::static_int_cast< ColorData >(NOT_LOADED)) + , _cProgressBarColor(sal::static_int_cast< ColorData >(NOT_LOADED)) + , _bNativeProgress(true) + , _iMax(100) + , _iProgress(0) + , _eBitmapMode(BM_DEFAULTMODE) + , _bPaintBitmap(sal_True) + , _bPaintProgress(sal_False) + , _bShowLogo(sal_True) + , _bFullScreenSplash(sal_False) + , _bProgressEnd(sal_False) + , _tlx(NOT_LOADED) + , _tly(NOT_LOADED) + , _barwidth(NOT_LOADED) + , _barheight(NOT_LOADED) + , _barspace(2) + , _fXPos(-1.0) + , _fYPos(-1.0) + , _fWidth(-1.0) + , _fHeight(-1.0) + , _xoffset(12) + , _yoffset(18) +{ + _rFactory = rSMgr; + + loadConfig(); +} + +SplashScreen::~SplashScreen() +{ + Application::RemoveEventListener( + LINK( this, SplashScreen, AppEventListenerHdl ) ); + Hide(); + +} + +void SAL_CALL SplashScreen::start(const OUString&, sal_Int32 nRange) + throw (RuntimeException) +{ + _iMax = nRange; + if (_bVisible) { + _bProgressEnd = sal_False; + SolarMutexGuard aSolarGuard; + if ( _eBitmapMode == BM_FULLSCREEN ) + ShowFullScreenMode( TRUE ); + Show(); + Paint(Rectangle()); + Flush(); + } +} + +void SAL_CALL SplashScreen::end() + throw (RuntimeException) +{ + _iProgress = _iMax; + if (_bVisible ) + { + if ( _eBitmapMode == BM_FULLSCREEN ) + EndFullScreenMode(); + Hide(); + } + _bProgressEnd = sal_True; +} + +void SAL_CALL SplashScreen::reset() + throw (RuntimeException) +{ + _iProgress = 0; + if (_bVisible && !_bProgressEnd ) + { + if ( _eBitmapMode == BM_FULLSCREEN ) + ShowFullScreenMode( TRUE ); + Show(); + updateStatus(); + } +} + +void SAL_CALL SplashScreen::setText(const OUString& rText) + throw (RuntimeException) +{ + SolarMutexGuard aSolarGuard; + if ( _sProgressText != rText ) + { + _sProgressText = rText; + + if (_bVisible && !_bProgressEnd) + { + if ( _eBitmapMode == BM_FULLSCREEN ) + ShowFullScreenMode( TRUE ); + Show(); + updateStatus(); + } + } +} + +void SAL_CALL SplashScreen::setValue(sal_Int32 nValue) + throw (RuntimeException) +{ + RTL_LOGFILE_CONTEXT( aLog, "::SplashScreen::setValue (lo119109)" ); + RTL_LOGFILE_CONTEXT_TRACE1( aLog, "value=%d", nValue ); + + SolarMutexGuard aSolarGuard; + if (_bVisible && !_bProgressEnd) { + if ( _eBitmapMode == BM_FULLSCREEN ) + ShowFullScreenMode( TRUE ); + Show(); + if (nValue >= _iMax) _iProgress = _iMax; + else _iProgress = nValue; + updateStatus(); + } +} + +// XInitialize +void SAL_CALL +SplashScreen::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments ) + throw (RuntimeException) +{ + ::osl::ClearableMutexGuard aGuard( _aMutex ); + if (aArguments.getLength() > 0) + { + aArguments[0] >>= _bVisible; + if (aArguments.getLength() > 1 ) + aArguments[1] >>= _sAppName; + + // start to determine bitmap and all other required value + if ( _bShowLogo ) + SetScreenBitmap (_aIntroBmp); + Size aSize = _aIntroBmp.GetSizePixel(); + SetOutputSizePixel( aSize ); + _vdev.SetOutputSizePixel( aSize ); + _height = aSize.Height(); + _width = aSize.Width(); + if (_width > 500) + { + Point xtopleft(212,216); + if ( NOT_LOADED == _tlx || NOT_LOADED == _tly ) + { + _tlx = xtopleft.X(); // top-left x + _tly = xtopleft.Y(); // top-left y + } + if ( NOT_LOADED == _barwidth ) + _barwidth = 263; + if ( NOT_LOADED == _barheight ) + _barheight = 8; + if (( _eBitmapMode == BM_FULLSCREEN ) && + _bFullScreenSplash ) + { + if( ( _fXPos >= 0.0 ) && ( _fYPos >= 0.0 )) + { + _tlx = sal_Int32( double( aSize.Width() ) * _fXPos ); + _tly = sal_Int32( double( aSize.Height() ) * _fYPos ); + } + if ( _fWidth >= 0.0 ) + _barwidth = sal_Int32( double( aSize.Width() ) * _fWidth ); + if ( _fHeight >= 0.0 ) + _barheight = sal_Int32( double( aSize.Width() ) * _fHeight ); + } + } + else + { + if ( NOT_LOADED == _barwidth ) + _barwidth = _width - (2 * _xoffset); + if ( NOT_LOADED == _barheight ) + _barheight = 6; + if ( NOT_LOADED == _tlx || NOT_LOADED == _tly ) + { + _tlx = _xoffset; // top-left x + _tly = _height - _yoffset; // top-left y + } + } + + if ( sal::static_int_cast< ColorData >(NOT_LOADED) == + _cProgressFrameColor.GetColor() ) + _cProgressFrameColor = Color( COL_LIGHTGRAY ); + + if ( sal::static_int_cast< ColorData >(NOT_LOADED) == + _cProgressBarColor.GetColor() ) + { + // progress bar: new color only for big bitmap format + if ( _width > 500 ) + _cProgressBarColor = Color( 157, 202, 18 ); + else + _cProgressBarColor = Color( COL_BLUE ); + } + + Application::AddEventListener( + LINK( this, SplashScreen, AppEventListenerHdl ) ); + + SetBackgroundBitmap( _aIntroBmp ); + } +} + +void SplashScreen::updateStatus() +{ + if (!_bVisible || _bProgressEnd) return; + if (!_bPaintProgress) _bPaintProgress = sal_True; + //_bPaintBitmap=sal_False; + Paint(Rectangle()); + //_bPaintBitmap=sal_True; + Flush(); +} + +// internal private methods +IMPL_LINK( SplashScreen, AppEventListenerHdl, VclWindowEvent *, inEvent ) +{ + if ( inEvent != 0 ) + { + // Paint( Rectangle() ); + switch ( inEvent->GetId() ) + { + case VCLEVENT_WINDOW_SHOW: + Paint( Rectangle() ); + break; + default: + break; + } + } + return 0; +} + +// Read keys from edition/edition.ini or soffice{.ini|rc}: +OUString implReadBootstrapKey( const OUString& _rKey ) +{ + OUString sValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "${.override:${BRAND_BASE_DIR}/program/edition/edition.ini:")) + + _rKey + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("}"))); + rtl::Bootstrap::expandMacros(sValue); + return sValue; +} + +void SplashScreen::loadConfig() +{ + _bShowLogo = !implReadBootstrapKey( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Logo"))). + equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("0")); + + OUString sProgressFrameColor = implReadBootstrapKey( + OUString( RTL_CONSTASCII_USTRINGPARAM( "ProgressFrameColor" ) ) ); + OUString sProgressBarColor = implReadBootstrapKey( + OUString( RTL_CONSTASCII_USTRINGPARAM( "ProgressBarColor" ) ) ); + OUString sSize = implReadBootstrapKey( + OUString( RTL_CONSTASCII_USTRINGPARAM( "ProgressSize" ) ) ); + OUString sPosition = implReadBootstrapKey( + OUString( RTL_CONSTASCII_USTRINGPARAM( "ProgressPosition" ) ) ); + OUString sFullScreenSplash = implReadBootstrapKey( + OUString( RTL_CONSTASCII_USTRINGPARAM( "FullScreenSplash" ) ) ); + OUString sNativeProgress = implReadBootstrapKey( + OUString( RTL_CONSTASCII_USTRINGPARAM( "NativeProgress" ) ) ); + + + // Determine full screen splash mode + _bFullScreenSplash = (( sFullScreenSplash.getLength() > 0 ) && + ( !sFullScreenSplash.equalsAsciiL( "0", 1 ))); + + // Try to retrieve the relative values for the progress bar. The current + // schema uses the screen ratio to retrieve the associated values. + if ( _bFullScreenSplash ) + determineProgressRatioValues( _fXPos, _fYPos, _fWidth, _fHeight ); + + if ( sProgressFrameColor.getLength() ) + { + UINT8 nRed = 0; + UINT8 nGreen = 0; + UINT8 nBlue = 0; + sal_Int32 idx = 0; + sal_Int32 temp = sProgressFrameColor.getToken( 0, ',', idx ).toInt32(); + if ( idx != -1 ) + { + nRed = static_cast< UINT8 >( temp ); + temp = sProgressFrameColor.getToken( 0, ',', idx ).toInt32(); + } + if ( idx != -1 ) + { + nGreen = static_cast< UINT8 >( temp ); + nBlue = static_cast< UINT8 >( sProgressFrameColor.getToken( 0, ',', idx ).toInt32() ); + _cProgressFrameColor = Color( nRed, nGreen, nBlue ); + } + } + + if ( sProgressBarColor.getLength() ) + { + UINT8 nRed = 0; + UINT8 nGreen = 0; + UINT8 nBlue = 0; + sal_Int32 idx = 0; + sal_Int32 temp = sProgressBarColor.getToken( 0, ',', idx ).toInt32(); + if ( idx != -1 ) + { + nRed = static_cast< UINT8 >( temp ); + temp = sProgressBarColor.getToken( 0, ',', idx ).toInt32(); + } + if ( idx != -1 ) + { + nGreen = static_cast< UINT8 >( temp ); + nBlue = static_cast< UINT8 >( sProgressBarColor.getToken( 0, ',', idx ).toInt32() ); + _cProgressBarColor = Color( nRed, nGreen, nBlue ); + } + } + + if( sNativeProgress.getLength() ) + { + _bNativeProgress = sNativeProgress.toBoolean(); + } + + if ( sSize.getLength() ) + { + sal_Int32 idx = 0; + sal_Int32 temp = sSize.getToken( 0, ',', idx ).toInt32(); + if ( idx != -1 ) + { + _barwidth = temp; + _barheight = sSize.getToken( 0, ',', idx ).toInt32(); + } + } + + if ( _barheight >= 10 ) + _barspace = 3; // more space between frame and bar + + if ( sPosition.getLength() ) + { + sal_Int32 idx = 0; + sal_Int32 temp = sPosition.getToken( 0, ',', idx ).toInt32(); + if ( idx != -1 ) + { + _tlx = temp; + _tly = sPosition.getToken( 0, ',', idx ).toInt32(); + } + } +} + +void SplashScreen::SetScreenBitmap(BitmapEx &rBitmap) +{ + sal_Int32 nWidth( 0 ); + sal_Int32 nHeight( 0 ); + + // determine desktop resolution + sal_uInt32 nCount = Application::GetScreenCount(); + if ( nCount > 0 ) + { + // retrieve size from first screen + Rectangle aScreenArea = Application::GetScreenPosSizePixel((unsigned int)0); + nWidth = aScreenArea.GetWidth(); + nHeight = aScreenArea.GetHeight(); + } + + // create file name from screen resolution information + OStringBuffer aStrBuf( 128 ); + OStringBuffer aResBuf( 32 ); + aStrBuf.append( "intro_" ); + if ( _sAppName.getLength() > 0 ) + { + aStrBuf.append( OString( _sAppName, _sAppName.getLength(), + RTL_TEXTENCODING_UTF8 ) ); + aStrBuf.append( "_" ); + } + aResBuf.append( OString::valueOf( nWidth )); + aResBuf.append( "x" ); + aResBuf.append( OString::valueOf( nHeight )); + + aStrBuf.append( aResBuf.getStr() ); + if (Application::LoadBrandBitmap (aStrBuf.makeStringAndClear(), rBitmap)) + return; + + aStrBuf.append( "intro_" ); + aStrBuf.append( aResBuf.getStr() ); + if (Application::LoadBrandBitmap (aResBuf.makeStringAndClear(), rBitmap)) + return; + + Application::LoadBrandBitmap ("intro", rBitmap); +} + +void SplashScreen::determineProgressRatioValues( + double& rXRelPos, double& rYRelPos, + double& rRelWidth, double& rRelHeight ) +{ + sal_Int32 nWidth( 0 ); + sal_Int32 nHeight( 0 ); + sal_Int32 nScreenRatio( 0 ); + + // determine desktop resolution + sal_uInt32 nCount = Application::GetScreenCount(); + if ( nCount > 0 ) + { + // retrieve size from first screen + Rectangle aScreenArea = Application::GetScreenPosSizePixel((unsigned int)0); + nWidth = aScreenArea.GetWidth(); + nHeight = aScreenArea.GetHeight(); + nScreenRatio = sal_Int32( math::round( double( nWidth ) / double( nHeight ), 2 ) * 100 ); + } + + char szFullScreenProgressRatio[] = "FullScreenProgressRatio0"; + char szFullScreenProgressPos[] = "FullScreenProgressPos0"; + char szFullScreenProgressSize[] = "FullScreenProgressSize0"; + for ( sal_Int32 i = 0; i <= 9; i++ ) + { + char cNum = '0' + char( i ); + szFullScreenProgressRatio[23] = cNum; + szFullScreenProgressPos[21] = cNum; + szFullScreenProgressSize[22] = cNum; + + OUString sFullScreenProgressRatio = implReadBootstrapKey( + OUString::createFromAscii( szFullScreenProgressRatio ) ); + + if ( sFullScreenProgressRatio.getLength() > 0 ) + { + double fRatio = sFullScreenProgressRatio.toDouble(); + sal_Int32 nRatio = sal_Int32( math::round( fRatio, 2 ) * 100 ); + if ( nRatio == nScreenRatio ) + { + OUString sFullScreenProgressPos = implReadBootstrapKey( + OUString::createFromAscii( szFullScreenProgressPos ) ); + OUString sFullScreenProgressSize = implReadBootstrapKey( + OUString::createFromAscii( szFullScreenProgressSize ) ); + + if ( sFullScreenProgressPos.getLength() ) + { + sal_Int32 idx = 0; + double temp = sFullScreenProgressPos.getToken( 0, ',', idx ).toDouble(); + if ( idx != -1 ) + { + rXRelPos = temp; + rYRelPos = sFullScreenProgressPos.getToken( 0, ',', idx ).toDouble(); + } + } + + if ( sFullScreenProgressSize.getLength() ) + { + sal_Int32 idx = 0; + double temp = sFullScreenProgressSize.getToken( 0, ',', idx ).toDouble(); + if ( idx != -1 ) + { + rRelWidth = temp; + rRelHeight = sFullScreenProgressSize.getToken( 0, ',', idx ).toDouble(); + } + } + } + } + else + break; + } +} + +void SplashScreen::Paint( const Rectangle&) +{ + if(!_bVisible) return; + + //native drawing + BOOL bNativeOK = FALSE; + + // in case of native controls we need to draw directly to the window + if( _bNativeProgress && IsNativeControlSupported( CTRL_INTROPROGRESS, PART_ENTIRE_CONTROL ) ) + { + DrawBitmapEx( Point(), _aIntroBmp ); + + ImplControlValue aValue( _iProgress * _barwidth / _iMax); + Rectangle aDrawRect( Point(_tlx, _tly), Size( _barwidth, _barheight ) ); + Rectangle aNativeControlRegion, aNativeContentRegion; + + if( GetNativeControlRegion( CTRL_INTROPROGRESS, PART_ENTIRE_CONTROL, aDrawRect, + CTRL_STATE_ENABLED, aValue, rtl::OUString(), + aNativeControlRegion, aNativeContentRegion ) ) + { + long nProgressHeight = aNativeControlRegion.GetHeight(); + aDrawRect.Top() -= (nProgressHeight - _barheight)/2; + aDrawRect.Bottom() += (nProgressHeight - _barheight)/2; + } + + if( (bNativeOK = DrawNativeControl( CTRL_INTROPROGRESS, PART_ENTIRE_CONTROL, aDrawRect, + CTRL_STATE_ENABLED, aValue, _sProgressText )) != FALSE ) + { + return; + } + } + //non native drawing + // draw bitmap + if (_bPaintBitmap) + _vdev.DrawBitmapEx( Point(), _aIntroBmp ); + + if (_bPaintProgress) { + // draw progress... + long length = (_iProgress * _barwidth / _iMax) - (2 * _barspace); + if (length < 0) length = 0; + + // border + _vdev.SetFillColor(); + _vdev.SetLineColor( _cProgressFrameColor ); + _vdev.DrawRect(Rectangle(_tlx, _tly, _tlx+_barwidth, _tly+_barheight)); + _vdev.SetFillColor( _cProgressBarColor ); + _vdev.SetLineColor(); + _vdev.DrawRect(Rectangle(_tlx+_barspace, _tly+_barspace, _tlx+_barspace+length, _tly+_barheight-_barspace)); + _vdev.DrawText( Rectangle(_tlx, _tly+_barheight+5, _tlx+_barwidth, _tly+_barheight+5+20), _sProgressText, TEXT_DRAW_CENTER ); + } + Size aSize = GetOutputSizePixel(); + Size bSize = _vdev.GetOutputSizePixel(); + //_vdev.Flush(); + //_vdev.DrawOutDev(Point(), GetOutputSize(), Point(), GetOutputSize(), *((IntroWindow*)this) ); + DrawOutDev(Point(), GetOutputSizePixel(), Point(), _vdev.GetOutputSizePixel(), _vdev ); + //Flush(); +} + + +// get service instance... +SplashScreen *SplashScreen::_pINSTANCE = NULL; +osl::Mutex SplashScreen::_aMutex; + +Reference< XInterface > SplashScreen::getInstance(const Reference< XMultiServiceFactory >& rSMgr) +{ + if ( _pINSTANCE == 0 ) + { + osl::MutexGuard guard(_aMutex); + if (_pINSTANCE == 0) + return (XComponent*)new SplashScreen(rSMgr); + } + + return (XComponent*)0; +} + +// static service info... +const char* SplashScreen::interfaces[] = +{ + "com.sun.star.task.XStartusIndicator", + "com.sun.star.lang.XInitialization", + NULL, +}; +const sal_Char *SplashScreen::serviceName = "com.sun.star.office.SplashScreen"; +const sal_Char *SplashScreen::implementationName = "com.sun.star.office.comp.SplashScreen"; +const sal_Char *SplashScreen::supportedServiceNames[] = {"com.sun.star.office.SplashScreen", NULL}; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/splash/splash.hxx b/desktop/source/splash/splash.hxx new file mode 100644 index 000000000000..c7c3ff5b52ae --- /dev/null +++ b/desktop/source/splash/splash.hxx @@ -0,0 +1,134 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/task/XStatusIndicator.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <cppuhelper/implbase2.hxx> +#include <cppuhelper/interfacecontainer.h> +#include <vcl/introwin.hxx> +#include <vcl/bitmapex.hxx> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <osl/mutex.hxx> +#include <vcl/virdev.hxx> + + +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::task; + +namespace desktop { + +class SplashScreen + : public ::cppu::WeakImplHelper2< XStatusIndicator, XInitialization > + , public IntroWindow +{ +private: + struct FullScreenProgressRatioValue + { + double _fXRelPos; + double _fYRelPos; + double _fRelWidth; + double _fRelHeight; + }; + enum BitmapMode { BM_FULLSCREEN, BM_DEFAULTMODE }; + + // don't allow anybody but ourselves to create instances of this class + SplashScreen(const SplashScreen&); + SplashScreen(void); + SplashScreen operator =(const SplashScreen&); + + SplashScreen(const Reference< XMultiServiceFactory >& xFactory); + + DECL_LINK( AppEventListenerHdl, VclWindowEvent * ); + virtual ~SplashScreen(); + void loadConfig(); + void updateStatus(); + void SetScreenBitmap(BitmapEx &rBitmap); + void determineProgressRatioValues( double& rXRelPos, double& rYRelPos, double& rRelWidth, double& rRelHeight ); + + static SplashScreen *_pINSTANCE; + + static osl::Mutex _aMutex; + Reference< XMultiServiceFactory > _rFactory; + + VirtualDevice _vdev; + BitmapEx _aIntroBmp; + Color _cProgressFrameColor; + Color _cProgressBarColor; + bool _bNativeProgress; + OUString _sAppName; + OUString _sProgressText; + std::vector< FullScreenProgressRatioValue > _sFullScreenProgressRatioValues; + + sal_Int32 _iMax; + sal_Int32 _iProgress; + BitmapMode _eBitmapMode; + sal_Bool _bPaintBitmap; + sal_Bool _bPaintProgress; + sal_Bool _bVisible; + sal_Bool _bShowLogo; + sal_Bool _bFullScreenSplash; + sal_Bool _bProgressEnd; + long _height, _width, _tlx, _tly, _barwidth; + long _barheight, _barspace; + double _fXPos, _fYPos; + double _fWidth, _fHeight; + const long _xoffset, _yoffset; + +public: + static const char* interfaces[]; + static const sal_Char *serviceName; + static const sal_Char *implementationName; + static const sal_Char *supportedServiceNames[]; + + static Reference< XInterface > getInstance(const Reference < XMultiServiceFactory >& xFactory); + + // XStatusIndicator + virtual void SAL_CALL end() throw ( RuntimeException ); + virtual void SAL_CALL reset() throw ( RuntimeException ); + virtual void SAL_CALL setText(const OUString& aText) throw ( RuntimeException ); + virtual void SAL_CALL setValue(sal_Int32 nValue) throw ( RuntimeException ); + virtual void SAL_CALL start(const OUString& aText, sal_Int32 nRange) throw ( RuntimeException ); + + // XInitialize + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments ) + throw ( RuntimeException ); + + // workwindow + virtual void Paint( const Rectangle& ); + +}; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/test/deployment/boxt/Addons.xcu b/desktop/test/deployment/boxt/Addons.xcu new file mode 100644 index 000000000000..3df7e2de274c --- /dev/null +++ b/desktop/test/deployment/boxt/Addons.xcu @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<o:component-data xmlns:o="http://openoffice.org/2001/registry" + o:package="org.openoffice.Office" o:name="Addons"> + <node o:name="AddonUI"> + <node o:name="OfficeMenuBar"> + <node o:name="org.openoffice.test.desktop.deployment.boxt" o:op="replace"> + <prop o:name="Title" xml:lang="en-US"> + <value>boxt</value> + </prop> + <node o:name="Submenu"> + <node o:name="1" o:op="replace"> + <prop o:name="URL"> + <value>vnd.org.openoffice.test.desktop.deployment.boxt:</value> + </prop> + <prop o:name="Title" xml:lang="en-US"> + <value>boxt</value> + </prop> + </node> + </node> + </node> + </node> + </node> +</o:component-data> diff --git a/desktop/test/deployment/boxt/ProtocolHandler.xcu b/desktop/test/deployment/boxt/ProtocolHandler.xcu new file mode 100644 index 000000000000..fe448aedbe17 --- /dev/null +++ b/desktop/test/deployment/boxt/ProtocolHandler.xcu @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<o:component-data xmlns:o="http://openoffice.org/2001/registry" + o:package="org.openoffice.Office" o:name="ProtocolHandler"> + <node o:name="HandlerSet"> + <node o:name="com.sun.star.test.deployment.boxt" o:op="replace"> + <prop o:name="Protocols"> + <value>vnd.org.openoffice.test.desktop.deployment.boxt:*</value> + </prop> + </node> + </node> +</o:component-data> diff --git a/desktop/test/deployment/boxt/boxt.cxx b/desktop/test/deployment/boxt/boxt.cxx new file mode 100644 index 000000000000..a2fb2c43cbed --- /dev/null +++ b/desktop/test/deployment/boxt/boxt.cxx @@ -0,0 +1,238 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* +* +* 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 "precompiled_desktop.hxx" +#include "sal/config.h" + +#include "boost/noncopyable.hpp" +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/frame/DispatchDescriptor.hpp" +#include "com/sun/star/frame/XDispatch.hpp" +#include "com/sun/star/frame/XDispatchProvider.hpp" +#include "com/sun/star/frame/XStatusListener.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XSingleComponentFactory.hpp" +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/util/URL.hpp" +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/implbase3.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "cppuhelper/weak.hxx" +#include "filter/msfilter/countryid.hxx" +#include "osl/diagnose.h" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "uno/lbnames.h" +#include "vcl/svapp.hxx" + +namespace { + +namespace css = com::sun::star; + +namespace service { + +rtl::OUString getImplementationName() { + return rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.test.deployment.boxt")); +} + +css::uno::Sequence< rtl::OUString > getSupportedServiceNames() { + rtl::OUString name( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.test.deployment.boxt")); + return css::uno::Sequence< rtl::OUString >(&name, 1); +} + +} + +class Service: + public cppu::WeakImplHelper3< + css::lang::XServiceInfo, css::frame::XDispatchProvider, + css::frame::XDispatch >, + private boost::noncopyable +{ +public: + Service() {} + +private: + virtual ~Service() {} + + virtual rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException) + { return service::getImplementationName(); } + + virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & ServiceName) + throw (css::uno::RuntimeException) + { return ServiceName == getSupportedServiceNames()[0]; } //TODO + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException) + { return service::getSupportedServiceNames(); } + + virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch( + css::util::URL const &, rtl::OUString const &, sal_Int32) + throw (css::uno::RuntimeException) + { return this; } + + virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > + SAL_CALL queryDispatches( + css::uno::Sequence< css::frame::DispatchDescriptor > const & Requests) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL dispatch( + css::util::URL const &, + css::uno::Sequence< css::beans::PropertyValue > const &) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL addStatusListener( + css::uno::Reference< css::frame::XStatusListener > const &, + css::util::URL const &) + throw (css::uno::RuntimeException) + {} + + virtual void SAL_CALL removeStatusListener( + css::uno::Reference< css::frame::XStatusListener > const &, + css::util::URL const &) + throw (css::uno::RuntimeException) + {} +}; + +css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > +Service::queryDispatches( + css::uno::Sequence< css::frame::DispatchDescriptor > const & Requests) + throw (css::uno::RuntimeException) +{ + css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > s( + Requests.getLength()); + for (sal_Int32 i = 0; i < s.getLength(); ++i) { + s[i] = queryDispatch( + Requests[i].FeatureURL, Requests[i].FrameName, + Requests[i].SearchFlags); + } + return s; +} + +void Service::dispatch( + css::util::URL const &, + css::uno::Sequence< css::beans::PropertyValue > const &) + throw (css::uno::RuntimeException) +{ + msfilter::ConvertCountryToLanguage(msfilter::COUNTRY_DONTKNOW); + // link against some obscure library that is unlikely already loaded + Application::ShowNativeErrorBox( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("boxt")), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("test"))); +} + +class Factory: + public cppu::WeakImplHelper1< css::lang::XSingleComponentFactory >, + private boost::noncopyable +{ +public: + Factory() {} + +private: + virtual ~Factory() {} + + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL + createInstanceWithContext( + css::uno::Reference< css::uno::XComponentContext > const &) + throw (css::uno::Exception, css::uno::RuntimeException) + { return static_cast< cppu::OWeakObject * >(new Service); } + + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL + createInstanceWithArgumentsAndContext( + css::uno::Sequence< css::uno::Any > const &, + css::uno::Reference< css::uno::XComponentContext > const & Context) + throw (css::uno::Exception, css::uno::RuntimeException) + { return createInstanceWithContext(Context); } +}; + +css::uno::Reference< css::uno::XInterface > SAL_CALL dummy( + css::uno::Reference< css::uno::XComponentContext > const &) + SAL_THROW((css::uno::Exception)) +{ + OSL_ASSERT(false); + return css::uno::Reference< css::uno::XInterface >(); +} + +rtl::OUString SAL_CALL getImplementationName() { + return rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.test.deployment.boxt")); +} + +css::uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() { + rtl::OUString name( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.test.deployment.boxt")); + return css::uno::Sequence< rtl::OUString >(&name, 1); +} + +css::uno::Reference< css::lang::XSingleComponentFactory > SAL_CALL +createFactory( + cppu::ComponentFactoryFunc, rtl::OUString const &, + css::uno::Sequence< rtl::OUString > const &, rtl_ModuleCount *) + SAL_THROW(()) +{ + return new Factory; +} + +static cppu::ImplementationEntry const services[] = { + { &dummy, &service::getImplementationName, + &service::getSupportedServiceNames, &createFactory, 0, 0 }, + { 0, 0, 0, 0, 0, 0 } +}; + +} + +extern "C" void * SAL_CALL component_getFactory( + char const * pImplName, void * pServiceManager, void * pRegistryKey) +{ + return cppu::component_getFactoryHelper( + pImplName, pServiceManager, pRegistryKey, services); +} + +extern "C" void SAL_CALL component_getImplementationEnvironment( + char const ** ppEnvTypeName, uno_Environment **) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +extern "C" sal_Bool SAL_CALL component_writeInfo( + void * pServiceManager, void * pRegistryKey) +{ + return component_writeInfoHelper(pServiceManager, pRegistryKey, services); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/test/deployment/boxt/description.xml b/desktop/test/deployment/boxt/description.xml new file mode 100644 index 000000000000..5a67bf3e949f --- /dev/null +++ b/desktop/test/deployment/boxt/description.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<d:description xmlns:d="http://openoffice.org/extensions/description/2006"> + <d:identifier value="org.openoffice/framework/desktop/test/deployment/boxt"/> + <d:version value="@VERSION@"/> + <d:platform value="@PLATFORM@"/> + <d:dependencies> + <d:OpenOffice.org-minimal-version d:name="OpenOffice.org @VERSION@" + value="@VERSION@"/> + <d:OpenOffice.org-maximal-version d:name="OpenOffice.org @VERSION@ or older" + d:OpenOffice.org-minimal-version="2.3" value="@VERSION@"/> + </d:dependencies> +</d:description> diff --git a/desktop/test/deployment/boxt/makefile.mk b/desktop/test/deployment/boxt/makefile.mk new file mode 100644 index 000000000000..11d736448d44 --- /dev/null +++ b/desktop/test/deployment/boxt/makefile.mk @@ -0,0 +1,68 @@ +#************************************************************************* +# +# 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 = test_deployment_boxt + +ENABLE_EXCEPTIONS = TRUE + +.INCLUDE: settings.mk +.INCLUDE: rtlbootstrap.mk +.INCLUDE: versionlist.mk + +my_version = $(OOOBASEVERSIONMAJOR).$(OOOBASEVERSIONMINOR) + +DLLPRE = + +SLOFILES = $(SHL1OBJS) + +SHL1TARGET = boxt.uno +SHL1OBJS = $(SLO)/boxt.obj +SHL1RPATH = BOXT +SHL1STDLIBS = \ + $(CPPUHELPERLIB) $(CPPULIB) $(MSFILTERLIB) $(SALLIB) $(TOOLSLIB) $(VCLLIB) +SHL1VERSIONMAP = $(SOLARENV)/src/component.map +DEF1NAME = $(SHL1TARGET) + +.INCLUDE: target.mk + +ALLTAR : $(MISC)/boxt.oxt + +$(MISC)/boxt.oxt .ERRREMOVE : manifest.xml description.xml Addons.xcu \ + ProtocolHandler.xcu $(SHL1TARGETN) + $(RM) -r $@ $(MISC)/$(TARGET).zip + $(MKDIR) $(MISC)/$(TARGET).zip + $(MKDIR) $(MISC)/$(TARGET).zip/META-INF + $(SED) -e 's|@PATH@|$(SHL1TARGETN:f)|g' < manifest.xml \ + > $(MISC)/$(TARGET).zip/META-INF/manifest.xml + $(SED) -e 's|@PLATFORM@|$(RTL_OS:l)_$(RTL_ARCH:l)|g' \ + -e 's|@VERSION@|$(my_version)|g' < description.xml \ + > $(MISC)/$(TARGET).zip/description.xml + $(COPY) Addons.xcu ProtocolHandler.xcu $(SHL1TARGETN) $(MISC)/$(TARGET).zip + cd $(MISC)/$(TARGET).zip && zip ../boxt.oxt META-INF/manifest.xml \ + description.xml Addons.xcu ProtocolHandler.xcu $(SHL1TARGETN:f) diff --git a/desktop/test/deployment/boxt/manifest.xml b/desktop/test/deployment/boxt/manifest.xml new file mode 100644 index 000000000000..73ebfc306e30 --- /dev/null +++ b/desktop/test/deployment/boxt/manifest.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* 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. +* +**********************************************************************--> + +<m:manifest xmlns:m="http://openoffice.org/2001/manifest"> + <m:file-entry m:media-type="application/vnd.sun.star.configuration-data" + m:full-path="Addons.xcu"/> + <m:file-entry m:media-type="application/vnd.sun.star.configuration-data" + m:full-path="ProtocolHandler.xcu"/> + <m:file-entry + m:media-type="application/vnd.sun.star.uno-component;type=native" + m:full-path="@PATH@"/> +</m:manifest> diff --git a/desktop/test/deployment/dependencies/broken-dependency.oxt b/desktop/test/deployment/dependencies/broken-dependency.oxt Binary files differnew file mode 100644 index 000000000000..11bab0a95092 --- /dev/null +++ b/desktop/test/deployment/dependencies/broken-dependency.oxt diff --git a/desktop/test/deployment/dependencies/double-dependencies.oxt b/desktop/test/deployment/dependencies/double-dependencies.oxt Binary files differnew file mode 100644 index 000000000000..055c27ea53ba --- /dev/null +++ b/desktop/test/deployment/dependencies/double-dependencies.oxt diff --git a/desktop/test/deployment/dependencies/empty-dependencies.oxt b/desktop/test/deployment/dependencies/empty-dependencies.oxt Binary files differnew file mode 100644 index 000000000000..ebb18dcbf51b --- /dev/null +++ b/desktop/test/deployment/dependencies/empty-dependencies.oxt diff --git a/desktop/test/deployment/dependencies/funny-dependency.oxt b/desktop/test/deployment/dependencies/funny-dependency.oxt Binary files differnew file mode 100644 index 000000000000..9b683e6d1e4b --- /dev/null +++ b/desktop/test/deployment/dependencies/funny-dependency.oxt diff --git a/desktop/test/deployment/dependencies/license-dependency.oxt b/desktop/test/deployment/dependencies/license-dependency.oxt Binary files differnew file mode 100644 index 000000000000..b01da4b5ca8a --- /dev/null +++ b/desktop/test/deployment/dependencies/license-dependency.oxt diff --git a/desktop/test/deployment/dependencies/many-dependencies.oxt b/desktop/test/deployment/dependencies/many-dependencies.oxt Binary files differnew file mode 100644 index 000000000000..367568143778 --- /dev/null +++ b/desktop/test/deployment/dependencies/many-dependencies.oxt diff --git a/desktop/test/deployment/dependencies/minattr22.oxt b/desktop/test/deployment/dependencies/minattr22.oxt Binary files differnew file mode 100644 index 000000000000..a6c8e3758cf4 --- /dev/null +++ b/desktop/test/deployment/dependencies/minattr22.oxt diff --git a/desktop/test/deployment/dependencies/minattr23.oxt b/desktop/test/deployment/dependencies/minattr23.oxt Binary files differnew file mode 100644 index 000000000000..83d17938c425 --- /dev/null +++ b/desktop/test/deployment/dependencies/minattr23.oxt diff --git a/desktop/test/deployment/dependencies/minattr24.oxt b/desktop/test/deployment/dependencies/minattr24.oxt Binary files differnew file mode 100644 index 000000000000..00f053f487ec --- /dev/null +++ b/desktop/test/deployment/dependencies/minattr24.oxt diff --git a/desktop/test/deployment/dependencies/no-dependencies.oxt b/desktop/test/deployment/dependencies/no-dependencies.oxt Binary files differnew file mode 100644 index 000000000000..6487eb66ae14 --- /dev/null +++ b/desktop/test/deployment/dependencies/no-dependencies.oxt diff --git a/desktop/test/deployment/dependencies/no-description.oxt b/desktop/test/deployment/dependencies/no-description.oxt Binary files differnew file mode 100644 index 000000000000..1e6579cd7dd4 --- /dev/null +++ b/desktop/test/deployment/dependencies/no-description.oxt diff --git a/desktop/test/deployment/dependencies/readme.txt b/desktop/test/deployment/dependencies/readme.txt new file mode 100644 index 000000000000..a99fade00225 --- /dev/null +++ b/desktop/test/deployment/dependencies/readme.txt @@ -0,0 +1,82 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +no-description.oxt, no-dependencies.oxt, empty-dependencies.oxt effectively have +no dependencies and should thus install successfully. + +broken-dependencies.oxt contains a malformed description.xml and should thus +display an error and not install. + +double-dependencies.oxt contains a description.xml with two dependencies +elements. This is not allowed by the spec but behaviour is unspecified. In the +current implementation, it combines the two elements, and thus finds two +unsatisfied dependencies, displays the Unsatisfied Dependencies dialog and does +not install. + +version21.oxt contains a dependency on OOo 2.1 (and should thus only install in +OOo 2.1 or later); version21ns.oxt is the same, but with a different way of +using XML namespaces; version21other.oxt additionally contains an unsatisfied +dependency (and should thus not install in any OOo version). version22.oxt +contains a dependency on OOo 2.2 (and should thus only install in OOo 2.2 or +later). version23.oxt contains a dependency on OOo 2.3 (and should thus only +install in OOo 2.3 or later). version10000.oxt contains a dependency on the +hypothetical OOo version 10000 (and should thus not install in any OOo version). +versionempty.oxt contains an empty value attribute and versionnone.oxt lacks the +value attribute; neither is allowed by the spec, but the current implementation +treats both as pre OOo 2.1 versions (and the extensions should thus install in +OOo 2.1 or later). + +maxversion30.oxt contains a maximal version dependency on OOo 3.0 (and should +thus only install in OOo 3.0 or earlier, back to OOo 2.3, thanks to the +additionally specified OpenOffice.org-minimal-version attribute). +maxversion10000.oxt contains a maximal version dependency on the hypothetical +OOo version 10000 (and should thus install in any OOo version 3.1 or later; +OpenOffice.org-maximal-version was introduced in OOo 3.1, and no OpenOffice.org- +minimal-version attribute is specified). bad-minmaxversion.oxt contains a +minimal version dependency on OOo 3.2 and a maximal version dependency on +OOo 3.1 (and should thus not install in any OOo version). + +minattr22.oxt contains a (hypothetical, most probably never satisfied) +UNSATISFIED dependency with an OpenOffice.org-minimal-version attribute of +"2.2" (and should thus install in OOo 2.3 or later); minattr23.oxt is similar, +but with an OpenOffice.org-minimal-version attribute of "2.3" (and should thus +also install in OOo 2.3 or later); minattr24.oxt is similar, but with an +OpenOffice.org-minimal-version attribute of "2.4" (and should thus only install +in OOo 2.4 or later). + +All of the following testcases should result in the Unsatisfied Dependencies +dialog being displayed and the extension not being installed: + +unknown-dependency.oxt contains a dependency without a name attribute, and +should thus display "Unknown" (localized). + +funny-dependency.oxt, many-dependencies.oxt contain somewhat extreme input. + +license-dependency.oxt contains both a license to be accepted by the user and +dependencies. What is important here is that the Unsatisfied Dependencies +dialog is displayed, but not the license (as installation aborts as soon as +unsatisfied dependencies are found). diff --git a/desktop/test/deployment/dependencies/unknown-dependency.oxt b/desktop/test/deployment/dependencies/unknown-dependency.oxt Binary files differnew file mode 100644 index 000000000000..7c2a22c6d5da --- /dev/null +++ b/desktop/test/deployment/dependencies/unknown-dependency.oxt diff --git a/desktop/test/deployment/dependencies/version10000.oxt b/desktop/test/deployment/dependencies/version10000.oxt Binary files differnew file mode 100644 index 000000000000..c15b7a117c8c --- /dev/null +++ b/desktop/test/deployment/dependencies/version10000.oxt diff --git a/desktop/test/deployment/dependencies/version21.oxt b/desktop/test/deployment/dependencies/version21.oxt Binary files differnew file mode 100644 index 000000000000..922b2795555c --- /dev/null +++ b/desktop/test/deployment/dependencies/version21.oxt diff --git a/desktop/test/deployment/dependencies/version21ns.oxt b/desktop/test/deployment/dependencies/version21ns.oxt Binary files differnew file mode 100644 index 000000000000..5efb2ed90220 --- /dev/null +++ b/desktop/test/deployment/dependencies/version21ns.oxt diff --git a/desktop/test/deployment/dependencies/version21other.oxt b/desktop/test/deployment/dependencies/version21other.oxt Binary files differnew file mode 100644 index 000000000000..d88a8155af65 --- /dev/null +++ b/desktop/test/deployment/dependencies/version21other.oxt diff --git a/desktop/test/deployment/dependencies/version22.oxt b/desktop/test/deployment/dependencies/version22.oxt Binary files differnew file mode 100644 index 000000000000..4c8a207b68ba --- /dev/null +++ b/desktop/test/deployment/dependencies/version22.oxt diff --git a/desktop/test/deployment/dependencies/version23.oxt b/desktop/test/deployment/dependencies/version23.oxt Binary files differnew file mode 100644 index 000000000000..6c08d2949ced --- /dev/null +++ b/desktop/test/deployment/dependencies/version23.oxt diff --git a/desktop/test/deployment/dependencies/versionempty.oxt b/desktop/test/deployment/dependencies/versionempty.oxt Binary files differnew file mode 100644 index 000000000000..a06bb01294f4 --- /dev/null +++ b/desktop/test/deployment/dependencies/versionempty.oxt diff --git a/desktop/test/deployment/dependencies/versionnone.oxt b/desktop/test/deployment/dependencies/versionnone.oxt Binary files differnew file mode 100644 index 000000000000..ace2a11651ff --- /dev/null +++ b/desktop/test/deployment/dependencies/versionnone.oxt diff --git a/desktop/test/deployment/description/desc1.oxt b/desktop/test/deployment/description/desc1.oxt Binary files differnew file mode 100644 index 000000000000..e447fd6eae78 --- /dev/null +++ b/desktop/test/deployment/description/desc1.oxt diff --git a/desktop/test/deployment/description/desc2.oxt b/desktop/test/deployment/description/desc2.oxt Binary files differnew file mode 100644 index 000000000000..8df2f33fa6de --- /dev/null +++ b/desktop/test/deployment/description/desc2.oxt diff --git a/desktop/test/deployment/description/desc3.oxt b/desktop/test/deployment/description/desc3.oxt Binary files differnew file mode 100644 index 000000000000..fbd1136b039a --- /dev/null +++ b/desktop/test/deployment/description/desc3.oxt diff --git a/desktop/test/deployment/description/desc4.oxt b/desktop/test/deployment/description/desc4.oxt Binary files differnew file mode 100644 index 000000000000..0c97f5fd4426 --- /dev/null +++ b/desktop/test/deployment/description/desc4.oxt diff --git a/desktop/test/deployment/description/desc5.oxt b/desktop/test/deployment/description/desc5.oxt Binary files differnew file mode 100644 index 000000000000..8110073499ca --- /dev/null +++ b/desktop/test/deployment/description/desc5.oxt diff --git a/desktop/test/deployment/description/readme.txt b/desktop/test/deployment/description/readme.txt new file mode 100755 index 000000000000..bb133ba516ce --- /dev/null +++ b/desktop/test/deployment/description/readme.txt @@ -0,0 +1,23 @@ +The folder contains extensions which use in the description.xml the following:
+-The <extension-description> element The element contains localized child
+elements.
+
+The following table shows what localized item is used, when the Office the locale
+en-US uses. The displayed extension description contains the locale.
+
+
+Localization:
+
+Installed office: en-US
+ | locale
+=========================
+desc1.oxt | en-US
+-------------------------
+desc2.oxt | en-US-region1
+--------------------------
+desc3.oxt | en
+--------------------------
+desc4.oxt | en-GB
+--------------------------
+desc5.oxt | de
+
diff --git a/desktop/test/deployment/display_name/name1.oxt b/desktop/test/deployment/display_name/name1.oxt Binary files differnew file mode 100644 index 000000000000..5a53690d6935 --- /dev/null +++ b/desktop/test/deployment/display_name/name1.oxt diff --git a/desktop/test/deployment/display_name/name2.oxt b/desktop/test/deployment/display_name/name2.oxt Binary files differnew file mode 100644 index 000000000000..f6cbcae3bcbd --- /dev/null +++ b/desktop/test/deployment/display_name/name2.oxt diff --git a/desktop/test/deployment/display_name/name3.oxt b/desktop/test/deployment/display_name/name3.oxt Binary files differnew file mode 100644 index 000000000000..8df750ce62a5 --- /dev/null +++ b/desktop/test/deployment/display_name/name3.oxt diff --git a/desktop/test/deployment/display_name/name4.oxt b/desktop/test/deployment/display_name/name4.oxt Binary files differnew file mode 100644 index 000000000000..6ce4822e3701 --- /dev/null +++ b/desktop/test/deployment/display_name/name4.oxt diff --git a/desktop/test/deployment/display_name/name5.oxt b/desktop/test/deployment/display_name/name5.oxt Binary files differnew file mode 100644 index 000000000000..56973be7817b --- /dev/null +++ b/desktop/test/deployment/display_name/name5.oxt diff --git a/desktop/test/deployment/display_name/readme.txt b/desktop/test/deployment/display_name/readme.txt new file mode 100644 index 000000000000..23173bde63dd --- /dev/null +++ b/desktop/test/deployment/display_name/readme.txt @@ -0,0 +1,26 @@ +The folder contains extensions which use in the description.xml the following: +-The <display-name> element +The element contains localized child elements. + +To test the display name in the update dialog use the extensions in +desktop/test/deployment/update/simple + + +The following table shows what localized item is used, when the Office the locale +en-US uses. + + +Localization: + +Installed office: en-US + | publisher | release notes +============================================= +name1.oxt | en-US | en-US +--------------------------------------------- +name2.oxt | en-US-region1 | en-US-region1 +--------------------------------------------- +name3.oxt | en | en +--------------------------------------------- +name4.oxt | en-GB | en-GB +--------------------------------------------- +name5.oxt | de | de diff --git a/desktop/test/deployment/executable_content/build/hello.c b/desktop/test/deployment/executable_content/build/hello.c new file mode 100644 index 000000000000..4e86d9d0e866 --- /dev/null +++ b/desktop/test/deployment/executable_content/build/hello.c @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 <stdio.h> + +int main(int argc , char** argv, char** envp) +{ + //prevent warning about unused parameters + //we need to provide parameter names in C + argc = argc; + argv = argv; + envp = envp; + + fprintf(stdout,"Hello world!\n"); + return 0; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/test/deployment/executable_content/build/makefile.mk b/desktop/test/deployment/executable_content/build/makefile.mk new file mode 100644 index 000000000000..038051c97499 --- /dev/null +++ b/desktop/test/deployment/executable_content/build/makefile.mk @@ -0,0 +1,51 @@ +#************************************************************************* +# +# 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 = hello +LIBTARGET=NO +NO_DEFAULT_STL=TRUE +LIBSALCPPRT= + +.INCLUDE : settings.mk + + +APP1NOSAL = TRUE +APP1OBJS = \ + $(OBJ)$/hello.obj + + +APP1TARGET = $(TARGET) + +DEPOBJFILES = \ + $(OBJ)$/hello.obj + + +.INCLUDE : target.mk + diff --git a/desktop/test/deployment/executable_content/build/readme.txt b/desktop/test/deployment/executable_content/build/readme.txt new file mode 100644 index 000000000000..4f956e573e07 --- /dev/null +++ b/desktop/test/deployment/executable_content/build/readme.txt @@ -0,0 +1,2 @@ +This folder contains the sources to build the hello executable which is contained +in the hello.oxt. diff --git a/desktop/test/deployment/executable_content/hello.oxt b/desktop/test/deployment/executable_content/hello.oxt Binary files differnew file mode 100644 index 000000000000..97d6d14a3128 --- /dev/null +++ b/desktop/test/deployment/executable_content/hello.oxt diff --git a/desktop/test/deployment/executable_content/readme.txt b/desktop/test/deployment/executable_content/readme.txt new file mode 100644 index 000000000000..ad3c01097e14 --- /dev/null +++ b/desktop/test/deployment/executable_content/readme.txt @@ -0,0 +1,12 @@ +When the executable is installed try to execute the executable "hello". The executable +file attribute (not on Windows) should be set. + +CD into the extension directory in /user|share)/uno_packages/cache/uno_packages/xyz_ +Then there are the directories for different platforms: + +windows, +solaris, +linux + +Each directory contains a hello executable. On linux one should execute it in a +shell with an build environment, so that the c++ runtime is found. diff --git a/desktop/test/deployment/identifier/explicit/identifier.oxt b/desktop/test/deployment/identifier/explicit/identifier.oxt Binary files differnew file mode 100644 index 000000000000..3851e291c970 --- /dev/null +++ b/desktop/test/deployment/identifier/explicit/identifier.oxt diff --git a/desktop/test/deployment/identifier/legacy/identifier.oxt b/desktop/test/deployment/identifier/legacy/identifier.oxt Binary files differnew file mode 100644 index 000000000000..df8bb8449241 --- /dev/null +++ b/desktop/test/deployment/identifier/legacy/identifier.oxt diff --git a/desktop/test/deployment/identifier/readme.txt b/desktop/test/deployment/identifier/readme.txt new file mode 100644 index 000000000000..8a791c586a78 --- /dev/null +++ b/desktop/test/deployment/identifier/readme.txt @@ -0,0 +1,33 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +legacy/identifier.oxt and explicit/identifier.oxt are two different extensions +that happen to have the same file name. legacy/identifier.oxt does not have an +explicit extension identifier, so it gets the implicit one "org.openoffice. +legacy.identifier.oxt". explicit/identifier.oxt has the +explicit extension identifier "org.openoffice/framework/desktop/test/deployment/ +identifier/explicit/identifier.oxt". diff --git a/desktop/test/deployment/locationtest/LocationTest.idl b/desktop/test/deployment/locationtest/LocationTest.idl new file mode 100644 index 000000000000..43beaac0a353 --- /dev/null +++ b/desktop/test/deployment/locationtest/LocationTest.idl @@ -0,0 +1,40 @@ +/************************************************************************* + * + * 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 _com_sun_star_comp_smoketest_LocationTest_idl_ +#define _com_sun_star_comp_smoketest_LocationTest_idl_ + +#include <com/sun/star/lang/XServiceInfo.idl> + + +module com { module sun { module star { module comp { module smoketest { + // example service, XServiceInfo is implemented here for demonstration + // issues. XServiceInfo must be implemented by all components. + service TestExtension: ::com::sun::star::lang::XServiceInfo; +};};};};}; + +#endif diff --git a/desktop/test/deployment/locationtest/LocationTest.java b/desktop/test/deployment/locationtest/LocationTest.java new file mode 100644 index 000000000000..b16d4945515b --- /dev/null +++ b/desktop/test/deployment/locationtest/LocationTest.java @@ -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. + * + *************************************************************************/ +package com.sun.star.comp.smoketest; + +import com.sun.star.lib.uno.helper.Factory; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XSingleComponentFactory; +import com.sun.star.lib.uno.helper.WeakBase; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.registry.XRegistryKey; +import com.sun.star.lang.XInitialization; +import com.sun.star.lang.XTypeProvider; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.uno.Type; + +/** This class capsulates the class, that implements the minimal component, a + * factory for creating the service (<CODE>__getComponentFactory</CODE>) and a + * method, that writes the information into the given registry key + * (<CODE>__writeRegistryServiceInfo</CODE>). + */ +public class LocationTest { + /** This class implements the component. At least the interfaces XServiceInfo, + * XTypeProvider, and XInitialization should be provided by the service. + */ + public static class _LocationTest extends WeakBase + implements XServiceInfo { + /** The service name, that must be used to get an instance of this service. + */ + static private final String __serviceName = + "com.sun.star.comp.smoketest.LocationTest"; + + /** The initial component contextr, that gives access to + * the service manager, supported singletons, ... + * It's often later used + */ + private XComponentContext m_cmpCtx; + + /** The service manager, that gives access to all registered services. + * It's often later used + */ + private XMultiComponentFactory m_xMCF; + + /** The constructor of the inner class has a XMultiServiceFactory parameter. + * @param xmultiservicefactoryInitialization A special service factory + * could be introduced while initializing. + */ + public _LocationTest(XComponentContext xCompContext) { + try { + m_cmpCtx = xCompContext; + m_xMCF = m_cmpCtx.getServiceManager(); + } + catch( Exception e ) { + e.printStackTrace(); + } + } + + /** This method returns an array of all supported service names. + * @return Array of supported service names. + */ + public String[] getSupportedServiceNames() { + return getServiceNames(); + } + + /** This method is a simple helper function to used in the + * static component initialisation functions as well as in + * getSupportedServiceNames. + */ + public static String[] getServiceNames() { + String[] sSupportedServiceNames = { __serviceName }; + return sSupportedServiceNames; + } + + /** This method returns true, if the given service will be + * supported by the component. + * @param sServiceName Service name. + * @return True, if the given service name will be supported. + */ + public boolean supportsService( String sServiceName ) { + return sServiceName.equals( __serviceName ); + } + + /** Return the class name of the component. + * @return Class name of the component. + */ + public String getImplementationName() { + return _LocationTest.class.getName(); + } + } + + + /** + * Gives a factory for creating the service. + * This method is called by the <code>JavaLoader</code> + * <p> + * @return returns a <code>XSingleComponentFactory</code> for creating + * the component + * @param sImplName the name of the implementation for which a + * service is desired + * @see com.sun.star.comp.loader.JavaLoader + */ + public static XSingleComponentFactory __getComponentFactory(String sImplName) + { + XSingleComponentFactory xFactory = null; + + if ( sImplName.equals( _LocationTest.class.getName() ) ) + xFactory = Factory.createComponentFactory(_LocationTest.class, + _LocationTest.getServiceNames()); + + return xFactory; + } + + /** + * Writes the service information into the given registry key. + * This method is called by the <code>JavaLoader</code> + * <p> + * @return returns true if the operation succeeded + * @param regKey the registryKey + * @see com.sun.star.comp.loader.JavaLoader + */ + public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) { + return Factory.writeRegistryServiceInfo(_LocationTest.class.getName(), + _LocationTest.getServiceNames(), + regKey); + } + + /** This method is a member of the interface for initializing an object + * directly after its creation. + * @param object This array of arbitrary objects will be passed to the + * component after its creation. + * @throws Exception Every exception will not be handled, but will be + * passed to the caller. + */ + public void initialize( Object[] object ) + throws com.sun.star.uno.Exception { + /* The component describes what arguments its expected and in which + * order!At this point you can read the objects and can intialize + * your component using these objects. + */ + } +} diff --git a/desktop/test/deployment/locationtest/LocationTest.odt b/desktop/test/deployment/locationtest/LocationTest.odt Binary files differnew file mode 100644 index 000000000000..8e1aa70078db --- /dev/null +++ b/desktop/test/deployment/locationtest/LocationTest.odt diff --git a/desktop/test/deployment/locationtest/MANIFEST.MF b/desktop/test/deployment/locationtest/MANIFEST.MF new file mode 100644 index 000000000000..a2fa8c34b7f9 --- /dev/null +++ b/desktop/test/deployment/locationtest/MANIFEST.MF @@ -0,0 +1,2 @@ +RegistrationClassName: com.sun.star.comp.smoketest.LocationTest + diff --git a/desktop/test/deployment/locationtest/delzip b/desktop/test/deployment/locationtest/delzip new file mode 100644 index 000000000000..636fda90bfcb --- /dev/null +++ b/desktop/test/deployment/locationtest/delzip @@ -0,0 +1 @@ +ECHO is OFF diff --git a/desktop/test/deployment/locationtest/description.xml b/desktop/test/deployment/locationtest/description.xml new file mode 100644 index 000000000000..54e45537b0aa --- /dev/null +++ b/desktop/test/deployment/locationtest/description.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/description/2006" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:d="http://openoffice.org/extensions/description/2006" > + <identifier value="org.openoffice.extensions.testarea.desktop.location"/> + <version value="1.0" /> + <dependencies > + <OpenOffice.org-minimal-version value="2.2" d:name="OpenOffice.org 2.2"/> + </dependencies> + <update-information> + <src xlink:href="http://update.services.openoffice.org/ProductUpdateService/check.Update?product=extension&extensionid=org.openoffice.extensions.testarea.desktop.updateinfo&refresh=true"/> + </update-information> +</description> diff --git a/desktop/test/deployment/locationtest/makefile.mk b/desktop/test/deployment/locationtest/makefile.mk new file mode 100644 index 000000000000..8fe189791961 --- /dev/null +++ b/desktop/test/deployment/locationtest/makefile.mk @@ -0,0 +1,84 @@ +#************************************************************************* +# +# 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 = location_test +PACKAGE = com$/sun$/star$/comp$/smoketest +TARGET = com_sun_star_comp_smoketest + +no_common_build_zip:=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +JARFILES = ridl.jar jurt.jar unoil.jar juh.jar + +JARTARGET = LocationTest.jar +JARCOMPRESS = TRUE +CUSTOMMANIFESTFILE = MANIFEST.MF + +ZIP1TARGET=locationtest +ZIP1LIST=* +ZIPFLAGS=-r +ZIP1DIR=$(MISC)$/$(TARGET) +ZIP1EXT=.oxt + +# --- Files -------------------------------------------------------- + +COPY_OXT_MANIFEST:= $(MISC)$/$(TARGET)$/META-INF$/manifest.xml +JAVAFILES = LocationTest.java + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +$(JARTARGETN) : $(MISC)$/$(TARGET).javamaker.done + +$(JAVACLASSFILES) : $(MISC)$/$(TARGET).javamaker.done + +$(MISC)$/$(TARGET).javamaker.done: $(BIN)$/LocationTest.rdb + $(JAVAMAKER) -O$(CLASSDIR) -BUCR -nD -X$(SOLARBINDIR)/types.rdb $< + $(TOUCH) $@ + +$(BIN)$/LocationTest.rdb: LocationTest.idl + $(IDLC) -O$(MISC) -I$(SOLARIDLDIR) -cid -we $< + +-$(RM) $@ + $(REGMERGE) $@ /UCR $(MISC)$/LocationTest.urd + +$(MISC)$/$(ZIP1TARGET).createdir : + +$(MKDIRHIER) $(MISC)$/$(TARGET)$/META-INF >& $(NULLDEV) && $(TOUCH) $@ + +$(MISC)$/$(TARGET)_resort : manifest.xml $(JARTARGETN) $(MISC)$/$(ZIP1TARGET).createdir $(BIN)$/LocationTest.rdb description.xml + $(COPY) manifest.xml $(MISC)$/$(TARGET)$/META-INF$/manifest.xml + $(COPY) $(JARTARGETN) $(MISC)$/$(TARGET)$/$(JARTARGET) + $(COPY) $(BIN)$/LocationTest.rdb $(MISC)$/$(TARGET)$/LocationTest.rdb + $(COPY) description.xml $(MISC)$/$(TARGET)$/description.xml + $(TOUCH) $@ + +$(ZIP1TARGETN) : $(MISC)$/$(TARGET)_resort $(MISC)$/$(ZIP1TARGET).createdir + diff --git a/desktop/test/deployment/locationtest/manifest.xml b/desktop/test/deployment/locationtest/manifest.xml new file mode 100644 index 000000000000..8791582798bd --- /dev/null +++ b/desktop/test/deployment/locationtest/manifest.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<manifest:manifest> + <manifest:file-entry manifest:full-path="LocationTest.jar" manifest:media-type="application/vnd.sun.star.uno-component;type=Java"/> + <manifest:file-entry manifest:full-path="LocationTest.rdb" manifest:media-type="application/vnd.sun.star.uno-typelibrary;type=RDB"/> +</manifest:manifest>
\ No newline at end of file diff --git a/desktop/test/deployment/options/handler/com/sun/star/comp/extensionoptions/MANIFEST.MF b/desktop/test/deployment/options/handler/com/sun/star/comp/extensionoptions/MANIFEST.MF new file mode 100644 index 000000000000..fba55a6e0d5a --- /dev/null +++ b/desktop/test/deployment/options/handler/com/sun/star/comp/extensionoptions/MANIFEST.MF @@ -0,0 +1,2 @@ +RegistrationClassName: com.sun.star.comp.extensionoptions.OptionsEventHandler + diff --git a/desktop/test/deployment/options/handler/com/sun/star/comp/extensionoptions/OptionsEventHandler.java b/desktop/test/deployment/options/handler/com/sun/star/comp/extensionoptions/OptionsEventHandler.java new file mode 100644 index 000000000000..bd8e40826cf3 --- /dev/null +++ b/desktop/test/deployment/options/handler/com/sun/star/comp/extensionoptions/OptionsEventHandler.java @@ -0,0 +1,449 @@ +************************************************************************* + * + * 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. + * + *************************************************************************/ +package com.sun.star.comp.extensionoptions; + +import com.sun.star.lib.uno.helper.Factory; +import com.sun.star.lib.uno.helper.WeakBase; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XSingleComponentFactory; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.lang.IllegalArgumentException; +import com.sun.star.lang.XInitialization; +import com.sun.star.lang.XTypeProvider; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.Any; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.Exception; +import com.sun.star.registry.XRegistryKey; +import com.sun.star.awt.XContainerWindowEventHandler; +import com.sun.star.awt.XControl; +import com.sun.star.awt.XControlModel; +import com.sun.star.awt.XControlContainer; +import com.sun.star.container.XNameAccess; +import com.sun.star.container.NoSuchElementException; +import com.sun.star.beans.PropertyValue; +import com.sun.star.beans.PropertyState; +import com.sun.star.beans.XPropertySet; +import com.sun.star.beans.UnknownPropertyException; +import com.sun.star.beans.PropertyVetoException; +import com.sun.star.util.XChangesBatch; + +/** A handler which supports multiple options pages which all + * have the same controls. + */ +public class OptionsEventHandler { + + public static class _OptionsEventHandler extends WeakBase + implements XServiceInfo, XContainerWindowEventHandler { + + static private final String __serviceName = + "com.sun.star.comp.extensionoptions.OptionsEventHandler"; + + private XComponentContext m_cmpCtx; + + private XMultiComponentFactory m_xMCF; + + private XNameAccess m_xAccessLeaves; + + /**Names of supported options pages. + */ + private String[] m_arWindowNames = { + "Writer1", "Writer2", "Writer3", "Calc1", "Calc2", "Calc3", + "Draw1", "Draw2", "Draw3", "Node1_1", "Node1_2", "Node1_3", + "Node2_1", "Node2_2", "Node2_3", "Node3_1", "Node3_2", "Node3_3"}; + + /**Names of the controls which are supported by this handler. All these + *controls must have a "Text" property. + */ + private String[] m_arStringControls = { + "String0", "String1", "String2", "String3", "String4"}; + + public _OptionsEventHandler(XComponentContext xCompContext) { + m_cmpCtx = xCompContext; + m_xMCF = m_cmpCtx.getServiceManager(); + + //Create the com.sun.star.configuration.ConfigurationUpdateAccess + //for the registry node which contains the data for our option + //pages. + XMultiServiceFactory xConfig; + try { + xConfig = (XMultiServiceFactory) UnoRuntime.queryInterface( + XMultiServiceFactory.class, + m_cmpCtx.getServiceManager().createInstanceWithContext( + "com.sun.star.configuration.ConfigurationProvider", m_cmpCtx)); + } catch (com.sun.star.uno.Exception e) { + e.printStackTrace(); + return; + } + + //One argument for creating the ConfigurationUpdateAccess is the "nodepath". + //Our nodepath point to the node of which the direct subnodes represent the + //different options pages. + Object[] args = new Object[1]; + args[0] = new PropertyValue( + "nodepath", 0, "/org.openoffice.desktop.deployment.options.ExtensionData/Leaves", + PropertyState.DIRECT_VALUE); + + //We get the com.sun.star.container.XNameAccess from the instance of + //ConfigurationUpdateAccess and save it for later use. + try { + m_xAccessLeaves = (XNameAccess) UnoRuntime.queryInterface( + XNameAccess.class, xConfig.createInstanceWithArguments( + "com.sun.star.configuration.ConfigurationUpdateAccess", args)); + + } catch (com.sun.star.uno.Exception e) { + e.printStackTrace(); + return; + } + } + + /** This method returns an array of all supported service names. + * @return Array of supported service names. + */ + public String[] getSupportedServiceNames() { + return getServiceNames(); + } + + /** This method is a simple helper function to used in the + * static component initialisation functions as well as in + * getSupportedServiceNames. + */ + public static String[] getServiceNames() { + String[] sSupportedServiceNames = { __serviceName }; + return sSupportedServiceNames; + } + + /** This method returns true, if the given service will be + * supported by the component. + * @param sServiceName Service name. + * @return True, if the given service name will be supported. + */ + public boolean supportsService( String sServiceName ) { + return sServiceName.equals( __serviceName ); + } + + /** Return the class name of the component. + * @return Class name of the component. + */ + public String getImplementationName() { + return _OptionsEventHandler.class.getName(); + } + + //XContainerWindowEventHandler + public boolean callHandlerMethod(com.sun.star.awt.XWindow aWindow, + Object aEventObject, String sMethod) + throws WrappedTargetException { + if (sMethod.equals("external_event") ){ + try { + return handleExternalEvent(aWindow, aEventObject); + } catch (com.sun.star.uno.RuntimeException re) { + throw re; + } catch (com.sun.star.uno.Exception e) { + throw new WrappedTargetException(sMethod, this, e); + } + } + + return true; + } + + //XContainerWindowEventHandler + public String[] getSupportedMethodNames() { + return new String[] {"external_event"}; + } + + private boolean handleExternalEvent(com.sun.star.awt.XWindow aWindow, Object aEventObject) + throws com.sun.star.uno.Exception { + try { + String sMethod = AnyConverter.toString(aEventObject); + if (sMethod.equals("ok")) { + saveData(aWindow); + } else if (sMethod.equals("back") || sMethod.equals("initialize")) { + loadData(aWindow); + } + } catch (com.sun.star.lang.IllegalArgumentException e) { + throw new com.sun.star.lang.IllegalArgumentException( + "Method external_event requires a string in the event object argument.", + this, (short) -1); + } + + return true; + } + + private void saveData(com.sun.star.awt.XWindow aWindow) + throws com.sun.star.lang.IllegalArgumentException, + com.sun.star.uno.Exception { + + //Determine the name of the options page. This serves two purposes. First, if this + //options page is supported by this handler and second we use the name two locate + //the corresponding data in the registry. + String sWindowName = getWindowName(aWindow); + if (sWindowName == null) + throw new com.sun.star.lang.IllegalArgumentException( + "This window is not supported by this handler", this, (short) -1); + + //To access the separate controls of the window we need to obtain the + //XControlContainer from the window implementation + XControlContainer xContainer = (XControlContainer) UnoRuntime.queryInterface( + XControlContainer.class, aWindow); + if (xContainer == null) + throw new com.sun.star.uno.Exception( + "Could not get XControlContainer from window.", this); + + //This is an implementation which will be used for several options pages + //which all have the same controls. m_arStringControls is an array which + //contains the names. + for (int i = 0; i < m_arStringControls.length; i++) { + + //To obtain the data from the controls we need to get their model. + //First get the respective control from the XControlContainer. + XControl xControl = xContainer.getControl(m_arStringControls[i]); + + //This generic handler and the corresponding registry schema support + //up to five text controls. However, if a options page does not use all + //five controls then we will not complain here. + if (xControl == null) + continue; + + //From the control we get the model, which in turn supports the + //XPropertySet interface, which we finally use to get the data from + //the control. + XPropertySet xProp = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, xControl.getModel()); + + if (xProp == null) + throw new com.sun.star.uno.Exception( + "Could not get XPropertySet from control.", this); + //Get the "Text" property. + Object aText = xProp.getPropertyValue("Text"); + String sValue = null; + + //The value is still contained in a com.sun.star.uno.Any - so convert it. + try { + sValue = AnyConverter.toString(aText); + } catch (com.sun.star.lang.IllegalArgumentException e) { + throw new com.sun.star.lang.IllegalArgumentException( + "Wrong property type.", this, (short) -1); + } + + //Now we have the actual string value of the control. What we need now is + //the XPropertySet of the respective property in the registry, so that we + //can store the value. + //To access the registry we have previously created a service instance + //of com.sun.star.configuration.ConfigurationUpdateAccess which supports + //com.sun.star.container.XNameAccess. The XNameAccess is used to get the + //particular registry node which represents this options page. + //Fortunately the name of the window is the same as the registry node. + XPropertySet xLeaf = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, m_xAccessLeaves.getByName(sWindowName)); + if (xLeaf == null) + throw new com.sun.star.uno.Exception( + "XPropertySet not supported.", this); + + //Finally we can set the value + xLeaf.setPropertyValue(m_arStringControls[i], sValue); + } + + //Committing the changes will cause or changes to be written to the registry. + XChangesBatch xUpdateCommit = + (XChangesBatch) UnoRuntime.queryInterface(XChangesBatch.class, m_xAccessLeaves); + xUpdateCommit.commitChanges(); + } + + private void loadData(com.sun.star.awt.XWindow aWindow) + throws com.sun.star.uno.Exception { + + //Determine the name of the window. This serves two purposes. First, if this + //window is supported by this handler and second we use the name two locate + //the corresponding data in the registry. + String sWindowName = getWindowName(aWindow); + if (sWindowName == null) + throw new com.sun.star.lang.IllegalArgumentException( + "The window is not supported by this handler", this, (short) -1); + + //To acces the separate controls of the window we need to obtain the + //XControlContainer from window implementation + XControlContainer xContainer = (XControlContainer) UnoRuntime.queryInterface( + XControlContainer.class, aWindow); + if (xContainer == null) + throw new com.sun.star.uno.Exception( + "Could not get XControlContainer from window.", this); + + //This is an implementation which will be used for several options pages + //which all have the same controls. m_arStringControls is an array which + //contains the names. + for (int i = 0; i < m_arStringControls.length; i++) { + + //load the values from the registry + //To access the registry we have previously created a service instance + //of com.sun.star.configuration.ConfigurationUpdateAccess which supports + //com.sun.star.container.XNameAccess. We obtain now the section + //of the registry which is assigned to this options page. + XPropertySet xLeaf = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, m_xAccessLeaves.getByName(sWindowName)); + if (xLeaf == null) + throw new com.sun.star.uno.Exception( + "XPropertySet not supported.", this); + + //The properties in the registry have the same name as the respective + //controls. We use the names now to obtain the property values. + Object aValue = xLeaf.getPropertyValue(m_arStringControls[i]); + + //Now that we have the value we need to set it at the corresponding + //control in the window. The XControlContainer, which we obtained earlier + //is the means to get hold of all the controls. + XControl xControl = xContainer.getControl(m_arStringControls[i]); + + //This generic handler and the corresponding registry schema support + //up to five text controls. However, if a options page does not use all + //five controls then we will not complain here. + if (xControl == null) + continue; + + //From the control we get the model, which in turn supports the + //XPropertySet interface, which we finally use to set the data at the + //control + XPropertySet xProp = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, xControl.getModel()); + + if (xProp == null) + throw new com.sun.star.uno.Exception( + "Could not get XPropertySet from control.", this); + + //This handler supports only text controls, which are named "Pattern Field" + //in the dialog editor. We set the "Text" property. + xProp.setPropertyValue("Text", aValue); + } + } + + //Checks if the name property of the window is one of the supported names and returns + //always a valid string or null + private String getWindowName(com.sun.star.awt.XWindow aWindow) + throws com.sun.star.uno.Exception { + + if (aWindow == null) + new com.sun.star.lang.IllegalArgumentException( + "Method external_event requires that a window is passed as argument", + this, (short) -1); + + //We need to get the control model of the window. Therefore the first step is + //to query for it. + XControl xControlDlg = (XControl) UnoRuntime.queryInterface( + XControl.class, aWindow); + + if (xControlDlg == null) + throw new com.sun.star.uno.Exception( + "Cannot obtain XControl from XWindow in method external_event."); + //Now get model + XControlModel xModelDlg = xControlDlg.getModel(); + + if (xModelDlg == null) + throw new com.sun.star.uno.Exception( + "Cannot obtain XControlModel from XWindow in method external_event.", this); + //The model itself does not provide any information except that its + //implementation supports XPropertySet which is used to access the data. + XPropertySet xPropDlg = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, xModelDlg); + if (xPropDlg == null) + throw new com.sun.star.uno.Exception( + "Cannot obtain XPropertySet from window in method external_event.", this); + + //Get the "Name" property of the window + Object aWindowName = xPropDlg.getPropertyValue("Name"); + + //Get the string from the returned com.sun.star.uno.Any + String sName = null; + try { + sName = AnyConverter.toString(aWindowName); + } catch (com.sun.star.lang.IllegalArgumentException e) { + throw new com.sun.star.uno.Exception( + "Name - property of window is not a string.", this); + } + + //Eventually we can check if we this handler can "handle" this options page. + //The class has a member m_arWindowNames which contains all names of windows + //for which it is intended + for (int i = 0; i < m_arWindowNames.length; i++) { + if (m_arWindowNames[i].equals(sName)) { + return sName; + } + } + return null; + } + } + + + /** + * Gives a factory for creating the service. + * This method is called by the <code>JavaLoader</code> + * <p> + * @return returns a <code>XSingleComponentFactory</code> for creating + * the component + * @param sImplName the name of the implementation for which a + * service is desired + * @see com.sun.star.comp.loader.JavaLoader + */ + public static XSingleComponentFactory __getComponentFactory(String sImplName) + { + XSingleComponentFactory xFactory = null; + + if ( sImplName.equals( _OptionsEventHandler.class.getName() ) ) + xFactory = Factory.createComponentFactory(_OptionsEventHandler.class, + _OptionsEventHandler.getServiceNames()); + + return xFactory; + } + + /** + * Writes the service information into the given registry key. + * This method is called by the <code>JavaLoader</code> + * <p> + * @return returns true if the operation succeeded + * @param regKey the registryKey + * @see com.sun.star.comp.loader.JavaLoader + */ + public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) { + return Factory.writeRegistryServiceInfo(_OptionsEventHandler.class.getName(), + _OptionsEventHandler.getServiceNames(), + regKey); + } + + /** This method is a member of the interface for initializing an object + * directly after its creation. + * @param object This array of arbitrary objects will be passed to the + * component after its creation. + * @throws Exception Every exception will not be handled, but will be + * passed to the caller. + */ + public void initialize( Object[] object ) + throws com.sun.star.uno.Exception { + } + +} diff --git a/desktop/test/deployment/options/handler/com/sun/star/comp/extensionoptions/makefile.mk b/desktop/test/deployment/options/handler/com/sun/star/comp/extensionoptions/makefile.mk new file mode 100644 index 000000000000..662fffce407c --- /dev/null +++ b/desktop/test/deployment/options/handler/com/sun/star/comp/extensionoptions/makefile.mk @@ -0,0 +1,53 @@ +#************************************************************************* +# +# 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 +PACKAGE = com$/sun$/star$/comp$/extensionoptions +TARGET = options + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +JARFILES = ridl.jar jurt.jar unoil.jar juh.jar + + +JARTARGET = extensionoptions.jar +JARCOMPRESS = TRUE +CUSTOMMANIFESTFILE = MANIFEST.MF +JARCLASSDIRS=com + + +# --- Files -------------------------------------------------------- + +JAVAFILES = OptionsEventHandler.java + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/desktop/test/deployment/options/leaf1.oxt b/desktop/test/deployment/options/leaf1.oxt Binary files differnew file mode 100644 index 000000000000..9c3ff86985b6 --- /dev/null +++ b/desktop/test/deployment/options/leaf1.oxt diff --git a/desktop/test/deployment/options/leaf1mod.oxt b/desktop/test/deployment/options/leaf1mod.oxt Binary files differnew file mode 100644 index 000000000000..d5d9fe6896f8 --- /dev/null +++ b/desktop/test/deployment/options/leaf1mod.oxt diff --git a/desktop/test/deployment/options/leaf2.oxt b/desktop/test/deployment/options/leaf2.oxt Binary files differnew file mode 100644 index 000000000000..b95628900c40 --- /dev/null +++ b/desktop/test/deployment/options/leaf2.oxt diff --git a/desktop/test/deployment/options/leaves1.oxt b/desktop/test/deployment/options/leaves1.oxt Binary files differnew file mode 100644 index 000000000000..037389a018b8 --- /dev/null +++ b/desktop/test/deployment/options/leaves1.oxt diff --git a/desktop/test/deployment/options/leaves2.oxt b/desktop/test/deployment/options/leaves2.oxt Binary files differnew file mode 100644 index 000000000000..531b38566352 --- /dev/null +++ b/desktop/test/deployment/options/leaves2.oxt diff --git a/desktop/test/deployment/options/leaves3.oxt b/desktop/test/deployment/options/leaves3.oxt Binary files differnew file mode 100644 index 000000000000..f5bb0f226239 --- /dev/null +++ b/desktop/test/deployment/options/leaves3.oxt diff --git a/desktop/test/deployment/options/modules1.oxt b/desktop/test/deployment/options/modules1.oxt Binary files differnew file mode 100644 index 000000000000..bae652ffbc39 --- /dev/null +++ b/desktop/test/deployment/options/modules1.oxt diff --git a/desktop/test/deployment/options/modules2.oxt b/desktop/test/deployment/options/modules2.oxt Binary files differnew file mode 100644 index 000000000000..d6d7956d459c --- /dev/null +++ b/desktop/test/deployment/options/modules2.oxt diff --git a/desktop/test/deployment/options/nodes1.oxt b/desktop/test/deployment/options/nodes1.oxt Binary files differnew file mode 100644 index 000000000000..b1dfa18d3efa --- /dev/null +++ b/desktop/test/deployment/options/nodes1.oxt diff --git a/desktop/test/deployment/options/nodes2.oxt b/desktop/test/deployment/options/nodes2.oxt Binary files differnew file mode 100644 index 000000000000..a35cfaba9dc8 --- /dev/null +++ b/desktop/test/deployment/options/nodes2.oxt diff --git a/desktop/test/deployment/options/nodes3.oxt b/desktop/test/deployment/options/nodes3.oxt Binary files differnew file mode 100644 index 000000000000..db0bc49da522 --- /dev/null +++ b/desktop/test/deployment/options/nodes3.oxt diff --git a/desktop/test/deployment/options/nodes4.oxt b/desktop/test/deployment/options/nodes4.oxt Binary files differnew file mode 100644 index 000000000000..fe0550fdc655 --- /dev/null +++ b/desktop/test/deployment/options/nodes4.oxt diff --git a/desktop/test/deployment/options/nodes5.oxt b/desktop/test/deployment/options/nodes5.oxt Binary files differnew file mode 100644 index 000000000000..893e9ee3e216 --- /dev/null +++ b/desktop/test/deployment/options/nodes5.oxt diff --git a/desktop/test/deployment/options/readme.txt b/desktop/test/deployment/options/readme.txt new file mode 100644 index 000000000000..9879a72ceffa --- /dev/null +++ b/desktop/test/deployment/options/readme.txt @@ -0,0 +1,200 @@ +Important: The hander component extensionoptions.jar in the extensions may not +contain exactly the same sources as the one build in the handler directory. To +make sure that debugging works build the handler directory and put the +extensionoptions.jar into the extension. + + + +leaf1.oxt: Defines a leaf under the node WriterNode +================================================================================ + +leaf1mod.oxt: Defines a leaf under the node WriterNode + +It has a douplicate entry in the manifest.xml (OptionsDialog.xcu). This would cause a DisposedException when uninstalling on OOo 3.0 and prevent the extension from being uninstalled. This is actually a bug of the extensions. However, the error is difficult to investigate. Therefore this was fixed to make OOo more robust (i96690). +================================================================================ + +leaf2.oxt: Defines a leaf under a node that has a name which requires special +"xml encoding". The name is "My Writer's & Settings". The node is not assigned +to a Module and the Node/AllModules property is not true. This is a typical +scenario when a Node had been added to an existing Module and later the Module +was removed. This is a situation which actually should not occur. In this case +DO NOT show the Node in the OOo's options dialog, because it shows only nodes +for a particular module and in this case the Module for the Node is unknown. +In the Extension Manager's +options dialog this Node can be shown because the Module is irrelevant. +See also nodes5.oxt. +================================================================================ + +leaves1.oxt: multiple ordered leaves under available nodes. The leaves Lables are +localized for en-US and de. The following leaves should appear: + +Writer: +-leaves1 Writer 1 en-US +-leaves1 Writer 2 en-US +-leaves1 Writer 3 en-US + +Calc: +-leaves1 Calc 3 en-US +-leaves1 Calc 3 en-US +-leaves1 Calc 3 en-US + +Draw: +-leaves1 Draw 3 en-US +-leaves1 Draw 3 en-US +-leaves1 Draw 3 en-US + +If a german office is used then the strings contain "de" instead of "en-US". +================================================================================ + +leaves2.oxt: Same as leaves1.oxt. Use together with leaves1.oxt to test the +grouping of leaves. +================================================================================ + +leaves3.oxt: Same as leaves1.oxt, but the leaves are not ordered. +================================================================================ + +nodes1.oxt: Defines one node which has AllModules set and which has +no children. Therefore this node should not be displayed. +================================================================================ + +nodes2.oxt: Defines 3 nodes which use AllModules and which form an +ordered group. Every node defines also 3 nodes which have a determined order. + +-nodes2 node 1 en-US + -nodes2 node 1 leaf 1 en-US + -nodes2 node 1 leaf 2 en-US + -nodes2 node 1 leaf 3 en-US + +-nodes2 node 2 en-US + -nodes2 node 2 leaf 1 en-US + -nodes2 node 2 leaf 2 en-US + -nodes2 node 2 leaf 3 en-US + +-nodes2 node 3 en-US + -nodes2 node 3 leaf 1 en-US + -nodes2 node 3 leaf 2 en-US + -nodes2 node 3 leaf 3 en-US + +================================================================================ + +nodes3.oxt: Defines 3 nodes which are placed under different existing Modules. +The nodes and there leaves are ordered. + +Context Writer: +- nodes3 node 1 + nodes3 node 1 leaf 1 en-US + nodes3 node 1 leaf 2 en-US + nodes3 node 1 leaf 3 en-US + +- nodes3 node 2 + nodes3 node 2 leaf 1 en-US + nodes3 node 2 leaf 2 en-US + nodes3 node 2 leaf 3 en-US + +- nodes3 node 3 + nodes3 node 3 leaf 1 en-US + nodes3 node 3 leaf 2 en-US + nodes3 node 3 leaf 3 en-US + +Context Calc: +- nodes3 node 1 + nodes3 node 1 leaf 1 en-US + nodes3 node 1 leaf 2 en-US + nodes3 node 1 leaf 3 en-US + +- nodes3 node 3 + nodes3 node 3 leaf 1 en-US + nodes3 node 3 leaf 2 en-US + nodes3 node 3 leaf 3 en-US + +Context Draw: +- nodes3 node 2 + nodes3 node 2 leaf 1 en-US + nodes3 node 2 leaf 2 en-US + nodes3 node 2 leaf 3 en-US + +================================================================================ + +nodes4.oxt: Same as nodes3.oxt. Use together with nodes3.txt to test the +grouping of nodes. +================================================================================ + +nodes5.oxt: Defines a node which in turn defines 3 leaves. The Node +is not assigned to a Module and the AllModule property is false (which is the +default).This may happen when a node +had been added to an already existing Module and then this Module was removed. For +example, an extension adds a node to the "Writer Module" and the +next office update removes the "Writer Module" (which is rather inconceivable). +Then the node and its leaves MUST NOT be displayed in OOo's options dialog, +because the Module is not known. However, it can be displayed in the +options dialog of the Extension Manager. See also the description for leaf2.oxt. +================================================================================ + +modules1.oxt: Defines two Modules and three Nodes. The Nodes may not +be displayed in OOo's options dialog because there is currently no application +which uses this Module. However the Nodes are displayed in the options dialog +of the Extension Manager. +There are three Nodes defined. The relation ship is this: + +-module1 + -node 1 + -leaf 1 + -leaf 2 + -leaf 3 + -node 2 + -leaf 1 + -leaf 2 + -leaf 3 + -node 3 + -leaf 1 + -leaf 2 + -leaf 3 + +-module2 + -node1 + -leaf 1 + -leaf 2 + -leaf 3 + -node3 + -leaf 1 + -leaf 2 + -leaf 3 + +The options dialog of the Extension Manager shall display only three nodes: + + -node 1 + -leaf 1 + -leaf 2 + -leaf 3 + -node 2 + -leaf 1 + -leaf 2 + -leaf 3 + -node 3 + -leaf 1 + -leaf 2 + -leaf 3 + +or + + -node 1 + -leaf 1 + -leaf 2 + -leaf 3 + -node 3 + -leaf 1 + -leaf 2 + -leaf 3 + -node 2 + -leaf 1 + -leaf 2 + -leaf 3 + +Since the order of Module|s is not defined, the dialog may display first the +Nodes from module2 and then from module1. If a node is already displayed then +it is not shown again. + +================================================================================ + +modules2.oxt: Same as modules1, except that the order of nodes and leaves +is not defined. diff --git a/desktop/test/deployment/simple_license/BadDesc.oxt b/desktop/test/deployment/simple_license/BadDesc.oxt Binary files differnew file mode 100644 index 000000000000..436778d54dd4 --- /dev/null +++ b/desktop/test/deployment/simple_license/BadDesc.oxt diff --git a/desktop/test/deployment/simple_license/BadNamespace.oxt b/desktop/test/deployment/simple_license/BadNamespace.oxt Binary files differnew file mode 100644 index 000000000000..e439c9e171de --- /dev/null +++ b/desktop/test/deployment/simple_license/BadNamespace.oxt diff --git a/desktop/test/deployment/simple_license/BadRoot.oxt b/desktop/test/deployment/simple_license/BadRoot.oxt Binary files differnew file mode 100644 index 000000000000..1f6c60c992ba --- /dev/null +++ b/desktop/test/deployment/simple_license/BadRoot.oxt diff --git a/desktop/test/deployment/simple_license/Locale1.oxt b/desktop/test/deployment/simple_license/Locale1.oxt Binary files differnew file mode 100644 index 000000000000..51ecb5c75c6c --- /dev/null +++ b/desktop/test/deployment/simple_license/Locale1.oxt diff --git a/desktop/test/deployment/simple_license/Locale2.oxt b/desktop/test/deployment/simple_license/Locale2.oxt Binary files differnew file mode 100644 index 000000000000..bb6b236a5d07 --- /dev/null +++ b/desktop/test/deployment/simple_license/Locale2.oxt diff --git a/desktop/test/deployment/simple_license/Locale3.oxt b/desktop/test/deployment/simple_license/Locale3.oxt Binary files differnew file mode 100644 index 000000000000..56bfedc24025 --- /dev/null +++ b/desktop/test/deployment/simple_license/Locale3.oxt diff --git a/desktop/test/deployment/simple_license/Locale4.oxt b/desktop/test/deployment/simple_license/Locale4.oxt Binary files differnew file mode 100644 index 000000000000..9a465bc7cff3 --- /dev/null +++ b/desktop/test/deployment/simple_license/Locale4.oxt diff --git a/desktop/test/deployment/simple_license/Locale5.oxt b/desktop/test/deployment/simple_license/Locale5.oxt Binary files differnew file mode 100644 index 000000000000..ce16830c13fa --- /dev/null +++ b/desktop/test/deployment/simple_license/Locale5.oxt diff --git a/desktop/test/deployment/simple_license/Locale6.oxt b/desktop/test/deployment/simple_license/Locale6.oxt Binary files differnew file mode 100644 index 000000000000..770d32506ee3 --- /dev/null +++ b/desktop/test/deployment/simple_license/Locale6.oxt diff --git a/desktop/test/deployment/simple_license/LongLic.oxt b/desktop/test/deployment/simple_license/LongLic.oxt Binary files differnew file mode 100644 index 000000000000..a0a49daebacf --- /dev/null +++ b/desktop/test/deployment/simple_license/LongLic.oxt diff --git a/desktop/test/deployment/simple_license/MissingLic.oxt b/desktop/test/deployment/simple_license/MissingLic.oxt Binary files differnew file mode 100644 index 000000000000..04d58fd117a2 --- /dev/null +++ b/desktop/test/deployment/simple_license/MissingLic.oxt diff --git a/desktop/test/deployment/simple_license/MissingLicRef.oxt b/desktop/test/deployment/simple_license/MissingLicRef.oxt Binary files differnew file mode 100644 index 000000000000..01c9d19a2833 --- /dev/null +++ b/desktop/test/deployment/simple_license/MissingLicRef.oxt diff --git a/desktop/test/deployment/simple_license/NoDefLang.oxt b/desktop/test/deployment/simple_license/NoDefLang.oxt Binary files differnew file mode 100644 index 000000000000..3eadd5254ccc --- /dev/null +++ b/desktop/test/deployment/simple_license/NoDefLang.oxt diff --git a/desktop/test/deployment/simple_license/NoDesc.oxt b/desktop/test/deployment/simple_license/NoDesc.oxt Binary files differnew file mode 100644 index 000000000000..ac83dac97eba --- /dev/null +++ b/desktop/test/deployment/simple_license/NoDesc.oxt diff --git a/desktop/test/deployment/simple_license/NoLang.oxt b/desktop/test/deployment/simple_license/NoLang.oxt Binary files differnew file mode 100644 index 000000000000..a4f3dd43a079 --- /dev/null +++ b/desktop/test/deployment/simple_license/NoLang.oxt diff --git a/desktop/test/deployment/simple_license/Prefix.oxt b/desktop/test/deployment/simple_license/Prefix.oxt Binary files differnew file mode 100644 index 000000000000..3e09b8d804e9 --- /dev/null +++ b/desktop/test/deployment/simple_license/Prefix.oxt diff --git a/desktop/test/deployment/simple_license/ShortLicense.oxt b/desktop/test/deployment/simple_license/ShortLicense.oxt Binary files differnew file mode 100644 index 000000000000..efcfdc98e125 --- /dev/null +++ b/desktop/test/deployment/simple_license/ShortLicense.oxt diff --git a/desktop/test/deployment/simple_license/ShortLicenseShared.oxt b/desktop/test/deployment/simple_license/ShortLicenseShared.oxt Binary files differnew file mode 100644 index 000000000000..775559a2c7a3 --- /dev/null +++ b/desktop/test/deployment/simple_license/ShortLicenseShared.oxt diff --git a/desktop/test/deployment/simple_license/suppress_license.oxt b/desktop/test/deployment/simple_license/suppress_license.oxt Binary files differnew file mode 100755 index 000000000000..2bacd6aa378b --- /dev/null +++ b/desktop/test/deployment/simple_license/suppress_license.oxt diff --git a/desktop/test/deployment/simple_license/tests_simple_license.odt b/desktop/test/deployment/simple_license/tests_simple_license.odt Binary files differnew file mode 100644 index 000000000000..b0c86e11c69b --- /dev/null +++ b/desktop/test/deployment/simple_license/tests_simple_license.odt diff --git a/desktop/test/deployment/update/changing_display_name/change1.oxt b/desktop/test/deployment/update/changing_display_name/change1.oxt Binary files differnew file mode 100644 index 000000000000..c919129ab6d7 --- /dev/null +++ b/desktop/test/deployment/update/changing_display_name/change1.oxt diff --git a/desktop/test/deployment/update/changing_display_name/change1_mod.oxt b/desktop/test/deployment/update/changing_display_name/change1_mod.oxt Binary files differnew file mode 100644 index 000000000000..5ab99d7bf224 --- /dev/null +++ b/desktop/test/deployment/update/changing_display_name/change1_mod.oxt diff --git a/desktop/test/deployment/update/changing_display_name/readme.txt b/desktop/test/deployment/update/changing_display_name/readme.txt new file mode 100644 index 000000000000..905f0be9a962 --- /dev/null +++ b/desktop/test/deployment/update/changing_display_name/readme.txt @@ -0,0 +1,13 @@ + +The default display name, if nothing is provided by the extension, is the file name. +The display name could be changed in different versions. There are three versions +of change1.oxt available: + +v1: no display name +v2: change1 de +v3: change1 de - changed display name - + +change1_mod.oxt is the same as change1.oxt version 1 except that is has a display name. +This situation should actually never arise, because the version should always be +changed when the extension is changed - and be it only the display name. + diff --git a/desktop/test/deployment/update/changing_display_name/update1/change1.oxt b/desktop/test/deployment/update/changing_display_name/update1/change1.oxt Binary files differnew file mode 100644 index 000000000000..ef034f94459f --- /dev/null +++ b/desktop/test/deployment/update/changing_display_name/update1/change1.oxt diff --git a/desktop/test/deployment/update/changing_display_name/update1/change1.update.xml b/desktop/test/deployment/update/changing_display_name/update1/change1.update.xml new file mode 100644 index 000000000000..29aee72fa122 --- /dev/null +++ b/desktop/test/deployment/update/changing_display_name/update1/change1.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice/framework/desktop/changing_display_name/change1" /> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/changing_display_name/update1/change1.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/changing_display_name/update2/change1.oxt b/desktop/test/deployment/update/changing_display_name/update2/change1.oxt Binary files differnew file mode 100644 index 000000000000..551f5a3f48c3 --- /dev/null +++ b/desktop/test/deployment/update/changing_display_name/update2/change1.oxt diff --git a/desktop/test/deployment/update/changing_display_name/update2/change1.update.xml b/desktop/test/deployment/update/changing_display_name/update2/change1.update.xml new file mode 100644 index 000000000000..1e2ee11e9f4e --- /dev/null +++ b/desktop/test/deployment/update/changing_display_name/update2/change1.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice/framework/desktop/changing_display_name/change1" /> + <version value="3.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/changing_display_name/update2/change1.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/default_url/default1.oxt b/desktop/test/deployment/update/default_url/default1.oxt Binary files differnew file mode 100644 index 000000000000..3fa8c9f08f8d --- /dev/null +++ b/desktop/test/deployment/update/default_url/default1.oxt diff --git a/desktop/test/deployment/update/default_url/default2.oxt b/desktop/test/deployment/update/default_url/default2.oxt Binary files differnew file mode 100644 index 000000000000..d54ce88c51d6 --- /dev/null +++ b/desktop/test/deployment/update/default_url/default2.oxt diff --git a/desktop/test/deployment/update/default_url/readme.txt b/desktop/test/deployment/update/default_url/readme.txt new file mode 100644 index 000000000000..4ae7936bfc18 --- /dev/null +++ b/desktop/test/deployment/update/default_url/readme.txt @@ -0,0 +1,9 @@ +Tests for using the default URL for update information. This URL is currently contained in +the version.ini (ExtensionUpdateURL) and is used to obtain update information for extensions which do not provide +an URL themselves. + +The extensions default1.oxt and default2.oxt do not have a URL for update information. + +To test this one has to put this entry into the version.ini: + +ExtensionUpdateURL=http://extensions.openoffice.org/testarea/desktop/default_url/update/feed1.xml diff --git a/desktop/test/deployment/update/default_url/update/default1.oxt b/desktop/test/deployment/update/default_url/update/default1.oxt Binary files differnew file mode 100644 index 000000000000..198395c76e5d --- /dev/null +++ b/desktop/test/deployment/update/default_url/update/default1.oxt diff --git a/desktop/test/deployment/update/default_url/update/default1.update.xml b/desktop/test/deployment/update/default_url/update/default1.update.xml new file mode 100644 index 000000000000..0351d23e68d8 --- /dev/null +++ b/desktop/test/deployment/update/default_url/update/default1.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.default1.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/default_url/update/default1.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/default_url/update/default2.oxt b/desktop/test/deployment/update/default_url/update/default2.oxt Binary files differnew file mode 100644 index 000000000000..198395c76e5d --- /dev/null +++ b/desktop/test/deployment/update/default_url/update/default2.oxt diff --git a/desktop/test/deployment/update/default_url/update/default2.update.xml b/desktop/test/deployment/update/default_url/update/default2.update.xml new file mode 100644 index 000000000000..8bf00b2e2227 --- /dev/null +++ b/desktop/test/deployment/update/default_url/update/default2.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.default2.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/default_url/update/default2.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/default_url/update/feed1.xml b/desktop/test/deployment/update/default_url/update/feed1.xml new file mode 100644 index 000000000000..b504b7b4b00c --- /dev/null +++ b/desktop/test/deployment/update/default_url/update/feed1.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"> + + <title>OpenOffice.org Update Feed</title> + <link rel="alternate" type="text/html" href="http://update.services.openoffice.org/ooo/snapshot.html"/> + <updated>2006-11-06T18:30:02Z</updated> + <author> + <name>The OpenOffice.org Project</name> + <uri>http://openoffice.org</uri> + <email>updatefeed@openoffice.org</email> + </author> + <id>urn:uuid:a4ccd383-1dd1-11b2-a95c-0003ba566e9d</id> + <entry> + <title>default1.oxt version 2.0 available</title> + <link rel="alternate" type="text/html" + href="http://extensions.openoffice.org"/> + <id>urn:uuid:a4ccd383-1dd1-11b2-a95c-0003ba566e9f</id> + <category term="org.openoffice.legacy.default1.oxt" label="default1.oxt" /> + <updated>2006-11-06T18:30:02Z</updated> + <summary>Click here to go to the download page.</summary> + <content type="application/xml" src="http://extensions.openoffice.org/testarea/desktop/default_url/update/default1.update.xml" /> + </entry> + <entry> + <title>default2.oxt version 2.0 available</title> + <link rel="alternate" type="text/html" + href="http://extensions.openoffice.org"/> + <id>urn:uuid:a4ccd383-1dd1-11b2-a95c-0003ba566eaf</id> + <category term="org.openoffice.legacy.default2.oxt" label="default2.oxt" /> + <updated>2006-11-06T18:30:02Z</updated> + <summary>Click here to go to the download page.</summary> + <content type="application/xml" src="http://extensions.openoffice.org/testarea/desktop/default_url/update/default2.update.xml" /> + </entry> +</feed> diff --git a/desktop/test/deployment/update/defect/fail1.oxt b/desktop/test/deployment/update/defect/fail1.oxt Binary files differnew file mode 100644 index 000000000000..5b5cdba2cdbc --- /dev/null +++ b/desktop/test/deployment/update/defect/fail1.oxt diff --git a/desktop/test/deployment/update/defect/fail2.oxt b/desktop/test/deployment/update/defect/fail2.oxt Binary files differnew file mode 100644 index 000000000000..61b0306f0947 --- /dev/null +++ b/desktop/test/deployment/update/defect/fail2.oxt diff --git a/desktop/test/deployment/update/defect/fail3.oxt b/desktop/test/deployment/update/defect/fail3.oxt Binary files differnew file mode 100644 index 000000000000..9da26d48a636 --- /dev/null +++ b/desktop/test/deployment/update/defect/fail3.oxt diff --git a/desktop/test/deployment/update/defect/fail4.oxt b/desktop/test/deployment/update/defect/fail4.oxt Binary files differnew file mode 100644 index 000000000000..66b87caa14b7 --- /dev/null +++ b/desktop/test/deployment/update/defect/fail4.oxt diff --git a/desktop/test/deployment/update/defect/info1.oxt b/desktop/test/deployment/update/defect/info1.oxt Binary files differnew file mode 100644 index 000000000000..9ffd373fa11f --- /dev/null +++ b/desktop/test/deployment/update/defect/info1.oxt diff --git a/desktop/test/deployment/update/defect/info2.oxt b/desktop/test/deployment/update/defect/info2.oxt Binary files differnew file mode 100644 index 000000000000..229a52c3bc69 --- /dev/null +++ b/desktop/test/deployment/update/defect/info2.oxt diff --git a/desktop/test/deployment/update/defect/info3.oxt b/desktop/test/deployment/update/defect/info3.oxt Binary files differnew file mode 100644 index 000000000000..b702f3e00417 --- /dev/null +++ b/desktop/test/deployment/update/defect/info3.oxt diff --git a/desktop/test/deployment/update/defect/readme.txt b/desktop/test/deployment/update/defect/readme.txt new file mode 100644 index 000000000000..5e8322f5cf26 --- /dev/null +++ b/desktop/test/deployment/update/defect/readme.txt @@ -0,0 +1,15 @@ +The updates, that is the newer versions, are defect. However, only fail2.oxt fails to install. The other extensions can be installed directly and through an update.
+
+fail1.oxt: in version2 the contained t.rdb was renamed so that it is not found (t.rdb is referenced in the manifest.xml).
+
+fail2.oxt: in version 2 the contained t.rdb is corrupted. It is a renamed .txt file which contains some text.
+
+fail3.oxt: in version 2 the contained t.rdb is corrupted. It is a renamed .txt file which does not contain any text.
+
+fail4.oxt: the version 2 references by fail4.update.xml is empty.
+
+info1.oxt: The update information file has length null.
+
+info2.oxt: The update information does not contain xml.
+
+info3.oxt: The update information contain an error: the tag update information contains two opening brackets (<<update-information>)
\ No newline at end of file diff --git a/desktop/test/deployment/update/defect/update/fail1.oxt b/desktop/test/deployment/update/defect/update/fail1.oxt Binary files differnew file mode 100644 index 000000000000..dbcc7cd73eb9 --- /dev/null +++ b/desktop/test/deployment/update/defect/update/fail1.oxt diff --git a/desktop/test/deployment/update/defect/update/fail1.update.xml b/desktop/test/deployment/update/defect/update/fail1.update.xml new file mode 100644 index 000000000000..69cb73c4f1c1 --- /dev/null +++ b/desktop/test/deployment/update/defect/update/fail1.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.fail1.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/defect/update/fail1.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/defect/update/fail2.oxt b/desktop/test/deployment/update/defect/update/fail2.oxt Binary files differnew file mode 100644 index 000000000000..6df0c3cf9977 --- /dev/null +++ b/desktop/test/deployment/update/defect/update/fail2.oxt diff --git a/desktop/test/deployment/update/defect/update/fail2.update.xml b/desktop/test/deployment/update/defect/update/fail2.update.xml new file mode 100644 index 000000000000..8b235acd9bbc --- /dev/null +++ b/desktop/test/deployment/update/defect/update/fail2.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.fail2.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/defect/update/fail2.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/defect/update/fail3.oxt b/desktop/test/deployment/update/defect/update/fail3.oxt Binary files differnew file mode 100644 index 000000000000..2d340f41443b --- /dev/null +++ b/desktop/test/deployment/update/defect/update/fail3.oxt diff --git a/desktop/test/deployment/update/defect/update/fail3.update.xml b/desktop/test/deployment/update/defect/update/fail3.update.xml new file mode 100644 index 000000000000..60a29992102c --- /dev/null +++ b/desktop/test/deployment/update/defect/update/fail3.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.fail3.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/defect/update/fail3.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/defect/update/fail4.oxt b/desktop/test/deployment/update/defect/update/fail4.oxt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/desktop/test/deployment/update/defect/update/fail4.oxt diff --git a/desktop/test/deployment/update/defect/update/fail4.update.xml b/desktop/test/deployment/update/defect/update/fail4.update.xml new file mode 100644 index 000000000000..81775a72573d --- /dev/null +++ b/desktop/test/deployment/update/defect/update/fail4.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.fail4.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/defect/update/fail4.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/defect/update/info1.update.xml b/desktop/test/deployment/update/defect/update/info1.update.xml new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/desktop/test/deployment/update/defect/update/info1.update.xml diff --git a/desktop/test/deployment/update/defect/update/info2.update.xml b/desktop/test/deployment/update/defect/update/info2.update.xml new file mode 100644 index 000000000000..1446608022f0 --- /dev/null +++ b/desktop/test/deployment/update/defect/update/info2.update.xml @@ -0,0 +1 @@ +This is a invalid update information file!!! diff --git a/desktop/test/deployment/update/defect/update/info3.oxt b/desktop/test/deployment/update/defect/update/info3.oxt Binary files differnew file mode 100644 index 000000000000..60debac57c4e --- /dev/null +++ b/desktop/test/deployment/update/defect/update/info3.oxt diff --git a/desktop/test/deployment/update/defect/update/info3.update.xml b/desktop/test/deployment/update/defect/update/info3.update.xml new file mode 100644 index 000000000000..35106ea29a8f --- /dev/null +++ b/desktop/test/deployment/update/defect/update/info3.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.info3.oxt"/> + <version value="2.0" /> + <<update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/defect/update/info3.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/dependencies/publisher_en.html b/desktop/test/deployment/update/dependencies/publisher_en.html new file mode 100644 index 000000000000..37dbc2b9d6ce --- /dev/null +++ b/desktop/test/deployment/update/dependencies/publisher_en.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My Extension Company</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/dependencies/readme.txt b/desktop/test/deployment/update/dependencies/readme.txt new file mode 100644 index 000000000000..3c71da24884d --- /dev/null +++ b/desktop/test/deployment/update/dependencies/readme.txt @@ -0,0 +1,32 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +update-dependencies.oxt is an extension that itself has no dependencies, but +whose update has unsatisfied dependencies (and also uses update-website). + +The update information contain also publisher and release notes information, +which should be displayed in the update dialog. diff --git a/desktop/test/deployment/update/dependencies/release-notes_en.html b/desktop/test/deployment/update/dependencies/release-notes_en.html new file mode 100644 index 000000000000..0971f78d1484 --- /dev/null +++ b/desktop/test/deployment/update/dependencies/release-notes_en.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/dependencies/update-dependencies.oxt b/desktop/test/deployment/update/dependencies/update-dependencies.oxt Binary files differnew file mode 100644 index 000000000000..513b25d20763 --- /dev/null +++ b/desktop/test/deployment/update/dependencies/update-dependencies.oxt diff --git a/desktop/test/deployment/update/dependencies/update/update-dependencies.update.xml b/desktop/test/deployment/update/dependencies/update/update-dependencies.update.xml new file mode 100644 index 000000000000..51a631a8ebd2 --- /dev/null +++ b/desktop/test/deployment/update/dependencies/update/update-dependencies.update.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--*********************************************************************** + + 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. + + ************************************************************************ --> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:d="http://openoffice.org/extensions/description/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice/framework/desktop/test/deployment/update/dependencies/update-dependencies.oxt"/> + <version value="2.0"/> + <dependencies> + <dependency d:name="& < > ' " > ' tab	. crlf
. em-dash—. line-separator
. paragraph-separator
. xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"/> + <dependency d:name="Dependency 1"/> + <dependency d:name="Dependency 2"/> + <dependency d:name="Dependency 3"/> + <dependency d:name="Dependency 4"/> + <dependency d:name="Dependency 5"/> + <dependency d:name="Dependency 6"/> + <dependency d:name="Dependency 7"/> + <dependency d:name="Dependency 8"/> + <dependency d:name="Dependency 9"/> + <dependency d:name="Dependency 10"/> + <dependency d:name="Dependency 11"/> + <dependency d:name="Dependency 12"/> + <dependency d:name="Dependency 13"/> + <dependency d:name="Dependency 14"/> + <dependency d:name="Dependency 15"/> + <dependency d:name="Dependency 16"/> + <dependency d:name="Dependency 17"/> + <dependency d:name="Dependency 18"/> + <dependency d:name="Dependency 19"/> + <dependency d:name="Dependency 20"/> + <dependency/> + <d:OpenOffice.org-minimal-version value="2.1" d:name="OpenOffice.org 2.1"/> + </dependencies> + <update-website> + <src xlink:href="http://nowhere.openoffice.org"/> + <src xlink:href="http://nowhere.openoffice.org/2"/> + </update-website> + + <publisher> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/dependencies/publisher_en.html" lang="en">My Extension Company</name> + </publisher> + + <release-notes> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/dependencies/release-notes_en.html" lang="en" /> + </release-notes> + +</description> diff --git a/desktop/test/deployment/update/license/lic1.oxt b/desktop/test/deployment/update/license/lic1.oxt Binary files differnew file mode 100644 index 000000000000..43bfe3b77b2d --- /dev/null +++ b/desktop/test/deployment/update/license/lic1.oxt diff --git a/desktop/test/deployment/update/license/lic2.oxt b/desktop/test/deployment/update/license/lic2.oxt Binary files differnew file mode 100644 index 000000000000..266a45e9a857 --- /dev/null +++ b/desktop/test/deployment/update/license/lic2.oxt diff --git a/desktop/test/deployment/update/license/lic3.oxt b/desktop/test/deployment/update/license/lic3.oxt Binary files differnew file mode 100644 index 000000000000..3f1b98960043 --- /dev/null +++ b/desktop/test/deployment/update/license/lic3.oxt diff --git a/desktop/test/deployment/update/license/readme.txt b/desktop/test/deployment/update/license/readme.txt new file mode 100644 index 000000000000..03123d2c5812 --- /dev/null +++ b/desktop/test/deployment/update/license/readme.txt @@ -0,0 +1,9 @@ +The extensions contain a license which is displayed during installaion. If a the license is displayed during a update can be determined by the attribute +/description/registration/simple-license/@suppress-on-update + +The default value is false, which means that the attribute is not set, then the license is displayed during an update. + +lic1.oxt: attribute not set +lic2.oxt: attribute set to false +lic3.oxt: attribute set to true + diff --git a/desktop/test/deployment/update/license/update/lic1.oxt b/desktop/test/deployment/update/license/update/lic1.oxt Binary files differnew file mode 100644 index 000000000000..cc91e1ff16fe --- /dev/null +++ b/desktop/test/deployment/update/license/update/lic1.oxt diff --git a/desktop/test/deployment/update/license/update/lic1.update.xml b/desktop/test/deployment/update/license/update/lic1.update.xml new file mode 100644 index 000000000000..6c6037590503 --- /dev/null +++ b/desktop/test/deployment/update/license/update/lic1.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.lic1.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/license/update/lic1.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/license/update/lic2.oxt b/desktop/test/deployment/update/license/update/lic2.oxt Binary files differnew file mode 100644 index 000000000000..351000792487 --- /dev/null +++ b/desktop/test/deployment/update/license/update/lic2.oxt diff --git a/desktop/test/deployment/update/license/update/lic2.update.xml b/desktop/test/deployment/update/license/update/lic2.update.xml new file mode 100644 index 000000000000..6e284e9deff2 --- /dev/null +++ b/desktop/test/deployment/update/license/update/lic2.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.lic2.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/license/update/lic2.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/license/update/lic3.oxt b/desktop/test/deployment/update/license/update/lic3.oxt Binary files differnew file mode 100644 index 000000000000..6ac6e0fd0fd1 --- /dev/null +++ b/desktop/test/deployment/update/license/update/lic3.oxt diff --git a/desktop/test/deployment/update/license/update/lic3.update.xml b/desktop/test/deployment/update/license/update/lic3.update.xml new file mode 100644 index 000000000000..b6f55bca2060 --- /dev/null +++ b/desktop/test/deployment/update/license/update/lic3.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.lic3.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/license/update/lic3.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/platform/all1.oxt b/desktop/test/deployment/update/platform/all1.oxt Binary files differnew file mode 100644 index 000000000000..ad9662a7c226 --- /dev/null +++ b/desktop/test/deployment/update/platform/all1.oxt diff --git a/desktop/test/deployment/update/platform/all2.oxt b/desktop/test/deployment/update/platform/all2.oxt Binary files differnew file mode 100644 index 000000000000..632d11b42938 --- /dev/null +++ b/desktop/test/deployment/update/platform/all2.oxt diff --git a/desktop/test/deployment/update/platform/all3.oxt b/desktop/test/deployment/update/platform/all3.oxt Binary files differnew file mode 100644 index 000000000000..ab781552a5aa --- /dev/null +++ b/desktop/test/deployment/update/platform/all3.oxt diff --git a/desktop/test/deployment/update/platform/freebsd_x86.oxt b/desktop/test/deployment/update/platform/freebsd_x86.oxt Binary files differnew file mode 100644 index 000000000000..338f5761deb1 --- /dev/null +++ b/desktop/test/deployment/update/platform/freebsd_x86.oxt diff --git a/desktop/test/deployment/update/platform/freebsd_x86_64.oxt b/desktop/test/deployment/update/platform/freebsd_x86_64.oxt Binary files differnew file mode 100644 index 000000000000..39fee6de1a77 --- /dev/null +++ b/desktop/test/deployment/update/platform/freebsd_x86_64.oxt diff --git a/desktop/test/deployment/update/platform/invalid1.oxt b/desktop/test/deployment/update/platform/invalid1.oxt Binary files differnew file mode 100644 index 000000000000..13d709f438fc --- /dev/null +++ b/desktop/test/deployment/update/platform/invalid1.oxt diff --git a/desktop/test/deployment/update/platform/invalid2.oxt b/desktop/test/deployment/update/platform/invalid2.oxt Binary files differnew file mode 100644 index 000000000000..f14257191b81 --- /dev/null +++ b/desktop/test/deployment/update/platform/invalid2.oxt diff --git a/desktop/test/deployment/update/platform/invalid3.oxt b/desktop/test/deployment/update/platform/invalid3.oxt Binary files differnew file mode 100644 index 000000000000..cadffa4f2ac1 --- /dev/null +++ b/desktop/test/deployment/update/platform/invalid3.oxt diff --git a/desktop/test/deployment/update/platform/linux_arm_eabi.oxt b/desktop/test/deployment/update/platform/linux_arm_eabi.oxt Binary files differnew file mode 100644 index 000000000000..9c504e841b98 --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_arm_eabi.oxt diff --git a/desktop/test/deployment/update/platform/linux_arm_oabi.oxt b/desktop/test/deployment/update/platform/linux_arm_oabi.oxt Binary files differnew file mode 100644 index 000000000000..f2c987f645a7 --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_arm_oabi.oxt diff --git a/desktop/test/deployment/update/platform/linux_ia64.oxt b/desktop/test/deployment/update/platform/linux_ia64.oxt Binary files differnew file mode 100644 index 000000000000..f579a18ab90d --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_ia64.oxt diff --git a/desktop/test/deployment/update/platform/linux_mips_eb.oxt b/desktop/test/deployment/update/platform/linux_mips_eb.oxt Binary files differnew file mode 100644 index 000000000000..bf0bd942332b --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_mips_eb.oxt diff --git a/desktop/test/deployment/update/platform/linux_mips_el.oxt b/desktop/test/deployment/update/platform/linux_mips_el.oxt Binary files differnew file mode 100644 index 000000000000..6bd56446831b --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_mips_el.oxt diff --git a/desktop/test/deployment/update/platform/linux_powerpc.oxt b/desktop/test/deployment/update/platform/linux_powerpc.oxt Binary files differnew file mode 100644 index 000000000000..e301a3fb3ad1 --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_powerpc.oxt diff --git a/desktop/test/deployment/update/platform/linux_powerpc64.oxt b/desktop/test/deployment/update/platform/linux_powerpc64.oxt Binary files differnew file mode 100644 index 000000000000..e5f3ae063923 --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_powerpc64.oxt diff --git a/desktop/test/deployment/update/platform/linux_s390.oxt b/desktop/test/deployment/update/platform/linux_s390.oxt Binary files differnew file mode 100644 index 000000000000..199702ebf056 --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_s390.oxt diff --git a/desktop/test/deployment/update/platform/linux_s390x.oxt b/desktop/test/deployment/update/platform/linux_s390x.oxt Binary files differnew file mode 100644 index 000000000000..2ed250833fb1 --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_s390x.oxt diff --git a/desktop/test/deployment/update/platform/linux_sparc.oxt b/desktop/test/deployment/update/platform/linux_sparc.oxt Binary files differnew file mode 100644 index 000000000000..53dfc71e0c4e --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_sparc.oxt diff --git a/desktop/test/deployment/update/platform/linux_x86.oxt b/desktop/test/deployment/update/platform/linux_x86.oxt Binary files differnew file mode 100644 index 000000000000..8379539cad34 --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_x86.oxt diff --git a/desktop/test/deployment/update/platform/linux_x86_64.oxt b/desktop/test/deployment/update/platform/linux_x86_64.oxt Binary files differnew file mode 100644 index 000000000000..0fb18227522f --- /dev/null +++ b/desktop/test/deployment/update/platform/linux_x86_64.oxt diff --git a/desktop/test/deployment/update/platform/macosx_powerpc.oxt b/desktop/test/deployment/update/platform/macosx_powerpc.oxt Binary files differnew file mode 100644 index 000000000000..7c146347127a --- /dev/null +++ b/desktop/test/deployment/update/platform/macosx_powerpc.oxt diff --git a/desktop/test/deployment/update/platform/macosx_x86.oxt b/desktop/test/deployment/update/platform/macosx_x86.oxt Binary files differnew file mode 100644 index 000000000000..a20aadfefffd --- /dev/null +++ b/desktop/test/deployment/update/platform/macosx_x86.oxt diff --git a/desktop/test/deployment/update/platform/mul1.oxt b/desktop/test/deployment/update/platform/mul1.oxt Binary files differnew file mode 100644 index 000000000000..b3b555969bdf --- /dev/null +++ b/desktop/test/deployment/update/platform/mul1.oxt diff --git a/desktop/test/deployment/update/platform/os2_x86.oxt b/desktop/test/deployment/update/platform/os2_x86.oxt Binary files differnew file mode 100644 index 000000000000..1c7fd40bef9f --- /dev/null +++ b/desktop/test/deployment/update/platform/os2_x86.oxt diff --git a/desktop/test/deployment/update/platform/readme.txt b/desktop/test/deployment/update/platform/readme.txt new file mode 100644 index 000000000000..2ab102a27d3c --- /dev/null +++ b/desktop/test/deployment/update/platform/readme.txt @@ -0,0 +1,49 @@ +Extension which only support one platform +======================================================== + +freebsd_x86.oxt: freebsd_x86 +freebsd_x86_86.oxt: freebsd_x86_64 +linux_arm_eabi.oxt: linux_arm_eabi +linux_arm_oabi.oxt: linux_arm_oabi +linux_ia64.oxt: linux_ia64 +linux_mips_eb.oxt: linux_mips_eb +linux_mips_el.oxt: linux_mips_el +linux_powerpc64.oxt: linux_powerpc64 +linux_powerpc.oxt: linux_powerpc +linux_s390.oxt: linux_s390 +linux_s390x.oxt: linux_s390x +linux_sparc.oxt: linux_sparc +linux_x86.oxt: linux_x86 +linux_x86_64.oxt: linux_x86_64 +macos_powerpc.oxt: macos_powerpc +macos_x86.oxt: macos_x86 +solaris_sparc.oxt: solaris_sparc +solaris_x86.oxt: solaris_x86 +windows_x86.oxt: windows_x86 +os2_x86.oxt: os/2_x86 + +Extensions which support multiple platforms +======================================================= +mul1.oxt: windows_x86, linux_x86, solaris_x86 + + +All platforms +========================================================= +all1.oxt: all, The <platform> element is missing. Default is "all". + +all2.oxt: all, <platform value="all" /> + +all3.oxt: all, no description.xml + + + +Invalid platforms +========================================================= +The following extensions cannot be installed because the platform element +is not correct. We assume that no valid platform is defined. + +invalid1.oxt: <platform /> + +invalid2.oxt: <platform value=""/> + +invalid3.oxt: <platform value="," /> diff --git a/desktop/test/deployment/update/platform/solaris_sparc.oxt b/desktop/test/deployment/update/platform/solaris_sparc.oxt Binary files differnew file mode 100644 index 000000000000..a61f81f43942 --- /dev/null +++ b/desktop/test/deployment/update/platform/solaris_sparc.oxt diff --git a/desktop/test/deployment/update/platform/solaris_x86.oxt b/desktop/test/deployment/update/platform/solaris_x86.oxt Binary files differnew file mode 100644 index 000000000000..44d43df69184 --- /dev/null +++ b/desktop/test/deployment/update/platform/solaris_x86.oxt diff --git a/desktop/test/deployment/update/platform/windows_x86.oxt b/desktop/test/deployment/update/platform/windows_x86.oxt Binary files differnew file mode 100644 index 000000000000..c66a9b1418fa --- /dev/null +++ b/desktop/test/deployment/update/platform/windows_x86.oxt diff --git a/desktop/test/deployment/update/publisher/pub1.oxt b/desktop/test/deployment/update/publisher/pub1.oxt Binary files differnew file mode 100644 index 000000000000..c44ee9f3bc56 --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub1.oxt diff --git a/desktop/test/deployment/update/publisher/pub10.oxt b/desktop/test/deployment/update/publisher/pub10.oxt Binary files differnew file mode 100644 index 000000000000..1e7410ec1b2e --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub10.oxt diff --git a/desktop/test/deployment/update/publisher/pub11.oxt b/desktop/test/deployment/update/publisher/pub11.oxt Binary files differnew file mode 100644 index 000000000000..ef7fbca5e63a --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub11.oxt diff --git a/desktop/test/deployment/update/publisher/pub2.oxt b/desktop/test/deployment/update/publisher/pub2.oxt Binary files differnew file mode 100644 index 000000000000..438bcae830a3 --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub2.oxt diff --git a/desktop/test/deployment/update/publisher/pub3.oxt b/desktop/test/deployment/update/publisher/pub3.oxt Binary files differnew file mode 100644 index 000000000000..62fd69f5595a --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub3.oxt diff --git a/desktop/test/deployment/update/publisher/pub4.oxt b/desktop/test/deployment/update/publisher/pub4.oxt Binary files differnew file mode 100644 index 000000000000..4f6224f780cd --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub4.oxt diff --git a/desktop/test/deployment/update/publisher/pub5.oxt b/desktop/test/deployment/update/publisher/pub5.oxt Binary files differnew file mode 100644 index 000000000000..1774e6cd35c3 --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub5.oxt diff --git a/desktop/test/deployment/update/publisher/pub6.oxt b/desktop/test/deployment/update/publisher/pub6.oxt Binary files differnew file mode 100644 index 000000000000..791a37f8e710 --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub6.oxt diff --git a/desktop/test/deployment/update/publisher/pub7.oxt b/desktop/test/deployment/update/publisher/pub7.oxt Binary files differnew file mode 100644 index 000000000000..96e96887d0b1 --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub7.oxt diff --git a/desktop/test/deployment/update/publisher/pub8.oxt b/desktop/test/deployment/update/publisher/pub8.oxt Binary files differnew file mode 100644 index 000000000000..dc9f0ce34d95 --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub8.oxt diff --git a/desktop/test/deployment/update/publisher/pub9.oxt b/desktop/test/deployment/update/publisher/pub9.oxt Binary files differnew file mode 100644 index 000000000000..5e8ba9ebc154 --- /dev/null +++ b/desktop/test/deployment/update/publisher/pub9.oxt diff --git a/desktop/test/deployment/update/publisher/publisher_de-DE-altmark.html b/desktop/test/deployment/update/publisher/publisher_de-DE-altmark.html new file mode 100644 index 000000000000..c770b914ad78 --- /dev/null +++ b/desktop/test/deployment/update/publisher/publisher_de-DE-altmark.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My OpenOffice en-DE-altmark</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/publisher/publisher_de-DE.html b/desktop/test/deployment/update/publisher/publisher_de-DE.html new file mode 100644 index 000000000000..b06ed7088f08 --- /dev/null +++ b/desktop/test/deployment/update/publisher/publisher_de-DE.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My OpenOffice de-DE</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/publisher/publisher_de.html b/desktop/test/deployment/update/publisher/publisher_de.html new file mode 100644 index 000000000000..4cba9f423d5b --- /dev/null +++ b/desktop/test/deployment/update/publisher/publisher_de.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My OpenOffice de</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/publisher/publisher_en-GB.html b/desktop/test/deployment/update/publisher/publisher_en-GB.html new file mode 100644 index 000000000000..c73cf6219b78 --- /dev/null +++ b/desktop/test/deployment/update/publisher/publisher_en-GB.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My OpenOffice en-GB</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/publisher/publisher_en-US-region1.html b/desktop/test/deployment/update/publisher/publisher_en-US-region1.html new file mode 100644 index 000000000000..68beac724894 --- /dev/null +++ b/desktop/test/deployment/update/publisher/publisher_en-US-region1.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My OpenOffice en-US-region1</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/publisher/publisher_en-US-region2.html b/desktop/test/deployment/update/publisher/publisher_en-US-region2.html new file mode 100644 index 000000000000..501adb659664 --- /dev/null +++ b/desktop/test/deployment/update/publisher/publisher_en-US-region2.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My OpenOffice en-US-region2</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/publisher/publisher_en-US.html b/desktop/test/deployment/update/publisher/publisher_en-US.html new file mode 100644 index 000000000000..fd2575150315 --- /dev/null +++ b/desktop/test/deployment/update/publisher/publisher_en-US.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My OpenOffice en-US</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/publisher/publisher_en-region3.html b/desktop/test/deployment/update/publisher/publisher_en-region3.html new file mode 100644 index 000000000000..b9fdc9d657b4 --- /dev/null +++ b/desktop/test/deployment/update/publisher/publisher_en-region3.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My OpenOffice en-region3</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/publisher/publisher_en.html b/desktop/test/deployment/update/publisher/publisher_en.html new file mode 100644 index 000000000000..416ab8124314 --- /dev/null +++ b/desktop/test/deployment/update/publisher/publisher_en.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>My OpenOffice en</H1> +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/publisher/readme.txt b/desktop/test/deployment/update/publisher/readme.txt new file mode 100644 index 000000000000..1a659d8e875d --- /dev/null +++ b/desktop/test/deployment/update/publisher/readme.txt @@ -0,0 +1,212 @@ +--The folder contains extensions which use in the description.xml the following: + +-The <publisher> element +-The <release-notes> element + +Both element contain localized child elements. + +The following table shows what localized item is used, when the Office the locale +en-US uses. + + +Localization: + +Installed office en-US + | publisher | release notes +============================================= +pub1.oxt | en-US | en-US +--------------------------------------------- +pub2.oxt | en-US-region1 | en-US-region1 +--------------------------------------------- +pub3.oxt | en | en +--------------------------------------------- +pub4.oxt | en-GB | en-GB +--------------------------------------------- +pub5.oxt | de | de + + +================================================================================ +pub6.oxt +================================================================================ +like pub1 but without release notes. + + +================================================================================ +pub7.oxt +================================================================================ +like pub1 but without publisher name. + +================================================================================ +pub8.oxt +================================================================================ +Need not be committed in extensions/www/testarea/desktop. + +pub8.oxt is intended for tests with extensions.services.openoffice.org. +It does not contain <update-information>. That is, the Extension Manager will obtain +the update information from the repository as feed: + +http://updateext.services.openoffice.org/ProductUpdateService/check.Update + +pub8.oxt provides <publisher> and <release-notes>. These information should be transferred +in the update feed and not those entered in the repository. + +Test +---- +Repository: + +-Create the new extension in the repository. +-Provide a company name and a URL to the company website. This setting should be ignored + when generating the udpate feed. Instead the publisher name from the extension is used. + Enter "Publisher Title" : some arbitrary company + "Publisher URL": any arbitrary URL but not: + http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US.html + +-Create a new release for the extension. Upload the version 2.0 (update/pub8.oxt). + Provide release notes. These release notes should later not be seen when clicking on + the release notes link. + + +Office: +-Install version 1.0 of the extension: + desktop/test/deployment/update/publisher/pub8.oxt + +-Run the update in the Extension Manager + + +Result: +The Update Dialog should show the publisher name as provided in the description.xml. For example, +when lang=en-US was selected: My OpenOffice en-US + +A release notes link is displayed with an URL to the release notes as provided in +the description.xml. For example, when lang=en-US was selected: +"http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US.html + + +================================================================================ +pub9.oxt +================================================================================ +Need not be committed in extensions/www/testarea/desktop. + +pub9.oxt is intended for tests with extensions.services.openoffice.org. +It does not contain <update-information>. That is, the Extension Manager will obtain +the update information from the repository as feed: + +http://updateext.services.openoffice.org/ProductUpdateService/check.Update + +pub9.oxt provides <publisher>. That means the update feed should +contain the <publisher> as provided by the extension and the release notes as entered +in the repository. + +Test +---- +Repository: + +-Create the new extension in the repository. +-Provide a company name and a URL to the company website. This setting should be ignored + when generating the udpate feed. Instead the publisher name from the extension is used. + Enter "Publisher Title" : some arbitrary company name + "Publisher URL": any arbitrary URL but not: + http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US.html + +-Create a new release for the extension. Upload the version 2.0 (update/pub9.oxt). + Provide release notes. These release notes should later be displayed when clicking on + the release notes link. + + +Office: +-Install version 1.0 of the extension: + desktop/test/deployment/update/publisher/pub9.oxt + +-Run the update in the Extension Manager + + +Result: +The Update Dialog should show the publisher name as provided in the description.xml. For example, +when lang=en-US was selected: My OpenOffice en-US + +A release notes link is displayed with an URL to the release notes as provided in the release notes +field on the edit page for the extension in the repository. + +================================================================================ +pub10.oxt +================================================================================ +Need not be committed in extensions/www/testarea/desktop. + +pub10.oxt is intended for tests with extensions.services.openoffice.org. +It does not contain <update-information>. That is, the Extension Manager will obtain +the update information from the repository as feed: + +http://updateext.services.openoffice.org/ProductUpdateService/check.Update + +pub10.oxt provides <release-notes>. That means the update feed should +contain the <release-notes> as provided by the extension and the publisher name/URLs as entered +in the repository. + +Test +---- +Repository: + +-Create the new extension in the repository. +-Provide a company name and a URL to the company website. They should then be in the udpate + feed. + +-Create a new release for the extension. Upload the version 2.0 (update/pub10.oxt). + Provide release notes. These release notes should NOT be displayed when clicking on + the release notes link. Instead the release notes provided by pub10.oxt should be displayed. + + +Office: +-Install version 1.0 of the extension: + desktop/test/deployment/update/publisher/pub10.oxt + +-Run the update in the Extension Manager + + +Result: +The Update Dialog should show the publisher name as provided in the repository. + +A release notes link is displayed with an URL to the release notes as provided in the +pub10.oxt. For example, when the locale of the office is en-US then this page will be +displayed: +For example, +when lang=en-US was selected: My OpenOffice en-US + +================================================================================ +pub11.oxt +================================================================================ +Need not be committed in extensions/www/testarea/desktop. + +pub11.oxt is intended for tests with extensions.services.openoffice.org. +It does not contain <update-information>. That is, the Extension Manager will obtain +the update information from the repository as feed: + +http://updateext.services.openoffice.org/ProductUpdateService/check.Update + +pub10.oxt neither provides <release-notes> nor <publisher>. That means the update feed should +contain these data as provided by the user on the repository web site. + +Test +---- +Repository: + +-Create the new extension in the repository. +-Provide a company name and a URL to the company website. They should then be in the udpate + feed. + +-Create a new release for the extension. Upload the version 2.0 (update/pub11.oxt). + Provide release notes. These release notes should be displayed when clicking on + the release notes link. + + +Office: +-Install version 1.0 of the extension: + desktop/test/deployment/update/publisher/pub11.oxt + +-Run the update in the Extension Manager + + +Result: +The Update Dialog should show the publisher name as provided in the repository. + +A release notes link is displayed which leads to the release notes kept in the repository. + diff --git a/desktop/test/deployment/update/publisher/release-notes_de-DE-altmark.html b/desktop/test/deployment/update/publisher/release-notes_de-DE-altmark.html new file mode 100644 index 000000000000..81b38a9f5b44 --- /dev/null +++ b/desktop/test/deployment/update/publisher/release-notes_de-DE-altmark.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes de-DE-altmark</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/publisher/release-notes_de-DE.html b/desktop/test/deployment/update/publisher/release-notes_de-DE.html new file mode 100644 index 000000000000..f8f0121f0215 --- /dev/null +++ b/desktop/test/deployment/update/publisher/release-notes_de-DE.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes de-DE</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/publisher/release-notes_de.html b/desktop/test/deployment/update/publisher/release-notes_de.html new file mode 100644 index 000000000000..a9e1dc3647eb --- /dev/null +++ b/desktop/test/deployment/update/publisher/release-notes_de.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes de</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/publisher/release-notes_en-GB.html b/desktop/test/deployment/update/publisher/release-notes_en-GB.html new file mode 100644 index 000000000000..ca72ec1b9c6e --- /dev/null +++ b/desktop/test/deployment/update/publisher/release-notes_en-GB.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes en-GB</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/publisher/release-notes_en-US-region1.html b/desktop/test/deployment/update/publisher/release-notes_en-US-region1.html new file mode 100644 index 000000000000..0e6f99ce4c35 --- /dev/null +++ b/desktop/test/deployment/update/publisher/release-notes_en-US-region1.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes en-US-region1</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/publisher/release-notes_en-US-region2.html b/desktop/test/deployment/update/publisher/release-notes_en-US-region2.html new file mode 100644 index 000000000000..597bca0ebeef --- /dev/null +++ b/desktop/test/deployment/update/publisher/release-notes_en-US-region2.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes en-US-region2</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/publisher/release-notes_en-US.html b/desktop/test/deployment/update/publisher/release-notes_en-US.html new file mode 100644 index 000000000000..7f9d73e338f8 --- /dev/null +++ b/desktop/test/deployment/update/publisher/release-notes_en-US.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes en-US</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/publisher/release-notes_en-region3.html b/desktop/test/deployment/update/publisher/release-notes_en-region3.html new file mode 100644 index 000000000000..5d62c7bcb4cf --- /dev/null +++ b/desktop/test/deployment/update/publisher/release-notes_en-region3.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes en-region3</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/publisher/release-notes_en.html b/desktop/test/deployment/update/publisher/release-notes_en.html new file mode 100644 index 000000000000..d02e4f3330ee --- /dev/null +++ b/desktop/test/deployment/update/publisher/release-notes_en.html @@ -0,0 +1,8 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Release Notes en</H1> +</BODY> +</HTML> diff --git a/desktop/test/deployment/update/publisher/update/pub1.oxt b/desktop/test/deployment/update/publisher/update/pub1.oxt Binary files differnew file mode 100644 index 000000000000..cd04a58d5585 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub1.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub1.update.xml b/desktop/test/deployment/update/publisher/update/pub1.update.xml new file mode 100644 index 000000000000..65ca88e5b73f --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub1.update.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/publisher/pub1"/> + + <publisher> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de.html" lang="de">My OpenOffice de</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en.html" lang="en">My OpenOffice en</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE.html" lang="de-DE">My OpenOffice de-DE</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE-altmark.html" lang="de-DE-altmark">My OpenOffice de-DE-altmark</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-GB.html" lang="en-GB">My OpenOffice en-GB</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US.html" lang="en-US">My OpenOffice en-US</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US-region1.html" lang="en-US-region1">My OpenOffice en-US-region1</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US-region2.html" lang="en-US-region2">My OpenOffice en-US-region2</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-region3.html" lang="en-region3">My OpenOffice en-region3</name> + </publisher> + + <release-notes> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en.html" lang="en" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US.html" lang="en-US" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US-region1.html" lang="en-US-region1" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US-region2.html" lang="en-US-region2" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-region3.html" lang="en-region3" /> + </release-notes> + + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/update/pub1.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/publisher/update/pub10.oxt b/desktop/test/deployment/update/publisher/update/pub10.oxt Binary files differnew file mode 100644 index 000000000000..501a843381a8 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub10.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub11.oxt b/desktop/test/deployment/update/publisher/update/pub11.oxt Binary files differnew file mode 100644 index 000000000000..692c0401f4a5 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub11.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub2.oxt b/desktop/test/deployment/update/publisher/update/pub2.oxt Binary files differnew file mode 100644 index 000000000000..2a0bd6c21fed --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub2.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub2.update.xml b/desktop/test/deployment/update/publisher/update/pub2.update.xml new file mode 100644 index 000000000000..35415fc87dcc --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub2.update.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/publisher/pub2"/> + + <publisher> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de.html" lang="de">My OpenOffice de</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en.html" lang="en">My OpenOffice en</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE.html" lang="de-DE">My OpenOffice de-DE</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE-altmark.html" lang="de-DE-altmark">My OpenOffice de-DE-altmark</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-GB.html" lang="en-GB">My OpenOffice en-GB</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US-region1.html" lang="en-US-region1">My OpenOffice en-US-region1</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US-region2.html" lang="en-US-region2">My OpenOffice en-US-region2</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-region3.html" lang="en-region3">My OpenOffice en-region3</name> + </publisher> + + <release-notes> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en.html" lang="en" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US-region1.html" lang="en-US-region1" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US-region2.html" lang="en-US-region2" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-region3.html" lang="en-region3" /> + </release-notes> + + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/update/pub2.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/publisher/update/pub3.oxt b/desktop/test/deployment/update/publisher/update/pub3.oxt Binary files differnew file mode 100644 index 000000000000..60675fc4d21e --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub3.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub3.update.xml b/desktop/test/deployment/update/publisher/update/pub3.update.xml new file mode 100644 index 000000000000..f15a4c525ae3 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub3.update.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/publisher/pub3"/> + + <publisher> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de.html" lang="de">My OpenOffice de</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en.html" lang="en">My OpenOffice en</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE.html" lang="de-DE">My OpenOffice de-DE</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE-altmark.html" lang="de-DE-altmark">My OpenOffice de-DE-altmark</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-GB.html" lang="en-GB">My OpenOffice en-GB</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-region3.html" lang="en-region3">My OpenOffice en-region3</name> + </publisher> + + <release-notes> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en.html" lang="en" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-region3.html" lang="en-region3" /> + </release-notes> + + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/update/pub3.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/publisher/update/pub4.oxt b/desktop/test/deployment/update/publisher/update/pub4.oxt Binary files differnew file mode 100644 index 000000000000..19f7b7991bd4 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub4.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub4.update.xml b/desktop/test/deployment/update/publisher/update/pub4.update.xml new file mode 100644 index 000000000000..9c46b6eb3d6a --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub4.update.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/publisher/pub4"/> + + <publisher> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de.html" lang="de">My OpenOffice de</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE.html" lang="de-DE">My OpenOffice de-DE</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE-altmark.html" lang="de-DE-altmark">My OpenOffice de-DE-altmark</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-GB.html" lang="en-GB">My OpenOffice en-GB</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-region3.html" lang="en-region3">My OpenOffice en-region3</name> + </publisher> + + <release-notes> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-region3.html" lang="en-region3" /> + </release-notes> + + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/update/pub4.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/publisher/update/pub5.oxt b/desktop/test/deployment/update/publisher/update/pub5.oxt Binary files differnew file mode 100644 index 000000000000..afc632d570f1 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub5.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub5.update.xml b/desktop/test/deployment/update/publisher/update/pub5.update.xml new file mode 100644 index 000000000000..dd47e95403a0 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub5.update.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/publisher/pub5"/> + + <publisher> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de.html" lang="de">My OpenOffice de</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE.html" lang="de-DE">My OpenOffice de-DE</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE-altmark.html" lang="de-DE-altmark">My OpenOffice de-DE-altmark</name> + </publisher> + + <release-notes> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE-altmark.html" lang="de-DE-altmark" /> + </release-notes> + + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/update/pub5.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/publisher/update/pub6.oxt b/desktop/test/deployment/update/publisher/update/pub6.oxt Binary files differnew file mode 100644 index 000000000000..a68b445b8a1a --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub6.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub6.update.xml b/desktop/test/deployment/update/publisher/update/pub6.update.xml new file mode 100644 index 000000000000..5d4adc7a1607 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub6.update.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/publisher/pub6"/> + + <publisher> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de.html" lang="de">My OpenOffice de</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en.html" lang="en">My OpenOffice en</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE.html" lang="de-DE">My OpenOffice de-DE</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE-altmark.html" lang="de-DE-altmark">My OpenOffice de-DE-altmark</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-GB.html" lang="en-GB">My OpenOffice en-GB</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US.html" lang="en-US">My OpenOffice en-US</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US-region1.html" lang="en-US-region1">My OpenOffice en-US-region1</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US-region2.html" lang="en-US-region2">My OpenOffice en-US-region2</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-region3.html" lang="en-region3">My OpenOffice en-region3</name> + </publisher> + + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/update/pub6.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/publisher/update/pub7.oxt b/desktop/test/deployment/update/publisher/update/pub7.oxt Binary files differnew file mode 100644 index 000000000000..1b4bee0442bb --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub7.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub7.update.xml b/desktop/test/deployment/update/publisher/update/pub7.update.xml new file mode 100644 index 000000000000..cf61bc092d36 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub7.update.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/publisher/pub7"/> + + <release-notes> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en.html" lang="en" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US.html" lang="en-US" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US-region1.html" lang="en-US-region1" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US-region2.html" lang="en-US-region2" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-region3.html" lang="en-region3" /> + </release-notes> + + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/update/pub7.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/publisher/update/pub8.oxt b/desktop/test/deployment/update/publisher/update/pub8.oxt Binary files differnew file mode 100644 index 000000000000..5688ab9d24f5 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub8.oxt diff --git a/desktop/test/deployment/update/publisher/update/pub9.oxt b/desktop/test/deployment/update/publisher/update/pub9.oxt Binary files differnew file mode 100644 index 000000000000..752cfbbcf0b0 --- /dev/null +++ b/desktop/test/deployment/update/publisher/update/pub9.oxt diff --git a/desktop/test/deployment/update/readme.txt b/desktop/test/deployment/update/readme.txt new file mode 100644 index 000000000000..b3fd9126cae3 --- /dev/null +++ b/desktop/test/deployment/update/readme.txt @@ -0,0 +1,68 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + + +The extensions in the subdirectories of the update folder are used for +testing the online update feature of extensions. The folder such as +simple, +license, +defect, etc. contain extensions which can be installed in OOo. The +corresponding update information file and the update are located on +the extensions.openoffice.org website (cvs: extensions/www/testarea). For example: + +desktop/test/deployment/update/simple/plain1.oxt + +is version 1 of this extension and it references + +http://extensions.openoffice.org/testarea/desktop/simple/update/plain1.update.xml + +which in turn references version 2 at + +http://extensions.openoffice.org/testarea/desktop/simple/update/plain1.oxt + + +To have all in one place the update information file and the update are also contained +in the desktop project. They are in the update subfolder of the different test folders. +For example + +.../update/simple/update +.../update/license/update +.../update/updatefeed/udpate + + +The different test folders for the update are also commited in project extensions/www +so that the files can be obtain via an URL. The structure and the contents is about the +same as the content +of desktop/test/deployment/udpate +For example in + +extensions/www/testarea/desktop + +are the subfolder defect, simple, updatefeed, wrong_url, etc. +they contain the extensions which are installed directly by the Extension Manager. +These folders contain also the update subfolder which contains the update information +and the actual updates. diff --git a/desktop/test/deployment/update/simple/plain1.oxt b/desktop/test/deployment/update/simple/plain1.oxt Binary files differnew file mode 100644 index 000000000000..6256f99d5e9c --- /dev/null +++ b/desktop/test/deployment/update/simple/plain1.oxt diff --git a/desktop/test/deployment/update/simple/plain2.oxt b/desktop/test/deployment/update/simple/plain2.oxt Binary files differnew file mode 100644 index 000000000000..03249c27774c --- /dev/null +++ b/desktop/test/deployment/update/simple/plain2.oxt diff --git a/desktop/test/deployment/update/simple/plain3.oxt b/desktop/test/deployment/update/simple/plain3.oxt Binary files differnew file mode 100644 index 000000000000..64838932d1ae --- /dev/null +++ b/desktop/test/deployment/update/simple/plain3.oxt diff --git a/desktop/test/deployment/update/simple/readme.txt b/desktop/test/deployment/update/simple/readme.txt new file mode 100644 index 000000000000..34ad6bedabf9 --- /dev/null +++ b/desktop/test/deployment/update/simple/readme.txt @@ -0,0 +1,31 @@ +The folder contains only simple extension. That is, they only contain +- META-INF +-t.rdb +-description.xml + +The description.xml contains a version, a display name, and one URL to the update data + +For example: + + +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/description/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="1.0" /> + + <display-name> + <name lang="de">plain1 de</name> + </display-name> + + <update-information> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/simple/plain1.update.xml" /> + </update-information> +</description> + +There is only one language as display name available, which will therefore always be displayed. + +The update information which is referenced in the update-information and the update is committed in the extensions/www project. To modify them get the project: + +cvs co extensions/wwww + +the files can be found under extensions/www/testarea/desktop diff --git a/desktop/test/deployment/update/simple/update/plain1.oxt b/desktop/test/deployment/update/simple/update/plain1.oxt Binary files differnew file mode 100644 index 000000000000..d73362e873bc --- /dev/null +++ b/desktop/test/deployment/update/simple/update/plain1.oxt diff --git a/desktop/test/deployment/update/simple/update/plain1.update.xml b/desktop/test/deployment/update/simple/update/plain1.update.xml new file mode 100644 index 000000000000..5ee57aacb854 --- /dev/null +++ b/desktop/test/deployment/update/simple/update/plain1.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.plain1.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/simple/update/plain1.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/simple/update/plain2.oxt b/desktop/test/deployment/update/simple/update/plain2.oxt Binary files differnew file mode 100644 index 000000000000..3dc02aa97aa4 --- /dev/null +++ b/desktop/test/deployment/update/simple/update/plain2.oxt diff --git a/desktop/test/deployment/update/simple/update/plain2.update.xml b/desktop/test/deployment/update/simple/update/plain2.update.xml new file mode 100644 index 000000000000..e572908df691 --- /dev/null +++ b/desktop/test/deployment/update/simple/update/plain2.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.plain2.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/simple/update/plain2.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/simple/update/plain3.oxt b/desktop/test/deployment/update/simple/update/plain3.oxt Binary files differnew file mode 100644 index 000000000000..575152403bfe --- /dev/null +++ b/desktop/test/deployment/update/simple/update/plain3.oxt diff --git a/desktop/test/deployment/update/simple/update/plain3.update.xml b/desktop/test/deployment/update/simple/update/plain3.update.xml new file mode 100644 index 000000000000..038bebef021c --- /dev/null +++ b/desktop/test/deployment/update/simple/update/plain3.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.plain3.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/simple/update/plain3.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/updatefeed/feed1.oxt b/desktop/test/deployment/update/updatefeed/feed1.oxt Binary files differnew file mode 100644 index 000000000000..b1b11ecceabb --- /dev/null +++ b/desktop/test/deployment/update/updatefeed/feed1.oxt diff --git a/desktop/test/deployment/update/updatefeed/feed2.oxt b/desktop/test/deployment/update/updatefeed/feed2.oxt Binary files differnew file mode 100644 index 000000000000..47dca1676c6a --- /dev/null +++ b/desktop/test/deployment/update/updatefeed/feed2.oxt diff --git a/desktop/test/deployment/update/updatefeed/update/feed1.oxt b/desktop/test/deployment/update/updatefeed/update/feed1.oxt Binary files differnew file mode 100644 index 000000000000..82bb9665ae3d --- /dev/null +++ b/desktop/test/deployment/update/updatefeed/update/feed1.oxt diff --git a/desktop/test/deployment/update/updatefeed/update/feed1.update.xml b/desktop/test/deployment/update/updatefeed/update/feed1.update.xml new file mode 100644 index 000000000000..ebf421dbfd03 --- /dev/null +++ b/desktop/test/deployment/update/updatefeed/update/feed1.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.feed1.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/updatefeed/update/feed1.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/updatefeed/update/feed1.xml b/desktop/test/deployment/update/updatefeed/update/feed1.xml new file mode 100644 index 000000000000..1c31851d8cfd --- /dev/null +++ b/desktop/test/deployment/update/updatefeed/update/feed1.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"> + + <title>OpenOffice.org Update Feed</title> + <link rel="alternate" type="text/html" href="http://update.services.openoffice.org/ooo/snapshot.html"/> + <updated>2006-11-06T18:30:02Z</updated> + <author> + <name>The OpenOffice.org Project</name> + <uri>http://openoffice.org</uri> + <email>updatefeed@openoffice.org</email> + </author> + <id>urn:uuid:a4ccd383-1dd1-11b2-a95c-0003ba566e9d</id> + <entry> + <title>feed1.oxt version 2.0 available</title> + <link rel="alternate" type="text/html" + href="http://extensions.openoffice.org"/> + <id>urn:uuid:a4ccd383-1dd1-11b2-a95c-0003ba566e9f</id> + <category term="org.openoffice.legacy.feed1.oxt" label="feed1.oxt" /> + <updated>2006-11-06T18:30:02Z</updated> + <summary>Click here to go to the download page.</summary> + <content type="application/xml" src="http://extensions.openoffice.org/testarea/desktop/updatefeed/update/feed1.update.xml" /> + </entry> + <entry> + <title>feed2.oxt version 2.0 available</title> + <link rel="alternate" type="text/html" + href="http://extensions.openoffice.org"/> + <id>urn:uuid:a4ccd383-1dd1-11b2-a95c-0003ba566eaf</id> + <category term="org.openoffice.legacy.feed2.oxt" label="feed2.oxt" /> + <updated>2006-11-06T18:30:02Z</updated> + <summary>Click here to go to the download page.</summary> + <content type="application/xml" src="http://extensions.openoffice.org/testarea/desktop/updatefeed/update/feed2.update.xml" /> + </entry> +</feed> diff --git a/desktop/test/deployment/update/updatefeed/update/feed2.oxt b/desktop/test/deployment/update/updatefeed/update/feed2.oxt Binary files differnew file mode 100644 index 000000000000..9c867ae4a812 --- /dev/null +++ b/desktop/test/deployment/update/updatefeed/update/feed2.oxt diff --git a/desktop/test/deployment/update/updatefeed/update/feed2.update.xml b/desktop/test/deployment/update/updatefeed/update/feed2.update.xml new file mode 100644 index 000000000000..7a554b30c497 --- /dev/null +++ b/desktop/test/deployment/update/updatefeed/update/feed2.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.feed2.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/updatefeed/update/feed2.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/updateinfocreation/build/MANIFEST.MF b/desktop/test/deployment/update/updateinfocreation/build/MANIFEST.MF new file mode 100755 index 000000000000..09e2f42ca0f6 --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/build/MANIFEST.MF @@ -0,0 +1,2 @@ +RegistrationClassName: com.sun.star.comp.smoketest.TestExtension + diff --git a/desktop/test/deployment/update/updateinfocreation/build/TestExtension.idl b/desktop/test/deployment/update/updateinfocreation/build/TestExtension.idl new file mode 100755 index 000000000000..af7b3c507eb2 --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/build/TestExtension.idl @@ -0,0 +1,40 @@ +/************************************************************************* + * + * 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 _com_sun_star_comp_smoketest_TestExtension_idl_ +#define _com_sun_star_comp_smoketest_TestExtension_idl_ + +#include <com/sun/star/lang/XServiceInfo.idl> + + +module com { module sun { module star { module comp { module smoketest { + // example service, XServiceInfo is implemented here for demonstration + // issues. XServiceInfo must be implemented by all components. + service TestExtension: ::com::sun::star::lang::XServiceInfo; +};};};};}; + +#endif diff --git a/desktop/test/deployment/update/updateinfocreation/build/TestExtension.java b/desktop/test/deployment/update/updateinfocreation/build/TestExtension.java new file mode 100755 index 000000000000..91e8bf5ff363 --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/build/TestExtension.java @@ -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. + * + *************************************************************************/ +package com.sun.star.comp.smoketest; + +import com.sun.star.lib.uno.helper.Factory; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XSingleComponentFactory; +import com.sun.star.lib.uno.helper.WeakBase; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.registry.XRegistryKey; +import com.sun.star.lang.XInitialization; +import com.sun.star.lang.XTypeProvider; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.uno.Type; + +/** This class capsulates the class, that implements the minimal component, a + * factory for creating the service (<CODE>__getComponentFactory</CODE>) and a + * method, that writes the information into the given registry key + * (<CODE>__writeRegistryServiceInfo</CODE>). + */ +public class TestExtension { + /** This class implements the component. At least the interfaces XServiceInfo, + * XTypeProvider, and XInitialization should be provided by the service. + */ + public static class _TestExtension extends WeakBase + implements XServiceInfo { + /** The service name, that must be used to get an instance of this service. + */ + static private final String __serviceName = + "com.sun.star.comp.smoketest.TestExtension"; + + /** The initial component contextr, that gives access to + * the service manager, supported singletons, ... + * It's often later used + */ + private XComponentContext m_cmpCtx; + + /** The service manager, that gives access to all registered services. + * It's often later used + */ + private XMultiComponentFactory m_xMCF; + + /** The constructor of the inner class has a XMultiServiceFactory parameter. + * @param xmultiservicefactoryInitialization A special service factory + * could be introduced while initializing. + */ + public _TestExtension(XComponentContext xCompContext) { + try { + m_cmpCtx = xCompContext; + m_xMCF = m_cmpCtx.getServiceManager(); + } + catch( Exception e ) { + e.printStackTrace(); + } + } + + /** This method returns an array of all supported service names. + * @return Array of supported service names. + */ + public String[] getSupportedServiceNames() { + return getServiceNames(); + } + + /** This method is a simple helper function to used in the + * static component initialisation functions as well as in + * getSupportedServiceNames. + */ + public static String[] getServiceNames() { + String[] sSupportedServiceNames = { __serviceName }; + return sSupportedServiceNames; + } + + /** This method returns true, if the given service will be + * supported by the component. + * @param sServiceName Service name. + * @return True, if the given service name will be supported. + */ + public boolean supportsService( String sServiceName ) { + return sServiceName.equals( __serviceName ); + } + + /** Return the class name of the component. + * @return Class name of the component. + */ + public String getImplementationName() { + return _TestExtension.class.getName(); + } + } + + + /** + * Gives a factory for creating the service. + * This method is called by the <code>JavaLoader</code> + * <p> + * @return returns a <code>XSingleComponentFactory</code> for creating + * the component + * @param sImplName the name of the implementation for which a + * service is desired + * @see com.sun.star.comp.loader.JavaLoader + */ + public static XSingleComponentFactory __getComponentFactory(String sImplName) + { + XSingleComponentFactory xFactory = null; + + if ( sImplName.equals( _TestExtension.class.getName() ) ) + xFactory = Factory.createComponentFactory(_TestExtension.class, + _TestExtension.getServiceNames()); + + return xFactory; + } + + /** + * Writes the service information into the given registry key. + * This method is called by the <code>JavaLoader</code> + * <p> + * @return returns true if the operation succeeded + * @param regKey the registryKey + * @see com.sun.star.comp.loader.JavaLoader + */ + public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) { + return Factory.writeRegistryServiceInfo(_TestExtension.class.getName(), + _TestExtension.getServiceNames(), + regKey); + } + /** This method is a member of the interface for initializing an object + * directly after its creation. + * @param object This array of arbitrary objects will be passed to the + * component after its creation. + * @throws Exception Every exception will not be handled, but will be + * passed to the caller. + */ + public void initialize( Object[] object ) + throws com.sun.star.uno.Exception { + /* The component describes what arguments its expected and in which + * order!At this point you can read the objects and can intialize + * your component using these objects. + */ + } + +} diff --git a/desktop/test/deployment/update/updateinfocreation/build/delzip b/desktop/test/deployment/update/updateinfocreation/build/delzip new file mode 100755 index 000000000000..636fda90bfcb --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/build/delzip @@ -0,0 +1 @@ +ECHO is OFF diff --git a/desktop/test/deployment/update/updateinfocreation/build/description.xml b/desktop/test/deployment/update/updateinfocreation/build/description.xml new file mode 100644 index 000000000000..a175c3232ab5 --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/build/description.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/description/2006" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:d="http://openoffice.org/extensions/description/2006" > + <identifier value="org.openoffice.extensions.testarea.desktop.updateinfo"/> + <version value="2.0" /> + <dependencies > + <OpenOffice.org-minimal-version value="2.1" d:name="OpenOffice.org 2.1"/> + </dependencies> + <update-information> + <src xlink:href="http://update.services.openoffice.org/ProductUpdateService/check.Update?product=extension&extensionid=org.openoffice.extensions.testarea.desktop.updateinfo&refresh=true"/> + </update-information> +</description> diff --git a/desktop/test/deployment/update/updateinfocreation/build/makefile.mk b/desktop/test/deployment/update/updateinfocreation/build/makefile.mk new file mode 100755 index 000000000000..6af3928279e0 --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/build/makefile.mk @@ -0,0 +1,88 @@ +#************************************************************************* +# +# 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 = updateinfo +PACKAGE = com$/sun$/star$/comp$/smoketest +TARGET = com_sun_star_comp_smoketest + +no_common_build_zip:=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +JARFILES = ridl.jar jurt.jar unoil.jar juh.jar + + +JARTARGET = TestExtension.jar +JARCOMPRESS = TRUE +CUSTOMMANIFESTFILE = MANIFEST.MF + +ZIP1TARGET=updateinfo +ZIP1LIST=* +ZIPFLAGS=-r +ZIP1DIR=$(MISC)$/$(TARGET) +ZIP1EXT=.oxt + +EXTUPDATEINFO_NAME=org.openoffice.extensions.testarea.desktop.updateinfo.update.xml +EXTUPDATEINFO_SOURCE=description.xml +EXTUPDATEINFO_URLS = http://extensions.openoffice.org/testarea/desktop/updateinfocreation/update/updateinfo.oxt +# --- Files -------------------------------------------------------- + +COPY_OXT_MANIFEST:= $(MISC)$/$(TARGET)$/META-INF$/manifest.xml +JAVAFILES = TestExtension.java + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +$(JARTARGETN) : $(MISC)$/$(TARGET).javamaker.done + +$(JAVACLASSFILES) : $(MISC)$/$(TARGET).javamaker.done + +$(MISC)$/$(TARGET).javamaker.done: $(BIN)$/TestExtension.rdb + $(JAVAMAKER) -O$(CLASSDIR) -BUCR -nD -X$(SOLARBINDIR)/types.rdb $< + $(TOUCH) $@ + +$(BIN)$/TestExtension.rdb: TestExtension.idl + $(IDLC) -O$(MISC) -I$(SOLARIDLDIR) -cid -we $< + +-$(RM) $@ + $(REGMERGE) $@ /UCR $(MISC)$/TestExtension.urd + +$(MISC)$/$(ZIP1TARGET).createdir : + +$(MKDIRHIER) $(MISC)$/$(TARGET)$/META-INF >& $(NULLDEV) && $(TOUCH) $@ + +$(MISC)$/$(TARGET)_resort : manifest.xml $(JARTARGETN) $(MISC)$/$(ZIP1TARGET).createdir $(BIN)$/TestExtension.rdb description.xml + $(GNUCOPY) -u manifest.xml $(MISC)$/$(TARGET)$/META-INF$/manifest.xml + $(GNUCOPY) -u $(JARTARGETN) $(MISC)$/$(TARGET)$/$(JARTARGET) + $(GNUCOPY) -u $(BIN)$/TestExtension.rdb $(MISC)$/$(TARGET)$/TestExtension.rdb + $(GNUCOPY) -u description.xml $(MISC)$/$(TARGET)$/description.xml + $(TOUCH) $@ + +$(ZIP1TARGETN) : $(MISC)$/$(TARGET)_resort $(MISC)$/$(ZIP1TARGET).createdir + diff --git a/desktop/test/deployment/update/updateinfocreation/build/manifest.xml b/desktop/test/deployment/update/updateinfocreation/build/manifest.xml new file mode 100755 index 000000000000..7e3e7947aa0f --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/build/manifest.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<manifest:manifest> + <manifest:file-entry manifest:full-path="TestExtension.jar" manifest:media-type="application/vnd.sun.star.uno-component;type=Java"/> + <manifest:file-entry manifest:full-path="TestExtension.rdb" manifest:media-type="application/vnd.sun.star.uno-typelibrary;type=RDB"/> +</manifest:manifest>
\ No newline at end of file diff --git a/desktop/test/deployment/update/updateinfocreation/readme.txt b/desktop/test/deployment/update/updateinfocreation/readme.txt new file mode 100644 index 000000000000..c4fc059053e9 --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/readme.txt @@ -0,0 +1,38 @@ +The extension build in this test uses an update information which is obtained +through a http get request. That is the URL does not reference an update +information file. Instead it invokes code on a webserver which returns the +update information. The URL used in this example is: + +http://update.services.openoffice.org/ProductUpdateService/check.Update?product=extension&extensionid=org.openoffice.extensions.testarea.desktop.updateinfo&refresh=true + +The updateinfo.oxt in this directory has the version 1.0 and in the sub-directory "update is the version 2 of this extension. Version 1.0 is also available here +/extensions/www/testarea/desktop/updateinfocreation/updateinfo.oxt +and version 2.0 here +/extensions/www/testarea/desktop/updateinfocreation/update/updateinfo.oxt + +Therefore they can be accessed through + +http://extensions.openoffice.org/testarea/desktop/updateinfocreation/updateinfo.oxt +and +http://extensions.openoffice.org/testarea/desktop/updateinfocreation/update/updateinfo.oxt + +The latter location (version 2.0) will also be referenced by the update information +which are returned by the webserver. + +The build sub-directory contains the code of the extension (version 2.0) and can +be build by calling dmake in this directory. The makefile uses the special macros: + +EXTUPDATEINFO_NAME=org.openoffice.extensions.testarea.desktop.updateinfo.update.xml +EXTUPDATEINFO_SOURCE=description.xml +EXTUPDATEINFO_URLS = http://extensions.openoffice.org/testarea/desktop/updateinfocreation/update/updateinfo.oxt + +This causes the generation of the update information file. This file could be +directly references by the URL in the <update-information> of the description.xml. +See also the Wiki entry at: +http://wiki.services.openoffice.org/wiki/Creating_update_information_for_extensions +This generated update information file can then be used by the webserver, when it +sends back the requested update information. The update information file will be +generated in the misc diretory of the output directory. + +The update information file needs to be copied into common.pro/pus.mxyz directory. +The project mwsfinish will process the files in the pus directory. diff --git a/desktop/test/deployment/update/updateinfocreation/update/updateinfo.oxt b/desktop/test/deployment/update/updateinfocreation/update/updateinfo.oxt Binary files differnew file mode 100644 index 000000000000..52ddd3158e31 --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/update/updateinfo.oxt diff --git a/desktop/test/deployment/update/updateinfocreation/updateinfo.oxt b/desktop/test/deployment/update/updateinfocreation/updateinfo.oxt Binary files differnew file mode 100644 index 000000000000..43ac7003bc59 --- /dev/null +++ b/desktop/test/deployment/update/updateinfocreation/updateinfo.oxt diff --git a/desktop/test/deployment/update/website_update/readme.txt b/desktop/test/deployment/update/website_update/readme.txt new file mode 100644 index 000000000000..4ae5ddd9182f --- /dev/null +++ b/desktop/test/deployment/update/website_update/readme.txt @@ -0,0 +1,133 @@ +The folder contains extensions which need to be updated through a web site. +The "Updates dialog" of the Extension Manager will mark the updates for these +extensions as "browser based update". The Extension Manager will open a browser +for each of the extensions and navigate to the respective website. + +================================================================================ +web1.oxt - web5.oxt: +================================================================================ +They contain <update-information>. That is they reference directly the respective +webX.update.xml (for example, web1.update.xml) files which are available at +http://extensions.openoffice.org/testarea/desktop/website_update/update/... +For example: +http://extensions.openoffice.org/testarea/desktop/website_update/update/web2.update.xml + +The update information contain multiple URLs to "localized" web sites. Each URL is +assigned to a particular local. For example: + +<src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de.html" lang="de"/> + +The Extension Manager will choose the URLs where the lang attribute matches most +closely the locale of the office. + +The following table shows what localized web site is used, when the office uses the locale +en-US. The web page will display the locale used. See update/web1_de.html, etc. + + +Localization: + +Installed office en-US + | publisher | release notes +============================================= +web1.oxt | en-US | en-US +--------------------------------------------- +web2.oxt | en-US-region1 | en-US-region1 +--------------------------------------------- +web3.oxt | en | en +--------------------------------------------- +web4.oxt | en-GB | en-GB +--------------------------------------------- +web5.oxt | de | de + + +================================================================================ +web6.oxt +================================================================================ +Need not be committed in extensions/www/testarea/desktop. + +web6.oxt is intended for tests with extensions.services.openoffice.org. +It does not contain <update-information>. That is, the Extension Manager will obtain +the update information from the repository as feed: + +http://updateext.services.openoffice.org/ProductUpdateService/check.Update + +Test +---- +Repository: + +-Create the new extension in the repository. +-Provide a company name and a URL to the company website. In our case this should be + http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US.html + +-Create a new release for the extension. Upload the description.xml of version 2.0 +(update/web6/description.xml). Provide a download URL for the web site (field + "Download from page / Open follow up page URL", which should be + http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US.html + Provide release notes. + + +Office: +-Install version 1.0 of the extension: + desktop/test/deployment/update/website_update/web6.oxt + +-Run the update in the Extension Manager + + +Result: +The Update Dialog should show the publisher name as provided in "Provider URL" field +of the extension edit page (not release). + +A release notes link is displayed with an URL to the release notes as provided in +the "Provider Title" field of the extension release edit page. + +When running the update then the web browser should navigate to +http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US.html + + +================================================================================ +web7.oxt +================================================================================ +Need not be committed in extensions/www/testarea/desktop + +web7.oxt is intended for tests with extensions.services.openoffice.org. +It does not contain <update-information>. That is, the Extension Manager will obtain +the update information from the repository as feed: + +http://updateext.services.openoffice.org/ProductUpdateService/check.Update + +The description.xml which will be uploaded contains URLs for release notes and publisher +names/ URLs. That is, these information are not generated from the information of the +repository web site. + +Test +----------- +Repository: + +-Create the new extension in the repository. +-Provide a company name and a URL to the company website. In our case these should be different + to those provided in the description.xml. These should NOT go into the update feed. + Choose for example as "Provider Title": FOO and as "Provider URL" some valid URL but NOT + http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US.html + +-Create a new release for the extension. Upload the description.xml of version 2.0 +(update/web7/description.xml). Provide a download URL for the web site (field + "Download from page / Open follow up page URL", which should be + http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US.html + Provide release notes. + +Office: +-Install version 1.0 of the extension: + desktop/test/deployment/update/website_update/web7.oxt + +-Run the update in the Extension Manager + +Result: +The Update Dialog should show the publisher name as provided in the description.xml. +That is: My OpenOffice en-US and NOT "FOO". + +A release notes link is displayed with an URL to the release notes as provided in +the description.xml. That is: +http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_xxx.html + +When running the update then the web browser should navigate to +http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US.html diff --git a/desktop/test/deployment/update/website_update/update/web1.oxt b/desktop/test/deployment/update/website_update/update/web1.oxt Binary files differnew file mode 100644 index 000000000000..157d5d952c60 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1.oxt diff --git a/desktop/test/deployment/update/website_update/update/web1.update.xml b/desktop/test/deployment/update/website_update/update/web1.update.xml new file mode 100644 index 000000000000..1355851073bd --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1.update.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/website_update/web1"/> + + <update-website> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en.html" lang="en" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US.html" lang="en-US" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US-region1.html" lang="en-US-region1" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US-region2.html" lang="en-US-region2" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-region3.html" lang="en-region3" /> + </update-website> +</description> + diff --git a/desktop/test/deployment/update/website_update/update/web1_de-DE-altmark.html b/desktop/test/deployment/update/website_update/update/web1_de-DE-altmark.html new file mode 100644 index 000000000000..ffed5a52e892 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1_de-DE-altmark.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Update Extensions</H1> +<H1>de-DE-altmark</H1> +<p><a href="web1.oxt">web1.oxt</a></p> +<p><a href="web2.oxt">web2.oxt</a></p> +<p><a href="web3.oxt">web3.oxt</a></p> +<p><a href="web4.oxt">web4.oxt</a></p> +<p><a href="web5.oxt">web5.oxt</a></p> +<p><a href="web6.oxt">web6.oxt</a></p> +<p><a href="web7.oxt">web7.oxt</a></p> + +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/website_update/update/web1_de-DE.html b/desktop/test/deployment/update/website_update/update/web1_de-DE.html new file mode 100644 index 000000000000..33fb7f2ec8bc --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1_de-DE.html @@ -0,0 +1,18 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Update Extensions</H1> +<H1>de-DE</H1> +<p><a href="web1.oxt">web1.oxt</a></p> +<p><a href="web2.oxt">web2.oxt</a></p> +<p><a href="web3.oxt">web3.oxt</a></p> +<p><a href="web4.oxt">web4.oxt</a></p> +<p><a href="web5.oxt">web5.oxt</a></p> +<p><a href="web6.oxt">web6.oxt</a></p> +<p><a href="web7.oxt">web7.oxt</a></p> + +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/website_update/update/web1_de.html b/desktop/test/deployment/update/website_update/update/web1_de.html new file mode 100644 index 000000000000..31a53b91dbe4 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1_de.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Update Extensions</H1> +<H1>de</H1> +<p><a href="web1.oxt">web1.oxt</a></p> +<p><a href="web2.oxt">web2.oxt</a></p> +<p><a href="web3.oxt">web3.oxt</a></p> +<p><a href="web4.oxt">web4.oxt</a></p> +<p><a href="web5.oxt">web5.oxt</a></p> +<p><a href="web6.oxt">web6.oxt</a></p> +<p><a href="web7.oxt">web7.oxt</a></p> + + +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/website_update/update/web1_en-GB.html b/desktop/test/deployment/update/website_update/update/web1_en-GB.html new file mode 100644 index 000000000000..c46328a82145 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1_en-GB.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Update Extensions</H1> +<H1>en-GB</H1> +<p><a href="web1.oxt">web1.oxt</a></p> +<p><a href="web2.oxt">web2.oxt</a></p> +<p><a href="web3.oxt">web3.oxt</a></p> +<p><a href="web4.oxt">web4.oxt</a></p> +<p><a href="web5.oxt">web5.oxt</a></p> +<p><a href="web6.oxt">web6.oxt</a></p> +<p><a href="web7.oxt">web7.oxt</a></p> + + +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/website_update/update/web1_en-US-region1.html b/desktop/test/deployment/update/website_update/update/web1_en-US-region1.html new file mode 100644 index 000000000000..80b41823b70f --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1_en-US-region1.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+</HEAD>
+<BODY>
+<H1>Update Extensions</H1>
+<H1>en-US-region1</H1>
+<p><a href="web1.oxt">web1.oxt</a></p>
+<p><a href="web2.oxt">web2.oxt</a></p>
+<p><a href="web3.oxt">web3.oxt</a></p>
+<p><a href="web4.oxt">web4.oxt</a></p>
+<p><a href="web5.oxt">web5.oxt</a></p>
+<p><a href="web6.oxt">web6.oxt</a></p>
+<p><a href="web7.oxt">web7.oxt</a></p>
+
+
+</BODY>
+</HTML>
+
diff --git a/desktop/test/deployment/update/website_update/update/web1_en-US-region2.html b/desktop/test/deployment/update/website_update/update/web1_en-US-region2.html new file mode 100644 index 000000000000..1a501f520d85 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1_en-US-region2.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Update Extensions</H1> +<H1>en-US-region2</H1> +<p><a href="web1.oxt">web1.oxt</a></p> +<p><a href="web2.oxt">web2.oxt</a></p> +<p><a href="web3.oxt">web3.oxt</a></p> +<p><a href="web4.oxt">web4.oxt</a></p> +<p><a href="web5.oxt">web5.oxt</a></p> +<p><a href="web6.oxt">web6.oxt</a></p> +<p><a href="web7.oxt">web7.oxt</a></p> + + +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/website_update/update/web1_en-US.html b/desktop/test/deployment/update/website_update/update/web1_en-US.html new file mode 100644 index 000000000000..f861b09c0162 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1_en-US.html @@ -0,0 +1,20 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+</HEAD>
+<BODY>
+<H1>Update Extensions</H1>
+<H1>en-US</H1>
+<p><a href="web1.oxt">web1.oxt</a></p>
+<p><a href="web2.oxt">web2.oxt</a></p>
+<p><a href="web3.oxt">web3.oxt</a></p>
+<p><a href="web4.oxt">web4.oxt</a></p>
+<p><a href="web5.oxt">web5.oxt</a></p>
+<p><a href="web6.oxt">web6.oxt</a></p>
+<p><a href="web7.oxt">web7.oxt</a></p>
+
+
+
+</BODY>
+</HTML>
+
diff --git a/desktop/test/deployment/update/website_update/update/web1_en-region3.html b/desktop/test/deployment/update/website_update/update/web1_en-region3.html new file mode 100644 index 000000000000..f55bcbe38135 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1_en-region3.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Update Extensions</H1> +<H1>en-region3</H1> +<p><a href="web1.oxt">web1.oxt</a></p> +<p><a href="web2.oxt">web2.oxt</a></p> +<p><a href="web3.oxt">web3.oxt</a></p> +<p><a href="web4.oxt">web4.oxt</a></p> +<p><a href="web5.oxt">web5.oxt</a></p> +<p><a href="web6.oxt">web6.oxt</a></p> +<p><a href="web7.oxt">web7.oxt</a></p> + + +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/website_update/update/web1_en.html b/desktop/test/deployment/update/website_update/update/web1_en.html new file mode 100644 index 000000000000..a0b422ebf20e --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web1_en.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +</HEAD> +<BODY> +<H1>Update Extensions</H1> +<H1>en</H1> +<p><a href="web1.oxt">web1.oxt</a></p> +<p><a href="web2.oxt">web2.oxt</a></p> +<p><a href="web3.oxt">web3.oxt</a></p> +<p><a href="web4.oxt">web4.oxt</a></p> +<p><a href="web5.oxt">web5.oxt</a></p> +<p><a href="web6.oxt">web6.oxt</a></p> +<p><a href="web7.oxt">web7.oxt</a></p> + + +</BODY> +</HTML> + diff --git a/desktop/test/deployment/update/website_update/update/web2.oxt b/desktop/test/deployment/update/website_update/update/web2.oxt Binary files differnew file mode 100644 index 000000000000..3a13e8114314 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web2.oxt diff --git a/desktop/test/deployment/update/website_update/update/web2.update.xml b/desktop/test/deployment/update/website_update/update/web2.update.xml new file mode 100644 index 000000000000..23343ecedeed --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web2.update.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/website_update/web2"/> + + <update-website> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en.html" lang="en" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US-region1.html" lang="en-US-region1" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-US-region2.html" lang="en-US-region2" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-region3.html" lang="en-region3" /> + </update-website> +</description> + diff --git a/desktop/test/deployment/update/website_update/update/web3.oxt b/desktop/test/deployment/update/website_update/update/web3.oxt Binary files differnew file mode 100644 index 000000000000..b3214a4e693f --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web3.oxt diff --git a/desktop/test/deployment/update/website_update/update/web3.update.xml b/desktop/test/deployment/update/website_update/update/web3.update.xml new file mode 100644 index 000000000000..0958b497f8c2 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web3.update.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/website_update/web3"/> + + <update-website> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en.html" lang="en" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-region3.html" lang="en-region3" /> + </update-website> +</description> + diff --git a/desktop/test/deployment/update/website_update/update/web4.oxt b/desktop/test/deployment/update/website_update/update/web4.oxt Binary files differnew file mode 100644 index 000000000000..93766fd44faf --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web4.oxt diff --git a/desktop/test/deployment/update/website_update/update/web4.update.xml b/desktop/test/deployment/update/website_update/update/web4.update.xml new file mode 100644 index 000000000000..ddff6eb0a908 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web4.update.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/website_update/web4"/> + + <update-website> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_en-region3.html" lang="en-region3" /> + </update-website> +</description> + diff --git a/desktop/test/deployment/update/website_update/update/web5.oxt b/desktop/test/deployment/update/website_update/update/web5.oxt Binary files differnew file mode 100644 index 000000000000..1ae8f01b19cb --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web5.oxt diff --git a/desktop/test/deployment/update/website_update/update/web5.update.xml b/desktop/test/deployment/update/website_update/update/web5.update.xml new file mode 100644 index 000000000000..28a61e14de1a --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web5.update.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + + <identifier value="org.openoffice/framework/desktop/test/deployment/update/website_update/web5"/> + + <update-website> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/website_update/update/web1_de-DE-altmark.html" lang="de-DE-altmark" /> + </update-website> +</description> + diff --git a/desktop/test/deployment/update/website_update/update/web6.oxt b/desktop/test/deployment/update/website_update/update/web6.oxt Binary files differnew file mode 100644 index 000000000000..8bc16fb2c73a --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web6.oxt diff --git a/desktop/test/deployment/update/website_update/update/web6/description.xml b/desktop/test/deployment/update/website_update/update/web6/description.xml new file mode 100644 index 000000000000..294661b6fc6e --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web6/description.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/description/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + <identifier value="org.openoffice/framework/desktop/test/deployment/update/website_update/web6"/> + <display-name> + <name lang="en">web-based update test 1</name> + </display-name> + +</description> + diff --git a/desktop/test/deployment/update/website_update/update/web6/readme.txt b/desktop/test/deployment/update/website_update/update/web6/readme.txt new file mode 100644 index 000000000000..7a1ba06efaa3 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web6/readme.txt @@ -0,0 +1,5 @@ +This folder contains the description.xml from update/web6.oxt
+When creating the release 2.0 on the repository then this description.xml can be uploaded.
+
+
+This folder is not needed on extensions.openoffice.org/testarea/desktop/....
diff --git a/desktop/test/deployment/update/website_update/update/web7.oxt b/desktop/test/deployment/update/website_update/update/web7.oxt Binary files differnew file mode 100644 index 000000000000..4d6220a48af2 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web7.oxt diff --git a/desktop/test/deployment/update/website_update/update/web7/description.xml b/desktop/test/deployment/update/website_update/update/web7/description.xml new file mode 100644 index 000000000000..8fcaf9278ce1 --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web7/description.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/description/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <version value="2.0" /> + <identifier value="org.openoffice/framework/desktop/test/deployment/update/website_update/web7"/> + <display-name> + <name lang="en">web-based update test 1</name> + </display-name> + + <publisher> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de.html" lang="de">My OpenOffice de</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en.html" lang="en">My OpenOffice en</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE.html" lang="de-DE">My OpenOffice de-DE</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_de-DE-altmark.html" lang="de-DE-altmark">My OpenOffice de-DE-altmark</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-GB.html" lang="en-GB">My OpenOffice en-GB</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US.html" lang="en-US">My OpenOffice en-US</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US-region1.html" lang="en-US-region1">My OpenOffice en-US-region1</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-US-region2.html" lang="en-US-region2">My OpenOffice en-US-region2</name> + <name xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/publisher_en-region3.html" lang="en-region3">My OpenOffice en-region3</name> + </publisher> + + <release-notes> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de.html" lang="de" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en.html" lang="en" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE.html" lang="de-DE" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_de-DE-altmark.html" lang="de-DE-altmark" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-GB.html" lang="en-GB" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US.html" lang="en-US" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US-region1.html" lang="en-US-region1" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-US-region2.html" lang="en-US-region2" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/publisher/release-notes_en-region3.html" lang="en-region3" /> + </release-notes> + + +</description> + diff --git a/desktop/test/deployment/update/website_update/update/web7/readme.txt b/desktop/test/deployment/update/website_update/update/web7/readme.txt new file mode 100644 index 000000000000..8a6721b8e85c --- /dev/null +++ b/desktop/test/deployment/update/website_update/update/web7/readme.txt @@ -0,0 +1,5 @@ +This folder contains the description.xml from update/web7.oxt
+When creating the release 2.0 on the repository then this description.xml can be uploaded.
+
+
+This folder is not needed on extensions.openoffice.org/testarea/desktop/....
diff --git a/desktop/test/deployment/update/website_update/web1.oxt b/desktop/test/deployment/update/website_update/web1.oxt Binary files differnew file mode 100644 index 000000000000..7c17586e0454 --- /dev/null +++ b/desktop/test/deployment/update/website_update/web1.oxt diff --git a/desktop/test/deployment/update/website_update/web2.oxt b/desktop/test/deployment/update/website_update/web2.oxt Binary files differnew file mode 100644 index 000000000000..705e70a7533f --- /dev/null +++ b/desktop/test/deployment/update/website_update/web2.oxt diff --git a/desktop/test/deployment/update/website_update/web3.oxt b/desktop/test/deployment/update/website_update/web3.oxt Binary files differnew file mode 100644 index 000000000000..4e63a75f0cbf --- /dev/null +++ b/desktop/test/deployment/update/website_update/web3.oxt diff --git a/desktop/test/deployment/update/website_update/web4.oxt b/desktop/test/deployment/update/website_update/web4.oxt Binary files differnew file mode 100644 index 000000000000..e66513e68384 --- /dev/null +++ b/desktop/test/deployment/update/website_update/web4.oxt diff --git a/desktop/test/deployment/update/website_update/web5.oxt b/desktop/test/deployment/update/website_update/web5.oxt Binary files differnew file mode 100644 index 000000000000..65b02db9347d --- /dev/null +++ b/desktop/test/deployment/update/website_update/web5.oxt diff --git a/desktop/test/deployment/update/website_update/web6.oxt b/desktop/test/deployment/update/website_update/web6.oxt Binary files differnew file mode 100644 index 000000000000..98416edfa583 --- /dev/null +++ b/desktop/test/deployment/update/website_update/web6.oxt diff --git a/desktop/test/deployment/update/website_update/web7.oxt b/desktop/test/deployment/update/website_update/web7.oxt Binary files differnew file mode 100644 index 000000000000..31ba45f032d5 --- /dev/null +++ b/desktop/test/deployment/update/website_update/web7.oxt diff --git a/desktop/test/deployment/update/wrong_url/readme.txt b/desktop/test/deployment/update/wrong_url/readme.txt new file mode 100644 index 000000000000..cc2459763ca9 --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/readme.txt @@ -0,0 +1,18 @@ +The extensions use either multiple urls to the update information file, or the update information file contains multiple urls. Some of those URLs point to locations which do not exist. + +url1.oxt: The corresponding url1.update.xml contains two download urls. The first Url points to a location that is not available. The second points to the new version. + +url2.oxt: Contains to URLs to update information files. The first URL in url2.oxt is wrong and the second is +correct. + +url3.oxt: contains to URLs to update information files which point to locations which do not exist. + +wrongdownload1.oxt: The corresponding wrongdownload1.update.xml contains two download URLs which point to locations which are not available. + +wrongdownload2.oxt: same as wrongdownload1.oxt + +wrongdownload3.oxt: same as wrongdownload1.oxt + + +Use the wrongdownload extensions to check the automatic scolling of the text area that contains the results. + diff --git a/desktop/test/deployment/update/wrong_url/update/url1.oxt b/desktop/test/deployment/update/wrong_url/update/url1.oxt Binary files differnew file mode 100644 index 000000000000..479b546c84dd --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/update/url1.oxt diff --git a/desktop/test/deployment/update/wrong_url/update/url1.update.xml b/desktop/test/deployment/update/wrong_url/update/url1.update.xml new file mode 100644 index 000000000000..a50dec4cd51e --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/update/url1.update.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.url1.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/wrong_url/notavailable/url1.oxt" /> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/wrong_url/update/url1.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/wrong_url/update/url2.oxt b/desktop/test/deployment/update/wrong_url/update/url2.oxt Binary files differnew file mode 100644 index 000000000000..ec2c5c6528cd --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/update/url2.oxt diff --git a/desktop/test/deployment/update/wrong_url/update/url2.update.xml b/desktop/test/deployment/update/wrong_url/update/url2.update.xml new file mode 100644 index 000000000000..13757c825749 --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/update/url2.update.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.url2.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/wrong_url/update/url2.oxt" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/wrong_url/update/wrongdownload1.update.xml b/desktop/test/deployment/update/wrong_url/update/wrongdownload1.update.xml new file mode 100644 index 000000000000..b2b62a3be3ed --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/update/wrongdownload1.update.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.wrongdownload1.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/wrong_url/notavailable/wrongdownload1.oxt" /> + <src xlink:href="http://extensions.openoffice.org/notavailable/" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/wrong_url/update/wrongdownload2.update.xml b/desktop/test/deployment/update/wrong_url/update/wrongdownload2.update.xml new file mode 100644 index 000000000000..cb0171876526 --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/update/wrongdownload2.update.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.wrongdownload2.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/wrong_url/notavailable/wrongdownload2.oxt" /> + <src xlink:href="http://extensions.openoffice.org/notavailable/" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/wrong_url/update/wrongdownload3.update.xml b/desktop/test/deployment/update/wrong_url/update/wrongdownload3.update.xml new file mode 100644 index 000000000000..6ce027763df7 --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/update/wrongdownload3.update.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<description xmlns="http://openoffice.org/extensions/update/2006" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <identifier value="org.openoffice.legacy.wrongdownload3.oxt"/> + <version value="2.0" /> + <update-download> + <src xlink:href="http://extensions.openoffice.org/testarea/desktop/wrong_url/notavailable/wrongdownload3.oxt" /> + <src xlink:href="http://extensions.openoffice.org/notavailable/" /> + </update-download> +</description> + diff --git a/desktop/test/deployment/update/wrong_url/url1.oxt b/desktop/test/deployment/update/wrong_url/url1.oxt Binary files differnew file mode 100644 index 000000000000..41d8522fbbce --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/url1.oxt diff --git a/desktop/test/deployment/update/wrong_url/url2.oxt b/desktop/test/deployment/update/wrong_url/url2.oxt Binary files differnew file mode 100644 index 000000000000..d68e45e5e55f --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/url2.oxt diff --git a/desktop/test/deployment/update/wrong_url/url3.oxt b/desktop/test/deployment/update/wrong_url/url3.oxt Binary files differnew file mode 100644 index 000000000000..80f93b74d11f --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/url3.oxt diff --git a/desktop/test/deployment/update/wrong_url/wrongdownload1.oxt b/desktop/test/deployment/update/wrong_url/wrongdownload1.oxt Binary files differnew file mode 100644 index 000000000000..535ae331a9af --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/wrongdownload1.oxt diff --git a/desktop/test/deployment/update/wrong_url/wrongdownload2.oxt b/desktop/test/deployment/update/wrong_url/wrongdownload2.oxt Binary files differnew file mode 100644 index 000000000000..aafe2c24672b --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/wrongdownload2.oxt diff --git a/desktop/test/deployment/update/wrong_url/wrongdownload3.oxt b/desktop/test/deployment/update/wrong_url/wrongdownload3.oxt Binary files differnew file mode 100644 index 000000000000..fbdac925a257 --- /dev/null +++ b/desktop/test/deployment/update/wrong_url/wrongdownload3.oxt diff --git a/desktop/test/deployment/version/readme.txt b/desktop/test/deployment/version/readme.txt new file mode 100644 index 000000000000..c2ba28afd916 --- /dev/null +++ b/desktop/test/deployment/version/readme.txt @@ -0,0 +1,85 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +There are three extensions in various versions: + +1 version_XXX/plain.oxt has no dependencies and no license. +2a version_XXX/dependency.oxt has an unsatisfied dependency and no license. +2b version_nodependencies_XXX/dependency.oxt is identical to 2a but without the + dependency. +3 version_XXX/license.oxt has no dependencies and a license. + +The different versions are: + +A version_none contains no version element (treated as version "0"). +B version_badelement contains a bad <version val="1"/> (not allowed by the + specification, but treated by the current implementation as version "0"). +C version_badvalue contains a bad <version value="1.a"/> (not allowed by the + specification, but treated by the current implementation as version "1"). +D version_0.0 contains <version value="0.0"/> (same as version "0"). +E version_1.2.3 contains <version value="1.2.3"/>. +F version_1.2.4.7 contains <version value="1.2.4.7"/>. +G version_1.02.4.7.0 contains <version value="1.02.4.7.0"/> (same as version + "1.2.4.7"). +H version_1.2.15.3 contains <version value="1.2.15.3"/>. + +The total order among the various versions is thus + + A = B = D < C < E < F = G < H. + +Things to watch for: + +- If version y of extension e is to be installed and version x < y of + extension e is already installed, then + unopkg add e + will replace x with y. + +- If version y of extension e is to be installed and version x >= y of + extension e is already installed, then + unopkg add e + will fail with an error message. + +- If version y of extension e is to be installed and any version x of + extension e is already installed, then + unopkg add -f e + will replace x with y. + +- If version y of extension e is to be installed and any version x of + extension e is already installed, then + unopkg gui "Add..." + and + soffice "Tools - Package Manager... - Add..." + will query with a dialog whether to replace x with y. The dialog will have + "OK" (replace) preselected if x < y, and "Cancel" otherwise. + +- If replacing an installed version x of an extension e with a version y fails + because y has unsatisfied dependencies, or because y has a license to wich the + user does not agree, version x is left installed afterwards. + +- Checking for already installed versions of an extension is only done within a + single layer (unopkg versus unopkg --shared; "My Packages" versus + "OpenOffice Packages" in unopkg gui/soffice), not across layers. diff --git a/desktop/test/deployment/version/version_0.0/dependency.oxt b/desktop/test/deployment/version/version_0.0/dependency.oxt Binary files differnew file mode 100644 index 000000000000..30c8432251a5 --- /dev/null +++ b/desktop/test/deployment/version/version_0.0/dependency.oxt diff --git a/desktop/test/deployment/version/version_0.0/license.oxt b/desktop/test/deployment/version/version_0.0/license.oxt Binary files differnew file mode 100644 index 000000000000..b994ff71b732 --- /dev/null +++ b/desktop/test/deployment/version/version_0.0/license.oxt diff --git a/desktop/test/deployment/version/version_0.0/plain.oxt b/desktop/test/deployment/version/version_0.0/plain.oxt Binary files differnew file mode 100644 index 000000000000..f156014eb8c3 --- /dev/null +++ b/desktop/test/deployment/version/version_0.0/plain.oxt diff --git a/desktop/test/deployment/version/version_1.02.4.7.0/dependency.oxt b/desktop/test/deployment/version/version_1.02.4.7.0/dependency.oxt Binary files differnew file mode 100644 index 000000000000..4d75f7076234 --- /dev/null +++ b/desktop/test/deployment/version/version_1.02.4.7.0/dependency.oxt diff --git a/desktop/test/deployment/version/version_1.02.4.7.0/license.oxt b/desktop/test/deployment/version/version_1.02.4.7.0/license.oxt Binary files differnew file mode 100644 index 000000000000..40938b7543db --- /dev/null +++ b/desktop/test/deployment/version/version_1.02.4.7.0/license.oxt diff --git a/desktop/test/deployment/version/version_1.02.4.7.0/plain.oxt b/desktop/test/deployment/version/version_1.02.4.7.0/plain.oxt Binary files differnew file mode 100644 index 000000000000..521a2b6c77a8 --- /dev/null +++ b/desktop/test/deployment/version/version_1.02.4.7.0/plain.oxt diff --git a/desktop/test/deployment/version/version_1.2.15.3/dependency.oxt b/desktop/test/deployment/version/version_1.2.15.3/dependency.oxt Binary files differnew file mode 100644 index 000000000000..6f2a301f3bb3 --- /dev/null +++ b/desktop/test/deployment/version/version_1.2.15.3/dependency.oxt diff --git a/desktop/test/deployment/version/version_1.2.15.3/license.oxt b/desktop/test/deployment/version/version_1.2.15.3/license.oxt Binary files differnew file mode 100644 index 000000000000..2e2a87575047 --- /dev/null +++ b/desktop/test/deployment/version/version_1.2.15.3/license.oxt diff --git a/desktop/test/deployment/version/version_1.2.15.3/plain.oxt b/desktop/test/deployment/version/version_1.2.15.3/plain.oxt Binary files differnew file mode 100644 index 000000000000..000f3a144fbd --- /dev/null +++ b/desktop/test/deployment/version/version_1.2.15.3/plain.oxt diff --git a/desktop/test/deployment/version/version_1.2.3/dependency.oxt b/desktop/test/deployment/version/version_1.2.3/dependency.oxt Binary files differnew file mode 100644 index 000000000000..c2966345872d --- /dev/null +++ b/desktop/test/deployment/version/version_1.2.3/dependency.oxt diff --git a/desktop/test/deployment/version/version_1.2.3/license.oxt b/desktop/test/deployment/version/version_1.2.3/license.oxt Binary files differnew file mode 100644 index 000000000000..9cd80e9911b4 --- /dev/null +++ b/desktop/test/deployment/version/version_1.2.3/license.oxt diff --git a/desktop/test/deployment/version/version_1.2.3/plain.oxt b/desktop/test/deployment/version/version_1.2.3/plain.oxt Binary files differnew file mode 100644 index 000000000000..e34264591c58 --- /dev/null +++ b/desktop/test/deployment/version/version_1.2.3/plain.oxt diff --git a/desktop/test/deployment/version/version_1.2.4.7/dependency.oxt b/desktop/test/deployment/version/version_1.2.4.7/dependency.oxt Binary files differnew file mode 100644 index 000000000000..53089e76b07e --- /dev/null +++ b/desktop/test/deployment/version/version_1.2.4.7/dependency.oxt diff --git a/desktop/test/deployment/version/version_1.2.4.7/license.oxt b/desktop/test/deployment/version/version_1.2.4.7/license.oxt Binary files differnew file mode 100644 index 000000000000..e283508d3492 --- /dev/null +++ b/desktop/test/deployment/version/version_1.2.4.7/license.oxt diff --git a/desktop/test/deployment/version/version_1.2.4.7/plain.oxt b/desktop/test/deployment/version/version_1.2.4.7/plain.oxt Binary files differnew file mode 100644 index 000000000000..d63c79a734b6 --- /dev/null +++ b/desktop/test/deployment/version/version_1.2.4.7/plain.oxt diff --git a/desktop/test/deployment/version/version_badelement/dependency.oxt b/desktop/test/deployment/version/version_badelement/dependency.oxt Binary files differnew file mode 100644 index 000000000000..3cb8faa2e7b6 --- /dev/null +++ b/desktop/test/deployment/version/version_badelement/dependency.oxt diff --git a/desktop/test/deployment/version/version_badelement/license.oxt b/desktop/test/deployment/version/version_badelement/license.oxt Binary files differnew file mode 100644 index 000000000000..7b2b7730eced --- /dev/null +++ b/desktop/test/deployment/version/version_badelement/license.oxt diff --git a/desktop/test/deployment/version/version_badelement/plain.oxt b/desktop/test/deployment/version/version_badelement/plain.oxt Binary files differnew file mode 100644 index 000000000000..62267c212fdc --- /dev/null +++ b/desktop/test/deployment/version/version_badelement/plain.oxt diff --git a/desktop/test/deployment/version/version_badvalue/dependency.oxt b/desktop/test/deployment/version/version_badvalue/dependency.oxt Binary files differnew file mode 100644 index 000000000000..7d8103365452 --- /dev/null +++ b/desktop/test/deployment/version/version_badvalue/dependency.oxt diff --git a/desktop/test/deployment/version/version_badvalue/license.oxt b/desktop/test/deployment/version/version_badvalue/license.oxt Binary files differnew file mode 100644 index 000000000000..b97723ebb0bc --- /dev/null +++ b/desktop/test/deployment/version/version_badvalue/license.oxt diff --git a/desktop/test/deployment/version/version_badvalue/plain.oxt b/desktop/test/deployment/version/version_badvalue/plain.oxt Binary files differnew file mode 100644 index 000000000000..f9964ed8f070 --- /dev/null +++ b/desktop/test/deployment/version/version_badvalue/plain.oxt diff --git a/desktop/test/deployment/version/version_nodependencies_0.0/dependency.oxt b/desktop/test/deployment/version/version_nodependencies_0.0/dependency.oxt Binary files differnew file mode 100644 index 000000000000..f156014eb8c3 --- /dev/null +++ b/desktop/test/deployment/version/version_nodependencies_0.0/dependency.oxt diff --git a/desktop/test/deployment/version/version_nodependencies_1.02.4.7.0/dependency.oxt b/desktop/test/deployment/version/version_nodependencies_1.02.4.7.0/dependency.oxt Binary files differnew file mode 100644 index 000000000000..521a2b6c77a8 --- /dev/null +++ b/desktop/test/deployment/version/version_nodependencies_1.02.4.7.0/dependency.oxt diff --git a/desktop/test/deployment/version/version_nodependencies_1.2.15.3/dependency.oxt b/desktop/test/deployment/version/version_nodependencies_1.2.15.3/dependency.oxt Binary files differnew file mode 100644 index 000000000000..000f3a144fbd --- /dev/null +++ b/desktop/test/deployment/version/version_nodependencies_1.2.15.3/dependency.oxt diff --git a/desktop/test/deployment/version/version_nodependencies_1.2.3/dependency.oxt b/desktop/test/deployment/version/version_nodependencies_1.2.3/dependency.oxt Binary files differnew file mode 100644 index 000000000000..e34264591c58 --- /dev/null +++ b/desktop/test/deployment/version/version_nodependencies_1.2.3/dependency.oxt diff --git a/desktop/test/deployment/version/version_nodependencies_1.2.4.7/dependency.oxt b/desktop/test/deployment/version/version_nodependencies_1.2.4.7/dependency.oxt Binary files differnew file mode 100644 index 000000000000..d63c79a734b6 --- /dev/null +++ b/desktop/test/deployment/version/version_nodependencies_1.2.4.7/dependency.oxt diff --git a/desktop/test/deployment/version/version_nodependencies_badelement/dependency.oxt b/desktop/test/deployment/version/version_nodependencies_badelement/dependency.oxt Binary files differnew file mode 100644 index 000000000000..62267c212fdc --- /dev/null +++ b/desktop/test/deployment/version/version_nodependencies_badelement/dependency.oxt diff --git a/desktop/test/deployment/version/version_nodependencies_badvalue/dependency.oxt b/desktop/test/deployment/version/version_nodependencies_badvalue/dependency.oxt Binary files differnew file mode 100644 index 000000000000..f9964ed8f070 --- /dev/null +++ b/desktop/test/deployment/version/version_nodependencies_badvalue/dependency.oxt diff --git a/desktop/test/deployment/version/version_nodependencies_none/dependency.oxt b/desktop/test/deployment/version/version_nodependencies_none/dependency.oxt Binary files differnew file mode 100644 index 000000000000..fc227b099ec8 --- /dev/null +++ b/desktop/test/deployment/version/version_nodependencies_none/dependency.oxt diff --git a/desktop/test/deployment/version/version_none/dependency.oxt b/desktop/test/deployment/version/version_none/dependency.oxt Binary files differnew file mode 100644 index 000000000000..36a1854bf59b --- /dev/null +++ b/desktop/test/deployment/version/version_none/dependency.oxt diff --git a/desktop/test/deployment/version/version_none/license.oxt b/desktop/test/deployment/version/version_none/license.oxt Binary files differnew file mode 100644 index 000000000000..1564c089b0a7 --- /dev/null +++ b/desktop/test/deployment/version/version_none/license.oxt diff --git a/desktop/test/deployment/version/version_none/plain.oxt b/desktop/test/deployment/version/version_none/plain.oxt Binary files differnew file mode 100644 index 000000000000..fc227b099ec8 --- /dev/null +++ b/desktop/test/deployment/version/version_none/plain.oxt diff --git a/desktop/unx/source/makefile.mk b/desktop/unx/source/makefile.mk new file mode 100644 index 000000000000..494477a0c4d1 --- /dev/null +++ b/desktop/unx/source/makefile.mk @@ -0,0 +1,64 @@ +# +# Version: MPL 1.1 / GPLv3+ / LGPLv3+ +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Initial Developer of the Original Code is +# Novell, Inc. +# Portions created by the Initial Developer are Copyright (C) 2010 the +# Initial Developer. All Rights Reserved. +# +# Contributor(s): Jan Holesovsky <kendy@novell.com> +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 3 or later (the "GPLv3+"), or +# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), +# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable +# instead of those above. +# +PRJ=..$/.. +PRJNAME=desktop +TARGET=oosplash + +NO_DEFAULT_STL=TRUE + +.INCLUDE : settings.mk + +.IF "$(ENABLE_UNIX_QUICKSTARTER)"!="TRUE" + +dummy: + @echo "Unix quickstarter disabled" + +.ELSE + +STDLIB= + +CFLAGS+=$(LIBPNG_CFLAGS) + +OBJFILES= \ + $(OBJ)$/splashx.obj \ + $(OBJ)$/start.obj + +APP1TARGET = $(TARGET) +APP1RPATH = BRAND +APP1OBJS = $(OBJFILES) +APP1LIBSALCPPRT= +APP1CODETYPE = C +APP1STDLIBS = $(SALLIB) -lX11 $(LIBPNG_LIBS) +.IF "$(OS)"=="SOLARIS" +APP1STDLIBS+= -lsocket +.ENDIF + +.ENDIF # ENABLE_UNIX_QUICKSTARTER + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/desktop/unx/source/officeloader/makefile.mk b/desktop/unx/source/officeloader/makefile.mk new file mode 100644 index 000000000000..050da981e88d --- /dev/null +++ b/desktop/unx/source/officeloader/makefile.mk @@ -0,0 +1,47 @@ +#************************************************************************* +# +# 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=officeloader +LIBTARGET=NO + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +OBJFILES = \ + $(OBJ)$/officeloader.obj + +# --- Targets ------------------------------------------------------ + + +.INCLUDE : target.mk + diff --git a/desktop/unx/source/officeloader/officeloader.cxx b/desktop/unx/source/officeloader/officeloader.cxx new file mode 100644 index 000000000000..89147d76f09e --- /dev/null +++ b/desktop/unx/source/officeloader/officeloader.cxx @@ -0,0 +1,113 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 <sal/main.h> +#include <osl/process.h> +#include <rtl/ustring.hxx> + +#include "../../../source/inc/exithelper.hxx" + +using namespace rtl; +using namespace desktop; + +SAL_IMPLEMENT_MAIN() +{ + oslProcess process; + oslProcessError error; + + OUString sExecutableFile; + rtl_uString **pCommandArgs; + sal_uInt32 nCommandArgs; + + osl_getExecutableFile( &sExecutableFile.pData ); + + sExecutableFile += OUString( RTL_CONSTASCII_USTRINGPARAM(".bin") ); + + nCommandArgs = osl_getCommandArgCount(); + pCommandArgs = new rtl_uString *[nCommandArgs]; + + for ( sal_uInt32 i = 0; i < nCommandArgs; i++ ) + { + pCommandArgs[i] = NULL; + osl_getCommandArg( i, &pCommandArgs[i] ); + } + + bool bRestart = false; + bool bFirstRun = true; + oslProcessExitCode exitcode = 255; + + do { + error = osl_executeProcess( + sExecutableFile.pData, + bFirstRun ? pCommandArgs : NULL, + bFirstRun ? nCommandArgs : 0, + 0, + NULL, + NULL, + NULL, + 0, + &process + ); + + if ( osl_Process_E_None == error ) + { + oslProcessInfo info; + + info.Size = sizeof(info); + + error = osl_joinProcess( process ); + if ( osl_Process_E_None != error ) + break; + + error = osl_getProcessInfo( process, osl_Process_EXITCODE, &info ); + if ( osl_Process_E_None != error ) + break; + + if ( info.Fields & osl_Process_EXITCODE ) + { + exitcode = info.Code; + bRestart = (ExitHelper::E_CRASH_WITH_RESTART == exitcode || ExitHelper::E_NORMAL_RESTART == exitcode); + } + else + break; + + osl_freeProcessHandle( process ); + + } + + bFirstRun = false; + + } while ( bRestart ); + + return exitcode; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/unx/source/splashx.c b/desktop/unx/source/splashx.c new file mode 100644 index 000000000000..6e7088b42ca4 --- /dev/null +++ b/desktop/unx/source/splashx.c @@ -0,0 +1,625 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Novell, Inc. + * Portions created by the Initial Developer are Copyright (C) 2010 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): Jan Holesovsky <kendy@novell.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ +#include <X11/Xlib.h> +#include <X11/Xatom.h> +#include <X11/Xutil.h> + +#define USE_LIBPNG + +#include "osl/endian.h" +#include <fcntl.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#ifdef USE_LIBPNG +# include <png.h> +#endif + +#include "splashx.h" + +typedef struct { + unsigned char b, g, r; +} color_t; + +#define WINDOW_WIDTH 440 +#define WINDOW_HEIGHT 299 + +#define PROGRESS_XOFFSET 12 +#define PROGRESS_YOFFSET 18 +#define PROGRESS_BARSPACE 2 + +static Display *display = NULL; +static int screen; +static int depth; +static Visual *visual = NULL; + +static int width = WINDOW_WIDTH; +static int height = WINDOW_HEIGHT; + +static Colormap color_map; +static Window win; +static GC gc; + +// Progress bar values +// taken from desktop/source/splash/splash.cxx +static int tlx = 212; +static int tly = 216; +static int barwidth = 263; +static int barheight = 8; +static int barspace = PROGRESS_BARSPACE; +static color_t barcol = { 18, 202, 157 }; +static color_t framecol = { 0xD3, 0xD3, 0xD3 }; + +static XColor barcolor; +static XColor framecolor; + +static unsigned char **bitmap_rows = NULL; + +#define BMP_HEADER_LEN 14 +#define WIN_INFO_LEN 40 + +#define UINT8( x ) ( (unsigned int)( ( (uint8_t *)( x ) )[0] ) ) + +#define UINT16( x ) ( ( (unsigned int)( ( (uint8_t *)( x ) )[0] ) ) + \ + ( ( (unsigned int)( ( (uint8_t *)( x ) )[1] ) ) << 8 ) ) + +#define UINT32( x ) ( ( (unsigned int)( ( (uint8_t *)( x ) )[0] ) ) + \ + ( ( (unsigned int)( ( (uint8_t *)( x ) )[1] ) ) << 8 ) + \ + ( ( (unsigned int)( ( (uint8_t *)( x ) )[2] ) ) << 16 ) + \ + ( ( (unsigned int)( ( (uint8_t *)( x ) )[3] ) ) << 24 ) ) + +#define MAX( x, y ) ( ( (x) > (y) )? (x): (y) ) + +#define LOAD_FAILURE( msg ) \ + { \ + fprintf( stderr, "%s: " msg, filename ); \ + close( fd ); \ + return 0; \ + } + +#ifdef USE_LIBPNG + +/* libpng-1.2.41 */ +#ifndef PNG_TRANSFORM_GRAY_TO_RGB +# define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 +#endif + +int splash_load_bmp( const char *filename ) +{ + FILE *file; + png_structp png_ptr; + png_infop info_ptr; + + if ( !(file = fopen( filename, "r" ) ) ) + return 0; + + png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 ); + info_ptr = png_create_info_struct(png_ptr); + png_init_io( png_ptr, file ); + + if( setjmp( png_jmpbuf( png_ptr ) ) ) + { + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + fclose( file ); + return 0; + } + + png_read_png( png_ptr, info_ptr, + PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_ALPHA | + PNG_TRANSFORM_GRAY_TO_RGB | PNG_TRANSFORM_BGR, NULL); + + bitmap_rows = png_get_rows( png_ptr, info_ptr ); + width = info_ptr->width; + height = info_ptr->height; + +#if 0 + { + int i,j; + for (j = 0; j < height; j++) { + for (i = 0; i < width*3; i++) { + fprintf (stderr, "%.2x", bitmap_rows[j][i]); + } + fprintf (stderr, "\n"); + } + } +#endif + + return 1; +} +#else + +/* Load the specified Windows 24bit BMP to 'bitmap' + * Return: 1 - success, 0 - failure */ +int splash_load_bmp( const char *filename ) +{ + int fd = open( filename, O_RDONLY ); + if ( fd < 0 ) + return 0; + + char file_header[ BMP_HEADER_LEN ]; + + if ( read( fd, file_header, BMP_HEADER_LEN ) != BMP_HEADER_LEN || file_header[0] != 'B' || file_header[1] != 'M' ) + LOAD_FAILURE( "Not a bitmap.\n" ); + +/* int file_size = UINT32( file_header + 2 ); */ + + char info_header[ WIN_INFO_LEN ]; + if ( read( fd, info_header, 4 ) != 4 ) + LOAD_FAILURE( "Unable to read the header.\n" ); + + int header_size = UINT32( info_header ); + if ( header_size != WIN_INFO_LEN ) + LOAD_FAILURE( "Not a Windows bitmap.\n" ); + + if ( read( fd, info_header + 4, WIN_INFO_LEN - 4 ) != WIN_INFO_LEN - 4 ) + LOAD_FAILURE( "The header ended too early.\n" ); + + width = UINT32( info_header + 4 ); + height = UINT32( info_header + 8 ); + + int bits = UINT16( info_header + 14 ); + int compression = UINT16( info_header + 16 ); + + if ( bits != 24 ) + LOAD_FAILURE( "Just 24 bpp bitmaps are supported.\n" ); + + if ( compression != 0 ) + LOAD_FAILURE( "Just uncompressed bitmaps are supported.\n" ); + + size_t bitmap_size = width * height * 3; + unsigned char *bitmap = malloc( bitmap_size ); + if ( bitmap == NULL ) + LOAD_FAILURE( "Cannot allocate memory for the data.\n" ); + + if ( read( fd, bitmap, bitmap_size ) != bitmap_size ) + LOAD_FAILURE( "Cannot read the bitmap data.\n" ); + + bitmap_rows = malloc (sizeof (unsigned char*) * height); + int i; + for (i = 0; i < height; i++) + bitmap_rows[i] = bitmap + (width * height * 3) - width * 3 * (i + 1); + + close( fd ); + return 1; +} +#endif + +static void setup_color( int val[3], color_t *col ) +{ + if ( val[0] < 0 || val[1] < 0 || val[2] < 0 ) + return; + +#define CONVERT_COLOR( from,to ) if ( from < 0 ) to = 0; else if ( from > 255 ) to = 255; else to = from; + CONVERT_COLOR( val[0], col->r ); + CONVERT_COLOR( val[1], col->g ); + CONVERT_COLOR( val[2], col->b ); +#undef CONVERT_COLOR +} + +// setup +void splash_setup( int barc[3], int framec[3], int posx, int posy, int w, int h ) +{ + if ( width <= 500 ) + { + barwidth = width - ( 2 * PROGRESS_XOFFSET ); + barheight = 6; + tlx = PROGRESS_XOFFSET; + tly = height - PROGRESS_YOFFSET; + + barcol.r = 0; + barcol.g = 0; + barcol.b = 128; + } + + if ( posx >= 0 ) + tlx = posx; + if ( posy >= 0 ) + tly = posy; + if ( w >= 0 ) + barwidth = w; + if ( h >= 0 ) + barheight = h; + + setup_color( barc, &barcol ); + setup_color( framec, &framecol ); +} + +// Universal shift: bits >= 0 - left, otherwise right +#define SHIFT( x, bits ) ( ( (bits) >= 0 )? ( (x) << (bits) ): ( (x) >> -(bits) ) ) + +// Position of the highest bit (more or less integer log2) +inline int HIGHEST_BIT( unsigned long x ) +{ + int i = 0; + for ( ; x; ++i ) + x >>= 1; + + return i; +} + +// Number of bits set to 1 +inline int BITS( unsigned long x ) +{ + int i = 0; + for ( ; x; x >>= 1 ) + if ( x & 1UL ) + ++i; + + return i; +} + +// Set 'bitmap' as the background of our 'win' window +static void create_pixmap() +{ + if ( !bitmap_rows ) + return; + + Pixmap pixmap = XCreatePixmap( display, win, width, height, depth ); + + unsigned long value_mask = 0; + XGCValues values; + GC pixmap_gc = XCreateGC( display, pixmap, value_mask, &values ); + + if ( visual->class == TrueColor ) + { + unsigned long red_mask = visual->red_mask; + unsigned long green_mask = visual->green_mask; + unsigned long blue_mask = visual->blue_mask; + + unsigned long red_delta_mask = ( 1UL << ( 8 - BITS( red_mask ) ) ) - 1; + unsigned long green_delta_mask = ( 1UL << ( 8 - BITS( green_mask ) ) ) - 1; + unsigned long blue_delta_mask = ( 1UL << ( 8 - BITS( blue_mask ) ) ) - 1; + + int red_shift = HIGHEST_BIT( red_mask ) - 8; + int green_shift = HIGHEST_BIT( green_mask ) - 8; + int blue_shift = HIGHEST_BIT( blue_mask ) - 8; + + XImage *image = XCreateImage( display, visual, depth, ZPixmap, + 0, NULL, width, height, 32, 0 ); + + int bytes_per_line = image->bytes_per_line; + int bpp = image->bits_per_pixel; + int byte_order = image->byte_order; + int machine_byte_order; +#if defined( _LITTLE_ENDIAN ) + machine_byte_order = LSBFirst; +#elif defined( _BIG_ENDIAN ) + machine_byte_order = MSBFirst; +#else + { + fprintf( stderr, "Unsupported machine endianity.\n" ); + XFreeGC( display, pixmap_gc ); + XFreePixmap( display, pixmap ); + XDestroyImage( image ); + return; + } +#endif + + char *data = malloc( height * bytes_per_line ); + image->data = data; + + // The following dithers & converts the color_t color to one + // acceptable for the visual +#define COPY_IN_OUT( pix_size, code ) \ + { \ + int x, y; \ + for ( y = 0; y < height; ++y ) \ + { \ + unsigned long red_delta = 0, green_delta = 0, blue_delta = 0; \ + color_t *in = (color_t *)bitmap_rows[y]; \ + for ( x = 0; x < width; ++x, ++in ) \ + { \ + unsigned long red = in->r + red_delta; \ + unsigned long green = in->g + green_delta; \ + unsigned long blue = in->b + blue_delta; \ + red_delta = red & red_delta_mask; \ + green_delta = green & green_delta_mask; \ + blue_delta = blue & blue_delta_mask; \ + if ( red > 255 ) \ + red = 255; \ + if ( green > 255 ) \ + green = 255; \ + if ( blue > 255 ) \ + blue = 255; \ + unsigned long pixel = \ + ( SHIFT( red, red_shift ) & red_mask ) | \ + ( SHIFT( green, green_shift ) & green_mask ) | \ + ( SHIFT( blue, blue_shift ) & blue_mask ); \ + code \ + } \ + } \ + } + + char *out = data; + + if ( bpp == 32 ) + { + if ( machine_byte_order == byte_order ) + COPY_IN_OUT( 4, *( (uint32_t *)out ) = (uint32_t)pixel; out += 4; ) + else + COPY_IN_OUT( 4, uint32_t tmp = pixel; + *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 3 ); + *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) + 2 ); + *( (uint8_t *)out + 2 ) = *( (uint8_t *)(&tmp) + 1 ); + *( (uint8_t *)out + 3 ) = *( (uint8_t *)(&tmp) ); + out += 4; ) + } + else if ( bpp == 24 ) + { + if ( machine_byte_order == byte_order && byte_order == LSBFirst ) + COPY_IN_OUT( 3, *( (color_t *)out ) = *( (color_t *)( &pixel ) ); out += 3; ) + if ( machine_byte_order == byte_order && byte_order == MSBFirst ) + COPY_IN_OUT( 3, uint32_t tmp = pixel; + *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 1 ); + *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) + 2 ); + *( (uint8_t *)out + 2 ) = *( (uint8_t *)(&tmp) + 3 ); + out += 3; ) + else + COPY_IN_OUT( 3, uint32_t tmp = pixel; + *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 3 ); + *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) + 2 ); + *( (uint8_t *)out + 2 ) = *( (uint8_t *)(&tmp) + 1 ); + out += 3; ) + } + else if ( bpp == 16 ) + { + if ( machine_byte_order == byte_order ) + COPY_IN_OUT( 2, *( (uint16_t *)out ) = (uint16_t)pixel; out += 2; ) + else + COPY_IN_OUT( 2, uint16_t tmp = pixel; + *( (uint8_t *)out ) = *( (uint8_t *)(&tmp) + 1 ); + *( (uint8_t *)out + 1 ) = *( (uint8_t *)(&tmp) ); + out += 2; ); + } + else if ( bpp == 8 ) + { + COPY_IN_OUT( 1, *( (uint8_t *)out ) = (uint8_t)pixel; ++out; ) + } + else + { + fprintf( stderr, "Unsupported depth: %d bits per pixel.\n", bpp ); + XFreeGC( display, pixmap_gc ); + XFreePixmap( display, pixmap ); + XDestroyImage( image ); + return; + } + +#undef COPY_IN_OUT + + XPutImage( display, pixmap, pixmap_gc, image, 0, 0, 0, 0, width, height ); + XDestroyImage( image ); + } + else //if ( depth == 1 || visual->class == DirectColor ) + { + // FIXME Something like the following, but faster ;-) - XDrawPoint is not + // a good idea... + int x, y; + for ( y = 0; y < height; ++y ) + { + color_t *color = (color_t *)&bitmap_rows[y]; + + int delta = 0; + for ( x = 0; x < width; ++x, ++color ) + { + int rnd = (int)( ( (long)( random() - RAND_MAX/2 ) * 32000 )/RAND_MAX ); + int luminance = delta + rnd + 299 * (int)color->r + 587 * (int)color->g + 114 * (int)color->b; + + if ( luminance < 128000 ) + { + XSetForeground( display, pixmap_gc, BlackPixel( display, screen ) ); + delta = luminance; + } + else + { + XSetForeground( display, pixmap_gc, WhitePixel( display, screen ) ); + delta = luminance - 255000; + } + + XDrawPoint( display, pixmap, pixmap_gc, x, y ); + } + } + } + + XSetWindowBackgroundPixmap( display, win, pixmap ); + + XFreeGC( display, pixmap_gc ); + XFreePixmap( display, pixmap ); +} + +// The old method of hiding the window decorations +static void suppress_decorations_motif() +{ + struct { + unsigned long flags, functions, decorations; + long input_mode; + unsigned long status; + } mwmhints; + + Atom a = XInternAtom( display, "_MOTIF_WM_HINTS", False ); + + mwmhints.flags = 15; // functions, decorations, input_mode, status + mwmhints.functions = 2; // ? + mwmhints.decorations = 0; + mwmhints.input_mode = 0; + + XChangeProperty( display, win, a, a, 32, + PropModeReplace, (unsigned char*)&mwmhints, 5 ); +} + +// This is a splash, set it as such. +// If it fails, just hide the decorations... +static void suppress_decorations() +{ + Atom atom_type = XInternAtom( display, "_NET_WM_WINDOW_TYPE", True ); + Atom atom_splash = XInternAtom( display, "_NET_WM_WINDOW_TYPE_SPLASH", True ); + + if ( atom_type != None && atom_splash != None ) + XChangeProperty( display, win, atom_type, XA_ATOM, 32, + PropModeReplace, (unsigned char*)&atom_splash, 1 ); + //else + suppress_decorations_motif(); // FIXME: Unconditional until Metacity/compiz's SPLASH handling is fixed +} + +// Create the window +// Return: 1 - success, 0 - failure +int splash_create_window( int argc, char** argv ) +{ + char *display_name = NULL; + int i; + for ( i = 0; i < argc; i++ ) + { + if ( !strcmp( argv[i], "-display" ) || !strcmp( argv[i], "--display" ) ) + display_name = ( i + 1 < argc )? argv[i+1]: NULL; + } + + if ( !display_name ) + display_name = getenv( "DISPLAY" ); + + // init display + display = XOpenDisplay( display_name ); + if ( !display ) + { + fprintf( stderr, "Failed to open display\n" ); + return 0; + } + + // create the window + screen = DefaultScreen( display ); + depth = DefaultDepth( display, screen ); + color_map = DefaultColormap( display, screen ); + visual = DefaultVisual( display, screen ); + + Window root_win = RootWindow( display, screen ); + int display_width = DisplayWidth( display, screen ); + int display_height = DisplayHeight( display, screen ); + + win = XCreateSimpleWindow( display, root_win, + ( display_width - width ) / 2, ( display_height - height ) / 2, + width, height, 0, + BlackPixel( display, screen ), BlackPixel( display, screen ) ); + + XSetWindowColormap( display, win, color_map ); + + // setup colors +#define FILL_COLOR( xcol,col ) xcol.red = 256*col.r; xcol.green = 256*col.g; xcol.blue = 256*col.b; + FILL_COLOR( barcolor, barcol ); + FILL_COLOR( framecolor, framecol ); +#undef FILL_COLOR + + XAllocColor( display, color_map, &barcolor ); + XAllocColor( display, color_map, &framecolor ); + + // not resizable, no decorations, etc. + unsigned long value_mask = 0; + XGCValues values; + gc = XCreateGC( display, win, value_mask, &values ); + + XSizeHints size_hints; + size_hints.flags = PPosition | PSize | PMinSize | PMaxSize; + size_hints.min_width = width; + size_hints.max_width = width; + size_hints.min_height = height; + size_hints.max_height = height; + + char *name = "OpenOffice.org"; + char *icon = "icon"; // FIXME + + XSetStandardProperties( display, win, name, icon, None, + 0, 0, &size_hints ); + + // the actual work + suppress_decorations(); + create_pixmap(); + + // show it + XSelectInput( display, win, 0 ); + XMapWindow( display, win ); + + return 1; +} + +// Re-draw & process the events +// Just throwing them away - we do not need anything more... +static void process_events() +{ + XEvent xev; + int num_events; + + XFlush( display ); + num_events = XPending( display ); + while ( num_events > 0 ) + { + num_events--; + XNextEvent( display, &xev ); + //process_event(xev); + } +} + +// Draw the progress +void splash_draw_progress( int progress ) +{ + // sanity + if ( progress < 0 ) + progress = 0; + if ( progress > 100 ) + progress = 100; + + // draw progress... + int length = ( progress * barwidth / 100 ) - ( 2 * barspace ); + if ( length < 0 ) + length = 0; + + // border + XSetForeground( display, gc, framecolor.pixel ); + XDrawRectangle( display, win, gc, + tlx, tly, + barwidth, barheight ); + + // progress bar + XSetForeground( display, gc, barcolor.pixel ); + XFillRectangle( display, win, gc, + tlx + barspace, tly + barspace, + length + 1, barheight - 2*barspace + 1 ); + + // pending events + process_events(); +} + +// Close the window & cleanup +void splash_close_window() +{ + XCloseDisplay( display ); + + // leak it is faster + bitmap_rows = NULL; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/unx/source/splashx.h b/desktop/unx/source/splashx.h new file mode 100644 index 000000000000..537034c6efc8 --- /dev/null +++ b/desktop/unx/source/splashx.h @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Novell, Inc. + * Portions created by the Initial Developer are Copyright (C) 2010 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): Jan Holesovsky <kendy@novell.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ +#ifndef _SPLASHX_H +#define _SPLASHX_H + +#ifdef __cplusplus +extern "C" { +#endif + +// Load the specified bitmap so we can have as a background of the +// splash. +// +// Note: Must be called before the create_window(), otherwise there will be no +// image in the splash, just black rectangle. +// +// Return: 1 - success, 0 - failure (non-existing, etc.) +int splash_load_bmp( const char *filename ); + +// Init some of the values +// If not called, the defaults are used +// barc, framec - colors, posx, posy - position, w, h - size +void splash_setup( int barc[3], int framec[3], int posx, int posy, int w, int h ); + +// Create the splash window +// Return: 1 - success, 0 - failure +int splash_create_window( int argc, char** argv ); + +// Destroy the splash window +void splash_close_window(); + +// Update the progress bar +void splash_draw_progress( int progress ); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _SPLASHX_H + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/unx/source/start.c b/desktop/unx/source/start.c new file mode 100644 index 000000000000..dc28614fc6f1 --- /dev/null +++ b/desktop/unx/source/start.c @@ -0,0 +1,861 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Novell, Inc. + * Portions created by the Initial Developer are Copyright (C) 2010 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): Jan Holesovsky <kendy@novell.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ +#include <signal.h> +#include <unistd.h> +#include <limits.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <sys/un.h> +#include <sys/poll.h> +#include <fcntl.h> +#include <stdio.h> +#include <libgen.h> + +#include <osl/nlsupport.h> +#include <osl/process.h> +#include <osl/thread.h> +#include <rtl/bootstrap.h> +#include <rtl/digest.h> +#include <rtl/ustrbuf.h> +#include <sal/main.h> + +#include "splashx.h" + +/* + * magic argument - if passed, not passed onto soffice.bin but we exit + * immediately if we fail to control the process. Used to avoid doing + * an un-conditional pagein + */ +#define QSEND_AND_REPORT "-qsend-and-report" + +#define IMG_SUFFIX ".png" +#define PIPEDEFAULTPATH "/tmp" +#define PIPEALTERNATEPATH "/var/tmp" + +typedef enum { ProgressContinue, ProgressRestart, ProgressExit } ProgressStatus; + +/* Easier conversions: rtl_uString to rtl_String */ +static rtl_String * +ustr_to_str( rtl_uString *pStr ) +{ + rtl_String *pOut = NULL; + + rtl_uString2String( &pOut, rtl_uString_getStr( pStr ), + rtl_uString_getLength( pStr ), osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS ); + + return pOut; +} + +/* Easier conversions: char * to rtl_uString */ +static rtl_uString * +charp_to_ustr( const char *pStr ) +{ + rtl_uString *pOut = NULL; + + rtl_string2UString( &pOut, pStr, strlen( pStr ), osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS ); + + return pOut; +} + +/* Easier debugging of rtl_uString values. */ +#if OSL_DEBUG_LEVEL > 0 +static void +ustr_debug( const char *pMessage, rtl_uString *pStr ) +{ + rtl_String *pOut = ustr_to_str( pStr ); + + fprintf( stderr, "%s: %s\n", pMessage, rtl_string_getStr( pOut ) ); + + rtl_string_release( pOut ); + return; +} +#else +#define ustr_debug( a, b ) {} +#endif + +/* Path of the application. */ +static rtl_uString * +get_app_path( const char *pAppExec ) +{ + char pRealPath[PATH_MAX]; + rtl_uString *pResult; + + char *pPath = strdup( pAppExec ); + pPath = dirname( pPath ); + + realpath( pPath, pRealPath ); + pResult = charp_to_ustr( pRealPath ); + free( pPath ); + + return pResult; +} + +/* Compute the OOo md5 hash from 'pText' */ +static rtl_uString * +get_md5hash( rtl_uString *pText ) +{ + rtl_uString *pResult = NULL; + sal_Int32 nCapacity = 100; + +#if OSL_DEBUG_LEVEL > 0 + fprintf (stderr, "Generate pipe md5 for '%s'\n", ustr_to_str (pText)->buffer); +#endif + + if ( !pText ) + return NULL; + + unsigned char *pData = (unsigned char *)rtl_uString_getStr( pText ); + sal_uInt32 nSize = rtl_uString_getLength( pText ) * sizeof( sal_Unicode ); + if ( !pData ) + return NULL; + + rtlDigest digest = rtl_digest_create( rtl_Digest_AlgorithmMD5 ); + if ( digest == 0 ) + return NULL; + + sal_uInt32 md5_key_len = rtl_digest_queryLength( digest ); + sal_uInt8 *md5_buf = (sal_uInt8 *)calloc( md5_key_len, sizeof( sal_uInt8 ) ); + + rtl_digest_init( digest, pData , nSize ); + rtl_digest_update( digest, pData, nSize ); + rtl_digest_get( digest, md5_buf, md5_key_len ); + rtl_digest_destroy( digest ); + + /* create hex-value string from the MD5 value to keep + the string size minimal */ + rtl_uString_new_WithLength( &pResult, nCapacity ); + sal_uInt32 i = 0; + for ( ; i < md5_key_len; ++i ) + { + char val[3]; + snprintf( val, 3, "%x", md5_buf[i] ); /* sic! we ignore some of the 0's */ + + rtl_uStringbuffer_insert_ascii( &pResult, &nCapacity, rtl_uString_getLength( pResult ), + val, strlen( val ) ); + } + + /* cleanup */ + free( md5_buf ); + + return pResult; +} + +/* Construct the pipe name */ +static rtl_uString * +get_pipe_path( rtl_uString *pAppPath ) +{ + rtl_uString *pPath = NULL, *pTmp = NULL, *pUserInstallation = NULL; + rtl_uString *pResult = NULL, *pBasePath = NULL, *pAbsUserInstallation = NULL; + + /* setup bootstrap filename */ + rtl_uString_newFromAscii( &pPath, "file://" ); + rtl_uString_newConcat( &pPath, pPath, pAppPath ); + rtl_uString_newFromAscii( &pTmp, "/" ); + rtl_uString_newConcat( &pPath, pPath, pTmp ); + rtl_uString_newFromAscii( &pTmp, SAL_CONFIGFILE( "bootstrap" ) ); + rtl_uString_newConcat( &pPath, pPath, pTmp ); + + ustr_debug( "bootstap", pPath ); + + /* read userinstallation value */ + rtlBootstrapHandle handle = rtl_bootstrap_args_open( pPath ); + + rtl_uString_newFromAscii( &pTmp, "UserInstallation" ); + rtl_bootstrap_get_from_handle( handle, pTmp, &pUserInstallation, NULL ); + + rtl_bootstrap_args_close( handle ); + + /* turn it into an absolute path - unwinding symlinks etc. */ + if ( osl_getProcessWorkingDir (&pBasePath) || + osl_getAbsoluteFileURL( pBasePath, pUserInstallation, &pAbsUserInstallation ) ) + rtl_uString_newFromString (&pAbsUserInstallation, pUserInstallation); + + /* create the pipe name */ + ustr_debug( "user installation", pAbsUserInstallation ); + rtl_uString *pMd5hash = get_md5hash( pAbsUserInstallation ); + if ( !pMd5hash ) + rtl_uString_new( &pMd5hash ); + + if ( access( PIPEDEFAULTPATH, R_OK|W_OK ) == 0 ) + rtl_uString_newFromAscii( &pResult, PIPEDEFAULTPATH ); + else + rtl_uString_newFromAscii( &pResult, PIPEALTERNATEPATH ); + + rtl_uString_newFromAscii( &pTmp, "/OSL_PIPE_" ); + rtl_uString_newConcat( &pResult, pResult, pTmp ); + + sal_Unicode pUnicode[RTL_USTR_MAX_VALUEOFINT32]; + rtl_ustr_valueOfInt32( pUnicode, (int)getuid(), 10 ); + rtl_uString_newFromStr( &pTmp, pUnicode ); + rtl_uString_newConcat( &pResult, pResult, pTmp ); + + rtl_uString_newFromAscii( &pTmp, "_SingleOfficeIPC_" ); + rtl_uString_newConcat( &pResult, pResult, pTmp ); + + rtl_uString_newConcat( &pResult, pResult, pMd5hash ); + + ustr_debug( "result", pResult ); + + /* cleanup */ + rtl_uString_release( pPath ); + rtl_uString_release( pTmp ); + rtl_uString_release( pBasePath ); + rtl_uString_release( pUserInstallation ); + rtl_uString_release( pAbsUserInstallation ); + + return pResult; +} + +/* Get fd of the pipe of the already running OOo. */ +static int +connect_pipe( rtl_uString *pPipePath ) +{ + int fd; + size_t len; + struct sockaddr_un addr; + + rtl_String *pPipeStr = ustr_to_str( pPipePath ); + + memset( &addr, 0, sizeof( addr ) ); + + if ( ( fd = socket( AF_UNIX, SOCK_STREAM, 0 ) ) < 0 ) + return fd; + + fcntl( fd, F_SETFD, FD_CLOEXEC ); + + addr.sun_family = AF_UNIX; + strncpy( addr.sun_path, rtl_string_getStr( pPipeStr ), sizeof( addr.sun_path ) ); + rtl_string_release( pPipeStr ); + +/* cut / paste from osl's pipe.c */ +#if defined(FREEBSD) + len = SUN_LEN( &addr ); +#else + len = sizeof( addr ); +#endif + + if ( connect( fd, (struct sockaddr *)&addr, len ) < 0 ) + return -1; + + return fd; +} + +/* Escape: "," -> "\\,", "\0" -> "\\0", "\\" -> "\\\\" */ +static rtl_uString * +escape_path( rtl_uString *pToEscape ) +{ + rtl_uString *pBuffer = NULL; + sal_Int32 nCapacity = 1000; + + rtl_uString_new_WithLength( &pBuffer, nCapacity ); + + sal_Int32 i = 0; + sal_Int32 nEscapeLength = rtl_uString_getLength( pToEscape ); + for ( ; i < nEscapeLength; ++i ) + { + sal_Unicode c = pToEscape->buffer[i]; + switch ( c ) + { + case (sal_Unicode)'\0': + rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + RTL_CONSTASCII_STRINGPARAM( "\\0" ) ); + break; + case (sal_Unicode)',': + rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + RTL_CONSTASCII_STRINGPARAM( "\\," ) ); + break; + case (sal_Unicode)'\\': + rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + RTL_CONSTASCII_STRINGPARAM( "\\\\" ) ); + break; + default: + rtl_uStringbuffer_insert( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + &c, 1 ); + } + } + + return pBuffer; +} + +/* Send args to the OOo instance (using the 'fd' file descriptor) */ +static sal_Bool +send_args( int fd, rtl_uString *pCwdPath ) +{ + rtl_uString *pBuffer = NULL, *pTmp = NULL; + sal_Int32 nCapacity = 1000; + rtl_String *pOut = NULL; + sal_Bool bResult; + size_t nLen; + rtl_uString *pEscapedCwdPath = escape_path( pCwdPath ); + + rtl_uString_new_WithLength( &pBuffer, nCapacity ); + rtl_uString_new( &pTmp ); + + rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + RTL_CONSTASCII_STRINGPARAM( "InternalIPC::Arguments" ) ); + + if ( rtl_uString_getLength( pEscapedCwdPath ) ) + { + rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + RTL_CONSTASCII_STRINGPARAM( "1" ) ); + rtl_uStringbuffer_insert( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + rtl_uString_getStr( pEscapedCwdPath ), + rtl_uString_getLength( pEscapedCwdPath ) ); + } + else + rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + RTL_CONSTASCII_STRINGPARAM( "0" ) ); + + sal_Bool bDontConvertNext = sal_False; + sal_uInt32 nArg; + sal_uInt32 nArgCount = osl_getCommandArgCount(); + for ( nArg = 0; nArg < nArgCount; ++nArg ) + { + rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + ",", 1 ); + + osl_getCommandArg( nArg, &pTmp ); + + if ( rtl_uString_getLength( pTmp ) == 0 || + !rtl_ustr_ascii_compare( pTmp->buffer, QSEND_AND_REPORT ) ) + continue; + + // this is not a param, we have to prepend filenames with file:// + // FIXME: improve the check + if ( ( pTmp->buffer[0] != (sal_Unicode)'-' ) && + ( rtl_ustr_indexOfAscii_WithLength( pTmp->buffer, pTmp->length, "slot:", 5 /* length */ ) ) ) + { + sal_Int32 nFirstColon = rtl_ustr_indexOfChar_WithLength( pTmp->buffer, pTmp->length, ':' ); + sal_Int32 nFirstSlash = rtl_ustr_indexOfChar_WithLength( pTmp->buffer, pTmp->length, '/' ); + + // check that pTmp is not an URI yet + if ( nFirstColon < 1 || ( nFirstSlash != nFirstColon + 1 ) ) + { + // some of the switches (currently just -pt) don't want to + // have the filenames as URIs + if ( !bDontConvertNext ) + osl_getAbsoluteFileURL( pCwdPath, pTmp, &pTmp ); + } + } + + // don't convert filenames with some of the switches + // (currently just -pt) + bDontConvertNext = !rtl_ustr_ascii_compareIgnoreAsciiCase( pTmp->buffer, "-pt" ); + + rtl_uString *pEscapedTmp = escape_path( pTmp ); + + rtl_uStringbuffer_insert( &pBuffer, &nCapacity, + rtl_uString_getLength( pBuffer ), + rtl_uString_getStr( pEscapedTmp ), + rtl_uString_getLength( pEscapedTmp ) ); + + rtl_uString_release( pEscapedTmp ); + } + + ustr_debug( "Pass args", pBuffer ); + + pOut = ustr_to_str( pBuffer ); + + nLen = rtl_string_getLength( pOut ) + 1; + bResult = ( write( fd, rtl_string_getStr( pOut ), nLen ) == (ssize_t) nLen ); + + /* cleanup */ + rtl_uString_release( pEscapedCwdPath ); + rtl_uString_release( pBuffer ); + rtl_uString_release( pTmp ); + rtl_string_release( pOut ); + + return bResult; +} + +static void +load_splash_image( rtl_uString *pUAppPath ) +{ + char *pBuffer, *pSuffix, *pLocale; + int nLocSize; + rtl_Locale *pLoc = NULL; + rtl_String *pLang, *pCountry, *pAppPath; + + osl_getProcessLocale (&pLoc); + pLang = ustr_to_str (pLoc->Language); + pCountry = ustr_to_str (pLoc->Country); + + nLocSize = strlen (pLang->buffer) + strlen (pCountry->buffer) + 8; + pLocale = malloc (nLocSize); + pLocale[0] = '-'; + strcpy (pLocale + 1, pLang->buffer); + strcat (pLocale, "_"); + strcat (pLocale, pCountry->buffer); + + pAppPath = ustr_to_str (pUAppPath); + pBuffer = malloc (pAppPath->length + nLocSize + 256); + strcpy (pBuffer, pAppPath->buffer); + pSuffix = pBuffer + pAppPath->length; + + strcpy (pSuffix, "/edition/intro"); + strcat (pSuffix, pLocale); + strcat (pSuffix, IMG_SUFFIX); + if ( splash_load_bmp( pBuffer ) ) + goto cleanup; + + strcpy (pSuffix, "/edition/intro" IMG_SUFFIX); + if ( splash_load_bmp( pBuffer ) ) + goto cleanup; + + strcpy (pSuffix, "/intro"); + strcat (pSuffix, pLocale); + strcat (pSuffix, IMG_SUFFIX); + if ( splash_load_bmp( pBuffer ) ) + goto cleanup; + + strcpy (pSuffix, "/intro" IMG_SUFFIX); + if ( splash_load_bmp( pBuffer ) ) + goto cleanup; + + fprintf (stderr, "Failed to find intro image\n"); + + cleanup: + free (pLocale); + free (pBuffer); +} + +/* Fill 'array' with values of the key 'name'. + Its value is a comma delimited list of integers */ +static void +get_bootstrap_value( int *array, int size, rtlBootstrapHandle handle, const char *name ) +{ + rtl_uString *pKey = NULL, *pValue = NULL; + sal_Int32 nIndex = 0; + int i = 0; + + /* get the value from the ini file */ + rtl_uString_newFromAscii( &pKey, name ); + rtl_bootstrap_get_from_handle( handle, pKey, &pValue, NULL ); + + /* the value is several numbers delimited by ',' - parse it */ + if ( rtl_uString_getLength( pValue ) > 0 ) + { + rtl_uString *pToken = NULL; + + for ( ; ( nIndex >= 0 ) && ( i < size ); ++i ) + { + nIndex = rtl_uString_getToken( &pToken, pValue, 0, ',', nIndex ); + array[i] = rtl_ustr_toInt32( rtl_uString_getStr( pToken ), 10 ); + } + + rtl_uString_release( pToken ); + } + + /* cleanup */ + rtl_uString_release( pKey ); + rtl_uString_release( pValue ); +} + +/* Load the colors and size of the splash. */ +static void +load_splash_defaults( rtl_uString *pAppPath, sal_Bool *pInhibitSplash ) +{ + rtl_uString *pSettings = NULL, *pTmp = NULL; + rtlBootstrapHandle handle; + + /* costruct the sofficerc file location */ + rtl_uString_newFromAscii( &pSettings, "file://" ); + rtl_uString_newConcat( &pSettings, pSettings, pAppPath ); + rtl_uString_newFromAscii( &pTmp, "/" ); + rtl_uString_newConcat( &pSettings, pSettings, pTmp ); + rtl_uString_newFromAscii( &pTmp, SAL_CONFIGFILE( "soffice" ) ); + rtl_uString_newConcat( &pSettings, pSettings, pTmp ); + + /* use it as the bootstrap file */ + handle = rtl_bootstrap_args_open( pSettings ); + + int logo[1] = { -1 }, + bar[3] = { -1, -1, -1 }, + frame[3] = { -1, -1, -1 }, + pos[2] = { -1, -1 }, + size[2] = { -1, -1 }; + + /* get the values */ + get_bootstrap_value( logo, 1, handle, "Logo" ); + get_bootstrap_value( bar, 3, handle, "ProgressBarColor" ); + get_bootstrap_value( frame, 3, handle, "ProgressFrameColor" ); + get_bootstrap_value( pos, 2, handle, "ProgressPosition" ); + get_bootstrap_value( size, 2, handle, "ProgressSize" ); + + if ( logo[0] == 0 ) + *pInhibitSplash = sal_True; + + splash_setup( bar, frame, pos[0], pos[1], size[0], size[1] ); + + /* cleanup */ + rtl_bootstrap_args_close( handle ); + rtl_uString_release( pSettings ); + rtl_uString_release( pTmp ); +} + +#define BUFFER_LEN 255 + +/* Read the percent to show in splash. */ +static ProgressStatus +read_percent( int status_fd, int *pPercent ) +{ + static char pBuffer[BUFFER_LEN + 1]; + static char *pNext = pBuffer; + static ssize_t nRead = 0; + + char *pBegin; + char *pIter; + + /* from the last call */ + int nNotProcessed = nRead - ( pNext - pBuffer ); + if ( nNotProcessed >= BUFFER_LEN ) + return sal_False; + + memmove( pBuffer, pNext, nNotProcessed ); + + /* read data */ + nRead = read( status_fd, pBuffer + nNotProcessed, BUFFER_LEN - nNotProcessed ); + if ( nRead < 0 ) + return sal_False; + + nRead += nNotProcessed; + pBuffer[nRead] = '\0'; + + /* skip old data */ + pBegin = pBuffer; + pNext = pBuffer; + for ( pIter = pBuffer; *pIter; ++pIter ) + if ( *pIter == '\n' ) + { + pBegin = pNext; + pNext = pIter + 1; + } + +#if OSL_DEBUG_LEVEL > 0 + fprintf( stderr, "Got status: %s\n", pBegin ); +#endif + if ( !strncasecmp( pBegin, "end", 3 ) ) + return ProgressExit; + else if ( !strncasecmp( pBegin, "restart", 7 ) ) + return ProgressRestart; + else if ( sscanf( pBegin, "%d%%", pPercent ) ) + return ProgressContinue; + + /* unexpected - let's exit the splash to be safe */ + return ProgressExit; +} + +/* Periodically update the splash & the percent acconding to what + status_fd says */ +static ProgressStatus +show_splash( int status_fd ) +{ + int nRetval; + struct pollfd aPfd; + + int nPercent = 0; + sal_Bool bFinish = sal_False; + ProgressStatus eResult; + + /* we want to watch status_fd */ + aPfd.fd = status_fd; + aPfd.events = POLLIN; + +#if OSL_DEBUG_LEVEL > 0 + fprintf( stderr, "Starting main loop, status fd: %d\n", status_fd ); +#endif + + /* main loop */ + do { + splash_draw_progress( nPercent ); + + /* read from pipe if data available */ + nRetval = poll( &aPfd, 1, 50 ); + if ( aPfd.revents & ( POLLERR | POLLHUP | POLLNVAL ) ) + bFinish = sal_True; + else if ( nRetval > 0 ) + { + eResult = read_percent( status_fd, &nPercent ); + bFinish = ( eResult != ProgressContinue ); + } + else if ( nRetval < 0 ) + bFinish = sal_True; + } while ( !bFinish ); + +#if OSL_DEBUG_LEVEL > 0 + fprintf( stderr, "Finishing, result is %s\n", + ( eResult == ProgressContinue )? "continue" : ( ( eResult == ProgressRestart )? "restart" : "exit" ) ); +#endif + return eResult; +} + +/* Simple system check. */ +static void +system_checks( void ) +{ +#ifdef LINUX + struct stat buf; + + /* check proc is mounted - lots of things fail otherwise */ + if ( stat( "/proc/version", &buf ) != 0 ) + { + fprintf( stderr, "ERROR: /proc not mounted - OO.o is unlikely to work well if at all" ); + exit( 1 ); + } +#endif +} + +/* Start the OOo application */ +static sal_Bool +fork_app( rtl_uString *pAppPath, int *status_fd ) +{ + rtl_uString *pApp = NULL, *pTmp = NULL, *pArg = NULL; + rtl_uString **ppArgs; + sal_uInt32 nArgs, i; + + oslProcess aProcess; + oslProcessError nError; + int status_pipe[2]; + + system_checks(); + + /* application name */ + rtl_uString_newFromAscii( &pApp, "file://" ); + rtl_uString_newConcat( &pApp, pApp, pAppPath ); + rtl_uString_newFromAscii( &pTmp, "/soffice.bin" ); + rtl_uString_newConcat( &pApp, pApp, pTmp ); + + rtl_uString_new( &pTmp ); + + /* copy args */ + nArgs = osl_getCommandArgCount(); + ppArgs = (rtl_uString **)calloc( nArgs + 1, sizeof( rtl_uString* ) ); + for ( i = 0; i < nArgs; ++i ) + { + ppArgs[i] = NULL; + osl_getCommandArg( i, &pTmp ); + rtl_uString_newFromString( &(ppArgs[i]), pTmp ); + } + + /* create pipe */ + if ( pipe( status_pipe ) < 0 ) + { + fprintf( stderr, "ERROR: no file handles\n"); + exit( 1 ); + } + + /* add the pipe arg */ + sal_Unicode pUnicode[RTL_USTR_MAX_VALUEOFINT32]; + rtl_ustr_valueOfInt32( pUnicode, status_pipe[1], 10 ); + + rtl_uString_newFromAscii( &pArg, "-splash-pipe=" ); + rtl_uString_newFromStr( &pTmp, pUnicode ); + rtl_uString_newConcat( &pArg, pArg, pTmp ); + + ppArgs[nArgs] = NULL; + rtl_uString_newFromString( &(ppArgs[nArgs]), pArg ); + ++nArgs; + + /* start the OOo process */ + nError = osl_executeProcess( pApp, ppArgs, nArgs, + osl_Process_DETACHED | osl_Process_NORMAL, + NULL, + NULL, + NULL, 0, + &aProcess ); + + *status_fd = status_pipe[0]; + close( status_pipe[1] ); + + if ( nError != osl_Process_E_None ) + { + fprintf( stderr, "ERROR %d forking process", nError ); + ustr_debug( "", pApp ); + return sal_False; + } + + return sal_True; +} + +/* Check if 'pArg' is -pCmpWith or --pCmpWith */ +static sal_Bool +arg_check( rtl_uString *pArg, const char *pCmpWith ) +{ + sal_Unicode *pUnicode = rtl_uString_getStr( pArg ); + + if ( pUnicode[0] == (sal_Unicode)'-' ) + pUnicode++; + else + return sal_False; + + /* tolerate -- prefixes etc. */ + if ( pUnicode[0] == (sal_Unicode)'-' ) + pUnicode++; + + return !rtl_ustr_ascii_compare( pUnicode, pCmpWith ); +} + +static const char *ppInhibit[] = { + "nologo", "headless", "invisible", "help", "h", "?", "minimized", + NULL }; +static const char *ppTwoArgs[] = { + "pt", "display", + NULL }; + +/* Read command line parameters and return whether we display the splash. */ +static sal_Bool +get_inhibit_splash() +{ + rtl_uString *pTmp = NULL; + sal_Bool bSkipNextArg = sal_False; + const char **ppIter; + + rtl_uString_new( &pTmp ); + + sal_uInt32 nArg; + sal_uInt32 nArgCount = osl_getCommandArgCount(); + for ( nArg = 0; nArg < nArgCount; ++nArg ) + { + if ( bSkipNextArg ) + { + bSkipNextArg = sal_False; + continue; + } + + osl_getCommandArg( nArg, &pTmp ); + + /* check for inhibit splash params */ + for ( ppIter = ppInhibit; *ppIter; ++ppIter ) + { + if ( arg_check( pTmp, *ppIter ) ) + { + rtl_uString_release( pTmp ); + return sal_True; + } + } + /* check for 2 arguments params */ + for ( ppIter = ppTwoArgs; *ppIter; ++ppIter ) + { + if ( arg_check( pTmp, *ppIter ) ) + { + bSkipNextArg = sal_True; + break; + } + } + } + + /* cleanup */ + rtl_uString_release( pTmp ); + + return sal_False; +} + +SAL_IMPLEMENT_MAIN_WITH_ARGS( argc, argv ) +{ + int fd = 0, status_fd = 0; + sal_Bool bInhibitSplash, bSendAndReport; + sal_Bool bSentArgs = sal_False; + rtl_uString *pAppPath = NULL; + rtl_uString *pPipePath = NULL; + ProgressStatus eResult = ProgressExit; + + /* turn SIGPIPE into an error */ + signal( SIGPIPE, SIG_IGN ); + + bInhibitSplash = get_inhibit_splash(); + + pAppPath = get_app_path( argv[0] ); + if ( !pAppPath ) + { + fprintf( stderr, "ERROR: Can't read app link\n" ); + exit( 1 ); + } + ustr_debug( "App path", pAppPath ); + + bSendAndReport = argc > 1 && !strcmp (argv[1], QSEND_AND_REPORT); + + pPipePath = get_pipe_path( pAppPath ); + + if ( ( fd = connect_pipe( pPipePath ) ) >= 0 ) + { + rtl_uString *pCwdPath = NULL; + osl_getProcessWorkingDir( &pCwdPath ); + + bSentArgs = send_args( fd, pCwdPath ); + } +#if OSL_DEBUG_LEVEL > 0 + else + ustr_debug( "Failed to connect to pipe", pPipePath ); +#endif + + if ( !bSendAndReport && !bSentArgs ) + { + /* we have to exec the binary */ + do { + if ( !fork_app( pAppPath, &status_fd ) ) + return 1; + + if ( !bInhibitSplash ) + { + load_splash_image( pAppPath ); + load_splash_defaults( pAppPath, &bInhibitSplash ); + } + + if ( !bInhibitSplash && splash_create_window( argc, argv ) ) + { + splash_draw_progress( 0 ); + eResult = show_splash( status_fd ); + splash_close_window(); + } + + close( status_fd ); + } while ( eResult == ProgressRestart ); + } + + /* cleanup */ + rtl_uString_release( pAppPath ); + rtl_uString_release( pPipePath ); + + close( fd ); + + return bSendAndReport? !bSentArgs : 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/unx/splash/exports.map b/desktop/unx/splash/exports.map new file mode 100644 index 000000000000..ba501f9ae076 --- /dev/null +++ b/desktop/unx/splash/exports.map @@ -0,0 +1,10 @@ +UDK_3_0_0 { + global: + GetVersionInfo; + component_getImplementationEnvironment; + component_getFactory; + component_writeInfo; + + local: + *; +}; diff --git a/desktop/unx/splash/makefile.mk b/desktop/unx/splash/makefile.mk new file mode 100644 index 000000000000..d182173de1ff --- /dev/null +++ b/desktop/unx/splash/makefile.mk @@ -0,0 +1,71 @@ +# +# Version: MPL 1.1 / GPLv3+ / LGPLv3+ +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Initial Developer of the Original Code is +# Novell, Inc. +# Portions created by the Initial Developer are Copyright (C) 2010 the +# Initial Developer. All Rights Reserved. +# +# Contributor(s): Jan Holesovsky <kendy@novell.com> +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 3 or later (the "GPLv3+"), or +# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), +# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable +# instead of those above. +# +PRJ=..$/.. + +PRJNAME=desktop +TARGET=spl_unx +LIBTARGET=NO + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +.IF "$(ENABLE_UNIX_QUICKSTARTER)"!="TRUE" + +dummy: + @echo "Unix quickstarter disabled" + +.ELSE + +# --- Files -------------------------------------------------------- + +SLOFILES = $(SLO)$/unxsplash.obj \ + $(SLO)$/services_unxsplash.obj + +SHL1DEPN= makefile.mk +SHL1OBJS= $(SLOFILES) + + +SHL1TARGET=$(TARGET)$(DLLPOSTFIX) +SHL1IMPLIB=i$(TARGET) + +SHL1VERSIONMAP=exports.map +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +DEF1NAME=$(SHL1TARGET) + +SHL1STDLIBS= \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) + +.ENDIF # ENABLE_UNIX_QUICKSTARTER + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/desktop/unx/splash/services_unxsplash.cxx b/desktop/unx/splash/services_unxsplash.cxx new file mode 100644 index 000000000000..6e8b63afa57c --- /dev/null +++ b/desktop/unx/splash/services_unxsplash.cxx @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright 2010, Novell Inc. + * 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. + * + * Contributor(s): Jan Holesovsky <kendy@novell.com> + * + ************************************************************************/ +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/util/Date.hpp> +#include <uno/environment.h> +#include <cppuhelper/factory.hxx> +#include <unotools/configmgr.hxx> + +#include <string.h> + +#include "unxsplash.hxx" + +using namespace rtl; +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 ::desktop; + +static const char* pServices[] = +{ + UnxSplashScreen::serviceName, + NULL +}; + +static const char* pImplementations[] = +{ + UnxSplashScreen::implementationName, + NULL +}; + +typedef Reference<XInterface>(* fProvider)( const Reference<XMultiServiceFactory>& ); + +static const fProvider pInstanceProviders[] = +{ + UnxSplashScreen::getInstance, + NULL +}; + + +static const char** pSupportedServices[] = +{ + UnxSplashScreen::interfaces, + NULL +}; + +static Sequence<OUString> +getSupportedServiceNames( int p ) { + const char **names = pSupportedServices[p]; + Sequence<OUString> aSeq; + for ( int i = 0; names[i] != NULL; i++ ) + { + aSeq.realloc( i+1 ); + aSeq[i] = OUString::createFromAscii( names[i] ); + } + return aSeq; +} + +extern "C" +{ +void SAL_CALL +component_getImplementationEnvironment( + const sal_Char** ppEnvironmentTypeName, + uno_Environment** ppEnvironment ) +{ + *ppEnvironmentTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ; +} + +sal_Bool SAL_CALL +component_writeInfo( + void* pServiceManager, + void* pRegistryKey ) +{ + Reference<XMultiServiceFactory> xMan( + reinterpret_cast< XMultiServiceFactory* >( pServiceManager ) ) ; + Reference<XRegistryKey> xKey( + reinterpret_cast< XRegistryKey* >( pRegistryKey ) ) ; + + // iterate over service names and register them... + OUString aImpl; + const char* pServiceName = NULL; + const char* pImplName = NULL; + for ( int i = 0; ( pServices[i] != NULL ) && ( pImplementations[i] != NULL ); i++ ) + { + pServiceName= pServices[i]; + pImplName = pImplementations[i]; + aImpl = OUString::createFromAscii( "/" ) + + OUString::createFromAscii( pImplName ) + + OUString::createFromAscii( "/UNO/SERVICES" ); + Reference<XRegistryKey> xNewKey = xKey->createKey( aImpl ); + xNewKey->createKey( OUString::createFromAscii( pServiceName ) ); + } + return sal_True; +} + +void* SAL_CALL +component_getFactory( + const sal_Char* pImplementationName, + void* pServiceManager, + void* pRegistryKey ) +{ + // Set default return value for this operation - if it failed. + if ( pImplementationName && pServiceManager ) + { + Reference< XSingleServiceFactory > xFactory; + Reference< XMultiServiceFactory > xServiceManager( + reinterpret_cast< XMultiServiceFactory* >( pServiceManager ) ) ; + + // search implementation + for ( int i = 0; ( pImplementations[i] != NULL ); i++ ) + { + if ( strcmp( pImplementations[i], pImplementationName ) == 0 ) + { + // found implementation + xFactory = Reference<XSingleServiceFactory>( cppu::createSingleFactory( + xServiceManager, OUString::createFromAscii( pImplementationName ), + pInstanceProviders[i], getSupportedServiceNames( i ) ) ); + if ( xFactory.is() ) + { + // Factory is valid - service was found. + xFactory->acquire(); + return xFactory.get(); + } + } + } + } + + return NULL; +} +} // extern "C" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/unx/splash/unxsplash.cxx b/desktop/unx/splash/unxsplash.cxx new file mode 100644 index 000000000000..6c1501416322 --- /dev/null +++ b/desktop/unx/splash/unxsplash.cxx @@ -0,0 +1,180 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * Copyright 2010, Novell Inc. + * 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. + * + * Contributor(s): Jan Holesovsky <kendy@novell.com> + * + ************************************************************************/ +#include "unxsplash.hxx" +#include <stdio.h> +#include <unotools/bootstrap.hxx> +#include <osl/process.h> +#include <tools/urlobj.hxx> +#include <tools/stream.hxx> +#include <sfx2/sfx.hrc> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <rtl/logfile.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/math.hxx> + +#define PIPE_ARG "-splash-pipe=" + +using namespace ::rtl; +using namespace ::com::sun::star::registry; + +namespace desktop +{ + +UnxSplashScreen::UnxSplashScreen( const Reference< XMultiServiceFactory >& rSMgr ) + : m_rFactory( rSMgr ), + m_pOutFd( NULL ) +{ +} + +UnxSplashScreen::~UnxSplashScreen() +{ +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "UnxSplashScreen::~UnxSplashScreen()\n" ); +#endif + + if ( m_pOutFd ) + { + fclose( m_pOutFd ); + m_pOutFd = NULL; + } +} + +void SAL_CALL UnxSplashScreen::start( const OUString& /*aText*/, sal_Int32 /*nRange*/ ) + throw ( RuntimeException ) +{ +} + +void SAL_CALL UnxSplashScreen::end() + throw ( RuntimeException ) +{ +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "UnxSplashScreen::end()\n" ); +#endif + + fprintf( m_pOutFd, "end\n" ); + fflush( m_pOutFd ); +} + +void SAL_CALL UnxSplashScreen::reset() + throw ( RuntimeException ) +{ +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "UnxSplashScreen::reset()\n" ); +#endif + + fprintf( m_pOutFd, "restart\n" ); + fflush( m_pOutFd ); +} + +void SAL_CALL UnxSplashScreen::setText( const OUString& /*aText*/ ) + throw ( RuntimeException ) +{ + // TODO? +} + +void SAL_CALL UnxSplashScreen::setValue( sal_Int32 nValue ) + throw ( RuntimeException ) +{ + if ( m_pOutFd ) + { + fprintf( m_pOutFd, "%d%%\n", nValue ); + fflush( m_pOutFd ); + } +} + +// XInitialize +void SAL_CALL +UnxSplashScreen::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments ) + throw ( RuntimeException ) +{ + for ( sal_uInt32 i = 0; i < osl_getCommandArgCount(); i++ ) + { + rtl::OUString aArg; + if ( osl_getCommandArg( i, &aArg.pData ) ) + break; + if ( aArg.matchIgnoreAsciiCaseAsciiL( PIPE_ARG, sizeof( PIPE_ARG ) - 1, 0 ) ) + { + OUString aNum = aArg.copy( sizeof( PIPE_ARG ) - 1 ); + int fd = aNum.toInt32(); + m_pOutFd = fdopen( fd, "w" ); +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "Got argument '-splash-pipe=%d ('%s') (%p)\n", + fd, (const sal_Char *)rtl::OUStringToOString( aNum, RTL_TEXTENCODING_UTF8 ), + m_pOutFd ); +#endif + } + } +} + +// get service instance... +UnxSplashScreen *UnxSplashScreen::m_pINSTANCE = NULL; +osl::Mutex UnxSplashScreen::m_aMutex; + +Reference< XInterface > UnxSplashScreen::getInstance( const Reference< XMultiServiceFactory >& rSMgr ) +{ + if ( m_pINSTANCE == NULL ) + { + osl::MutexGuard guard( m_aMutex ); + if ( m_pINSTANCE == NULL ) + return (XComponent*) new UnxSplashScreen( rSMgr ); + } + + return (XComponent*)NULL; +} + +// static service info... +const char* UnxSplashScreen::interfaces[] = +{ + "com.sun.star.task.XStartusIndicator", + "com.sun.star.lang.XInitialization", + NULL, +}; +const sal_Char *UnxSplashScreen::serviceName = "com.sun.star.office.PipeSplashScreen"; +const sal_Char *UnxSplashScreen::implementationName = "com.sun.star.office.comp.PipeSplashScreen"; +const sal_Char *UnxSplashScreen::supportedServiceNames[] = { "com.sun.star.office.PipeSplashScreen", NULL }; + +OUString UnxSplashScreen::impl_getImplementationName() +{ + return OUString::createFromAscii( implementationName ); +} + +Sequence<OUString> UnxSplashScreen::impl_getSupportedServiceNames() +{ + Sequence<OUString> aSequence; + for ( int i = 0; supportedServiceNames[i] != NULL; i++ ) + { + aSequence.realloc( i+1 ); + aSequence[i] = OUString::createFromAscii( supportedServiceNames[i] ); + } + return aSequence; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/unx/splash/unxsplash.hxx b/desktop/unx/splash/unxsplash.hxx new file mode 100644 index 000000000000..31f57efbecd9 --- /dev/null +++ b/desktop/unx/splash/unxsplash.hxx @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Initial Developer of the Original Code is + * Novell, Inc. + * Portions created by the Initial Developer are Copyright (C) 2010 the + * Initial Developer. All Rights Reserved. + * + * Contributor(s): Jan Holesovsky <kendy@novell.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ +#include <stdio.h> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/task/XStatusIndicator.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <cppuhelper/implbase2.hxx> +#include <cppuhelper/interfacecontainer.h> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <osl/mutex.hxx> +#include <rtl/bootstrap.hxx> + +using namespace ::rtl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::task; + +namespace desktop { + +class UnxSplashScreen : public ::cppu::WeakImplHelper2< XStatusIndicator, XInitialization > +{ +private: + // don't allow anybody but ourselves to create instances of this class + UnxSplashScreen( const UnxSplashScreen& ); + UnxSplashScreen( void ); + UnxSplashScreen operator =( const UnxSplashScreen& ); + + UnxSplashScreen( const Reference< XMultiServiceFactory >& xFactory ); + + virtual ~UnxSplashScreen(); + + static UnxSplashScreen *m_pINSTANCE; + + static osl::Mutex m_aMutex; + Reference< XMultiServiceFactory > m_rFactory; + + FILE *m_pOutFd; + +public: + static const char* interfaces[]; + static const sal_Char *serviceName; + static const sal_Char *implementationName; + static const sal_Char *supportedServiceNames[]; + + static Reference< XInterface > getInstance( const Reference < XMultiServiceFactory >& xFactory ); + + // static service info + static OUString impl_getImplementationName(); + static Sequence<OUString> impl_getSupportedServiceNames(); + + // XStatusIndicator + virtual void SAL_CALL start( const OUString& aText, sal_Int32 nRange ) throw ( RuntimeException ); + virtual void SAL_CALL end() throw ( RuntimeException ); + virtual void SAL_CALL reset() throw ( RuntimeException ); + virtual void SAL_CALL setText( const OUString& aText ) throw ( RuntimeException ); + virtual void SAL_CALL setValue( sal_Int32 nValue ) throw ( RuntimeException ); + + // XInitialize + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments ) throw ( RuntimeException ); +}; + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/util/hidother.src b/desktop/util/hidother.src new file mode 100644 index 000000000000..0ab7ca9f8d36 --- /dev/null +++ b/desktop/util/hidother.src @@ -0,0 +1,54 @@ +/************************************************************************* + * + * 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 "../source/inc/helpid.hrc" + +hidspecial HID_PACKAGE_MANAGER { HelpID = HID_PACKAGE_MANAGER; }; +hidspecial HID_PACKAGE_MANAGER_MENU_ITEM { HelpID = HID_PACKAGE_MANAGER_MENU_ITEM; }; +hidspecial HID_PACKAGE_MANAGER_TREELISTBOX { HelpID = HID_PACKAGE_MANAGER_TREELISTBOX; }; +hidspecial HID_PACKAGE_MANAGER_PROGRESS { HelpID = HID_PACKAGE_MANAGER_PROGRESS; }; +hidspecial HID_PACKAGE_MANAGER_PROGRESS_CANCEL { HelpID = HID_PACKAGE_MANAGER_PROGRESS_CANCEL; }; + +hidspecial HID_PACKAGE_MANAGER_UPD_REQ { HelpID = HID_PACKAGE_MANAGER_UPD_REQ; }; + +hidspecial HID_FIRSTSTART_PREV { HelpId = HID_FIRSTSTART_PREV;}; +hidspecial HID_FIRSTSTART_NEXT { HelpId = HID_FIRSTSTART_NEXT;}; +hidspecial HID_FIRSTSTART_CANCEL { HelpId = HID_FIRSTSTART_CANCEL;}; +hidspecial HID_FIRSTSTART_FINISH { HelpId = HID_FIRSTSTART_FINISH;}; +hidspecial UID_FIRSTSTART_HELP { HelpId = UID_FIRSTSTART_HELP;}; + +hidspecial UID_BTN_LICENSE_ACCEPT { HelpId = UID_BTN_LICENSE_ACCEPT;}; + +hidspecial HID_DEPLOYMENT_GUI_UPDATE { HelpId = HID_DEPLOYMENT_GUI_UPDATE;}; +hidspecial HID_DEPLOYMENT_GUI_UPDATEINSTALL { HelpId = HID_DEPLOYMENT_GUI_UPDATEINSTALL;}; + +hidspecial HID_EXTENSION_MANAGER_LISTBOX { HelpId = HID_EXTENSION_MANAGER_LISTBOX; }; +hidspecial HID_EXTENSION_MANAGER_LISTBOX_OPTIONS { HelpId = HID_EXTENSION_MANAGER_LISTBOX_OPTIONS; }; +hidspecial HID_EXTENSION_MANAGER_LISTBOX_ENABLE { HelpId = HID_EXTENSION_MANAGER_LISTBOX_ENABLE; }; +hidspecial HID_EXTENSION_MANAGER_LISTBOX_DISABLE { HelpId = HID_EXTENSION_MANAGER_LISTBOX_DISABLE; }; +hidspecial HID_EXTENSION_MANAGER_LISTBOX_REMOVE { HelpId = HID_EXTENSION_MANAGER_LISTBOX_REMOVE; }; + diff --git a/desktop/util/makefile.mk b/desktop/util/makefile.mk new file mode 100644 index 000000000000..3d4950cb40f0 --- /dev/null +++ b/desktop/util/makefile.mk @@ -0,0 +1,264 @@ +#************************************************************************* +# +# 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=soffice +TARGETTYPE=GUI +LIBTARGET=NO +GEN_HID=TRUE +GEN_HID_OTHER=TRUE + +# --- Settings ----------------------------------------------------------- + +.INCLUDE : settings.mk + +UWINAPILIB = + +VERINFONAME=verinfo + +# --- Resourcen ---------------------------------------------------- + +.IF "$(GUI)" == "WNT" +RCFILES=verinfo.rc +.ENDIF +.IF "$(GUI)" == "OS2" +RCFILES=ooverinfo2.rc +.ENDIF + +# --- Linken der Applikation --------------------------------------- + +.IF "$(OS)" == "MACOSX" +LINKFLAGSAPPGUI!:= $(LINKFLAGSAPPGUI:s/-bind_at_load//) +.ENDIF # MACOSX + +RESLIB1NAME= dkt +RESLIB1IMAGES= $(PRJ)$/res +RESLIB1SRSFILES= $(SRS)$/desktop.srs + +.IF "$(L10N_framework)"=="" +.IF "$(LINK_SO)"=="TRUE" +.IF "$(GUI)" != "OS2" +APP1TARGET=so$/$(TARGET) +APP1NOSAL=TRUE +APP1RPATH=BRAND +APP1OBJS=$(OBJ)$/copyright_ascii_sun.obj $(OBJ)$/main.obj +APP1STDLIBS = $(SALLIB) $(SOFFICELIB) +APP1DEPN= $(APP1RES) verinfo.rc + +.IF "$(GUI)" == "WNT" +APP1RES= $(RES)$/desktop.res +APP1ICON=$(SOLARRESDIR)$/icons/so9_main_app.ico +APP1VERINFO=verinfo.rc +APP1LINKRES=$(MISC)$/$(TARGET)1.res +APP1STACK=10000000 + +# create a manifest file with the same name as the +#office executable file soffice.exe.manifest +#$(BIN)$/$(TARGET).exe.manifest: template.manifest +#$(COPY) $< $@ + +.ENDIF # WNT + +.ENDIF # "$(GUI)" != "OS2" + +.ENDIF # "$(LINK_SO)"=="TRUE" + +APP5TARGET=soffice +APP5NOSAL=TRUE +APP5RPATH=BRAND +APP5OBJS=$(OBJ)$/copyright_ascii_ooo.obj $(OBJ)$/main.obj +APP5STDLIBS = $(SALLIB) $(SOFFICELIB) +.IF "$(OS)" == "LINUX" +APP5STDLIBS+= -lXext -lX11 +#APP5STDLIBS+= -lXext -lSM -lICE +.ENDIF # LINUX + +APP5DEPN= $(APP1TARGETN) $(APP5RES) ooverinfo.rc +APP5DEF= $(MISCX)$/$(TARGET).def + +.IF "$(GUI)" == "WNT" +APP5RES= $(RES)$/oodesktop.res +APP5ICON=$(SOLARRESDIR)$/icons/ooo3_main_app.ico +APP5VERINFO=ooverinfo.rc +APP5LINKRES=$(MISC)$/ooffice5.res +APP5STACK=10000000 +.ENDIF # WNT + +.IF "$(GUI)" == "OS2" +APP5DEF= # automatic +APP5RES= $(RES)$/oodesktop.res +APP5ICON=$(SOLARRESDIR)$/icons/ooo-main-app.ico +APP5VERINFO=ooverinfo2.rc +APP5LINKRES=$(MISC)$/ooffice.res +.ENDIF # OS2 + +.IF "$(GUI)" == "WNT" +.IF "$(LINK_SO)"=="TRUE" +APP6TARGET=so$/officeloader +APP6RES=$(RES)$/soloader.res +APP6NOSAL=TRUE +APP6DEPN= $(APP1TARGETN) $(APP6RES) verinfo.rc +APP6VERINFO=verinfo.rc +APP6LINKRES=$(MISC)$/soffice6.res +APP6ICON=$(SOLARRESDIR)$/icons/so9_main_app.ico +APP6OBJS = \ + $(OBJ)$/extendloaderenvironment.obj \ + $(OBJ)$/officeloader.obj \ + $(SOLARLIBDIR)$/pathutils-obj.obj +STDLIB6=$(ADVAPI32LIB) $(SHELL32LIB) $(SHLWAPILIB) +.ENDIF # "$(LINK_SO)"=="TRUE" + +APP7TARGET=officeloader +APP7RES=$(RES)$/ooloader.res +APP7NOSAL=TRUE +APP7DEPN= $(APP1TARGETN) $(APP7RES) ooverinfo.rc +APP7VERINFO=ooverinfo.rc +APP7LINKRES=$(MISC)$/ooffice7.res +APP7ICON=$(SOLARRESDIR)$/icons/ooo3_main_app.ico +APP7OBJS = \ + $(OBJ)$/extendloaderenvironment.obj \ + $(OBJ)$/officeloader.obj \ + $(SOLARLIBDIR)$/pathutils-obj.obj +STDLIB7=$(ADVAPI32LIB) $(SHELL32LIB) $(SHLWAPILIB) +.ELIF "$(OS)" == "MACOSX" +APP6TARGET=officeloader +APP6NOSAL=TRUE +APP6RPATH=BRAND +APP6OBJS=$(OBJ)$/copyright_ascii_ooo.obj $(OBJ)$/officeloader.obj +APP6STDLIBS = $(SALLIB) +APP5DEPN= $(APP1TARGETN) $(APP5RES) ooverinfo.rc +APP5DEF= $(MISCX)$/$(TARGET).def +.ENDIF # WNT + +.ENDIF + +# --- Targets ------------------------------------------------------------- + +.INCLUDE : target.mk + +.IF "$(L10N_framework)"=="" + +.IF "$(APP1TARGETN)"!="" +$(APP1TARGETN) : $(MISC)$/binso_created.flg +.ENDIF # "$(APP1TARGETN)"!="" + +.IF "$(APP5TARGETN)"!="" +$(APP5TARGETN) : $(MISC)$/binso_created.flg +.ENDIF # "$(APP6TARGETN)"!="" + +.IF "$(APP6TARGETN)"!="" +$(APP6TARGETN) : $(MISC)$/binso_created.flg +.ENDIF # "$(APP6TARGETN)"!="" + +.IF "$(GUI)" == "WNT" +ALLTAR: $(MISC)$/$(TARGET).exe.manifest +ALLTAR: $(MISC)$/$(TARGET).bin.manifest +ALLTAR: $(BIN)$/$(TARGET).bin +.IF "$(LINK_SO)"=="TRUE" +ALLTAR: $(BIN)$/so$/$(TARGET).bin +.ENDIF # "$(LINK_SO)"=="TRUE" +.ENDIF # WNT + +.IF "$(GUI)" == "OS2" +ALLTAR: $(BIN)$/$(TARGET).bin +.ENDIF # OS2 + +$(BIN)$/soffice_oo$(EXECPOST) : $(APP5TARGETN) + $(COPY) $< $@ + +.IF "$(GUI)" != "OS2" +.IF "$(LINK_SO)"=="TRUE" +$(BIN)$/so$/soffice_so$(EXECPOST) : $(APP1TARGETN) + $(COPY) $< $@ + +ALLTAR : $(BIN)$/so$/soffice_so$(EXECPOST) +.ENDIF # "$(LINK_SO)"=="TRUE" +ALLTAR : $(BIN)$/soffice_oo$(EXECPOST) +.ENDIF + +.IF "$(OS)" == "MACOSX" +.IF "$(LINK_SO)"=="TRUE" +$(BIN)$/so$/soffice_mac$(EXECPOST) : $(APP1TARGETN) + $(COPY) $< $@ + +ALLTAR : $(BIN)$/so$/soffice_mac$(EXECPOST) +.ENDIF # "$(LINK_SO)"=="TRUE" + +$(BIN)$/soffice_mac$(EXECPOST) : $(APP5TARGETN) + $(COPY) $< $@ + +ALLTAR : $(BIN)$/soffice_mac$(EXECPOST) + +.ENDIF # "$(OS)" == "MACOSX" + +.IF "$(GUI)" == "WNT" + +# create a manifest file with the same name as the +# office executable file soffice.exe.manifest +.IF "$(CCNUMVER)" <= "001399999999" +$(MISC)$/$(TARGET).exe.manifest: template.manifest + $(COPY) $< $@ +.ELSE +$(MISC)$/$(TARGET).exe.template.manifest: template.manifest + $(COPY) $< $@ + +$(MISC)$/$(TARGET).exe.linker.manifest: $(BIN)$/$(TARGET)$(EXECPOST) + mt.exe -inputresource:$(BIN)$/$(TARGET)$(EXECPOST) -out:$@ + +$(MISC)$/$(TARGET).exe.manifest: $(MISC)$/$(TARGET).exe.template.manifest $(MISC)$/$(TARGET).exe.linker.manifest + mt.exe -manifest $(MISC)$/$(TARGET).exe.linker.manifest $(MISC)$/$(TARGET).exe.template.manifest -out:$@ +.ENDIF + +# create a manifest file with the same name as the +# office executable file soffice.bin.manifest +.IF "$(CCNUMVER)" <= "001399999999" +$(MISC)$/$(TARGET).bin.manifest: template.manifest + $(COPY) $< $@ +.ELSE +$(MISC)$/$(TARGET).bin.manifest: $(MISC)$/$(TARGET).exe.manifest + $(COPY) $(MISC)$/$(TARGET).exe.manifest $@ +.ENDIF + +$(BIN)$/$(TARGET).bin: $(BIN)$/$(TARGET)$(EXECPOST) + $(COPY) $< $@ + +$(BIN)$/so$/$(TARGET).bin: $(BIN)$/so$/$(TARGET)$(EXECPOST) + $(COPY) $< $@ + +.ENDIF # WNT + +.IF "$(GUI)" == "OS2" +$(BIN)$/$(TARGET).bin: $(BIN)$/$(TARGET)$(EXECPOST) + $(COPY) $< $@ +.ENDIF # OS2 + +$(MISC)$/binso_created.flg : + @@-$(MKDIRHIER) $(BIN)$/so && $(TOUCH) $@ + +.ENDIF diff --git a/desktop/util/ooverinfo.rc b/desktop/util/ooverinfo.rc new file mode 100644 index 000000000000..5412f5fb2f6d --- /dev/null +++ b/desktop/util/ooverinfo.rc @@ -0,0 +1,112 @@ +/************************************************************************* + * + * 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. + * + *************************************************************************/ + +#define VER_FIRSTYEAR 2000 + +#include <windows.h> +#include "version.hrc" + +// ----------------------------------------------------------------------- +// version information +// ----------------------------------------------------------------------- + +VS_VERSION_INFO versioninfo + fileversion VERSION, SUBVERSION, VERVARIANT, VER_COUNT + productversion VERSION, SUBVERSION, VERVARIANT, VER_COUNT + fileflagsmask 0x3F + fileflags +#if defined(DEBUG) + VS_FF_DEBUG | +#endif +#ifdef VER_PREL + VS_FF_PRERELEASE | +#endif + 0 + fileos VOS_NT_WINDOWS32 + filetype VFT_APP + { + block "StringFileInfo" + { + block "040904E4" + { + // International StringTable + value "CompanyName", "The Document Foundation\0" + value "FileDescription", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\0" + value "FileVersion", PPS(VER_LEVEL) "\0" + value "ProductVersion", PPS(VER_LEVEL) "\0" + value "OriginalFilename", "SOFFICE.EXE\0" + value "InternalName", "SOFFICE\0" + value "LegalCopyright", S_CRIGHT " Oracle, Inc.\0" + } + } + + block "VarFileInfo" + { + value "Translation", 0x0409, 1252 + } + } + +2 ICON "icons\\oasis-text.ico" +3 ICON "icons\\oasis-text-template.ico" +4 ICON "icons\\oasis-spreadsheet.ico" +5 ICON "icons\\oasis-spreadsheet-template.ico" +6 ICON "icons\\oasis-drawing.ico" +7 ICON "icons\\oasis-drawing-template.ico" +8 ICON "icons\\oasis-presentation.ico" +9 ICON "icons\\oasis-presentation-template.ico" +10 ICON "icons\\oasis-presentation-template.ico" +11 ICON "icons\\oasis-master-document.ico" +12 ICON "icons\\oasis-web-template.ico" +13 ICON "icons\\oasis-empty-document.ico" +14 ICON "icons\\oasis-database.ico" +15 ICON "icons\\oasis-formula.ico" +16 ICON "icons\\oasis-web-template.ico" +17 ICON "icons\\empty-document.ico" +18 ICON "icons\\ooo-configuration.ico" +19 ICON "icons\\ooo3_open.ico" +20 ICON "icons\\empty-document.ico" +21 ICON "icons\\ooo3_writer_app.ico" +22 ICON "icons\\ooo3_calc_app.ico" +23 ICON "icons\\ooo3_draw_app.ico" +24 ICON "icons\\ooo3_impress_app.ico" +25 ICON "icons\\ooo3_math_app.ico" +26 ICON "icons\\ooo3_base_app.ico" +27 ICON "icons\\oasis-empty-document.ico" +28 ICON "icons\\text.ico" +29 ICON "icons\\text-template.ico" +30 ICON "icons\\spreadsheet.ico" +31 ICON "icons\\spreadsheet-template.ico" +32 ICON "icons\\drawing.ico" +33 ICON "icons\\drawing-template.ico" +34 ICON "icons\\presentation.ico" +35 ICON "icons\\presentation-template.ico" +36 ICON "icons\\master-document.ico" +37 ICON "icons\\empty-document.ico" +38 ICON "icons\\database.ico" +39 ICON "icons\\formula.ico" +40 ICON "icons\\oxt-extension.ico" + diff --git a/desktop/util/ooverinfo2.rc b/desktop/util/ooverinfo2.rc new file mode 100644 index 000000000000..8bc39767f04a --- /dev/null +++ b/desktop/util/ooverinfo2.rc @@ -0,0 +1,90 @@ +/************************************************************************* + * + * 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. + * + *************************************************************************/ + +#define VERSION 3 +#define SUBVERSION 3 +//#define VERVARIANT 0 +// .0 + VER_CONCEPT +// .100 + VER_ALPHA +// .200 + VER_BETA +// .300 + VER_GAMMA +// .500 + VER_FINAL +//#define VER_CONCEPT 0 +//#define VER_BETA 6 +#define VER_FINAL 0 + +#define VER_DAY 1 +#define VER_MONTH 1 +#define VER_YEAR 2010 + +// ----------------------------------------------------------------------- + +// ----------------------------------------------------------------------- +// language/character set specification table +// ----------------------------------------------------------------------- + + +ICON 2 "icons/oasis-text.ico" +ICON 3 "icons/oasis-text-template.ico" +ICON 4 "icons/oasis-spreadsheet.ico" +ICON 5 "icons/oasis-spreadsheet-template.ico" +ICON 6 "icons/oasis-drawing.ico" +ICON 7 "icons/oasis-drawing-template.ico" +ICON 8 "icons/oasis-presentation.ico" +ICON 9 "icons/oasis-presentation-template.ico" +ICON 10 "icons/oasis-presentation-template.ico" +// ICON 11 "icons/oasis-master-document.ico" +// ICON 12 "icons/oasis-web-template.ico" +ICON 13 "icons/oasis-empty-document.ico" +ICON 14 "icons/oasis-database.ico" +ICON 15 "icons/oasis-formula.ico" +ICON 16 "icons/oasis-web-template.ico" +ICON 17 "icons/empty-document.ico" +ICON 18 "icons/ooo-configuration.ico" +ICON 19 "icons/ooo-open.ico" +ICON 20 "icons/empty-document.ico" +ICON 21 "icons/ooo-writer-app.ico" +ICON 22 "icons/ooo-calc-app.ico" +ICON 23 "icons/ooo-draw-app.ico" +ICON 24 "icons/ooo-impress-app.ico" +ICON 25 "icons/ooo-math-app.ico" +ICON 26 "icons/ooo-base-app.ico" +ICON 27 "icons/oasis-empty-document.ico" +ICON 28 "icons/text.ico" +ICON 29 "icons/text-template.ico" +ICON 30 "icons/spreadsheet.ico" +ICON 31 "icons/spreadsheet-template.ico" +ICON 32 "icons/drawing.ico" +ICON 33 "icons/drawing-template.ico" +ICON 34 "icons/presentation.ico" +ICON 35 "icons/presentation-template.ico" +ICON 36 "icons/master-document.ico" +ICON 37 "icons/empty-document.ico" +ICON 38 "icons/database.ico" +ICON 39 "icons/formula.ico" +ICON 40 "icons/oxt-extension.ico" + diff --git a/desktop/util/soffice.ico b/desktop/util/soffice.ico Binary files differnew file mode 100644 index 000000000000..88ccf5e5a6a0 --- /dev/null +++ b/desktop/util/soffice.ico diff --git a/desktop/util/template.manifest b/desktop/util/template.manifest new file mode 100644 index 000000000000..d3bd0c101f2f --- /dev/null +++ b/desktop/util/template.manifest @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> +<assemblyIdentity version="1.0.0.0" processorArchitecture="x86" name="LibreOffice" type="win32" /> +<description>http://www.documentfoundation.org</description> +<dependency> +<dependentAssembly> +<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="x86"/> +</dependentAssembly> +</dependency> +</assembly> diff --git a/desktop/util/verinfo.rc b/desktop/util/verinfo.rc new file mode 100755 index 000000000000..7fce1e773a14 --- /dev/null +++ b/desktop/util/verinfo.rc @@ -0,0 +1,116 @@ +/************************************************************************* + * + * 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. + * + *************************************************************************/ + +#define VER_FIRSTYEAR 2007 + +#include <windows.h> +#include "version_so.hrc" + +// ----------------------------------------------------------------------- +// version information +// ----------------------------------------------------------------------- + +VS_VERSION_INFO versioninfo +#ifndef SUBVERSION + fileversion VERSION, 0, VERVARIANT, VER_COUNT + productversion VERSION, 0, VERVARIANT, VER_COUNT +#else + fileversion VERSION, SUBVERSION, VERVARIANT, VER_COUNT + productversion VERSION, SUBVERSION, VERVARIANT, VER_COUNT +#endif + fileflagsmask 0x3F + fileflags +#if defined(DEBUG) + VS_FF_DEBUG | +#endif +#ifdef VER_PREL + VS_FF_PRERELEASE | +#endif + 0 + fileos VOS_NT_WINDOWS32 + filetype VFT_APP + { + block "StringFileInfo" + { + block "040904E4" + { + // International StringTable + value "CompanyName", "The Document Foundation\0" + value "FileDescription", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\0" + value "FileVersion", PPS(VER_LEVEL) "\0" + value "ProductVersion", PPS(VER_LEVEL) "\0" + value "OriginalFilename", "SOFFICE.EXE\0" + value "InternalName", "SOFFICE\0" + value "LegalCopyright", S_CRIGHT " Oracle and/or its affiliates. All rights reserved.\0" + } + } + + block "VarFileInfo" + { + value "Translation", 0x0409, 1252 + } + } + +2 ICON "icons\\oasis-text.ico" +3 ICON "icons\\oasis-text-template.ico" +4 ICON "icons\\oasis-spreadsheet.ico" +5 ICON "icons\\oasis-spreadsheet-template.ico" +6 ICON "icons\\oasis-drawing.ico" +7 ICON "icons\\oasis-drawing-template.ico" +8 ICON "icons\\oasis-presentation.ico" +9 ICON "icons\\oasis-presentation-template.ico" +10 ICON "icons\\oasis-presentation-template.ico" +11 ICON "icons\\oasis-master-document.ico" +12 ICON "icons\\oasis-web-template.ico" +13 ICON "icons\\oasis-empty-document.ico" +14 ICON "icons\\oasis-database.ico" +15 ICON "icons\\oasis-formula.ico" +16 ICON "icons\\oasis-web-template.ico" +17 ICON "icons\\empty-document.ico" +18 ICON "icons\\so8-configuration.ico" +19 ICON "icons\\so9_open.ico" +20 ICON "icons\\empty-document.ico" +21 ICON "icons\\so9_writer_app.ico" +22 ICON "icons\\so9_calc_app.ico" +23 ICON "icons\\so9_draw_app.ico" +24 ICON "icons\\so9_impress_app.ico" +25 ICON "icons\\so9_math_app.ico" +26 ICON "icons\\so9_base_app.ico" +27 ICON "icons\\oasis-empty-document.ico" +28 ICON "icons\\text.ico" +29 ICON "icons\\text-template.ico" +30 ICON "icons\\spreadsheet.ico" +31 ICON "icons\\spreadsheet-template.ico" +32 ICON "icons\\drawing.ico" +33 ICON "icons\\drawing-template.ico" +34 ICON "icons\\presentation.ico" +35 ICON "icons\\presentation-template.ico" +36 ICON "icons\\master-document.ico" +37 ICON "icons\\empty-document.ico" +38 ICON "icons\\database.ico" +39 ICON "icons\\formula.ico" +40 ICON "icons\\oxt-extension.ico" diff --git a/desktop/util/writer.r b/desktop/util/writer.r new file mode 100644 index 000000000000..2a0ec2722900 --- /dev/null +++ b/desktop/util/writer.r @@ -0,0 +1 @@ +//*************************************************************************
//*
//* $Workfile: writer.r $
//*
//* Ersterstellung KH
//*
//* Letzte Aenderung $Author: hr $ $Date: 2000-09-18 16:15:12 $
//* $Revision: 1.1.1.1 $
//*
//* $Logfile: T:/desktop/util/writer.r_v $
//*
//* Copyright (c) 1990 - 1995, STAR DIVISION
//*
//*************************************************************************
#include "Types.r"
//#ifndef MAINSHLBNAME
// #define MAINSHLBNAME "Sw356MP Library"
//#endif
//
//resource 'STR#' (2001, "MainShlbName", purgeable) {
// { /* array StringArray: 2 elements */
// /* [1] */
// MAINSHLBNAME,
// /* [2] */
// "Test"
// }
//};
resource 'SIZE' (-1) {
reserved,
acceptSuspendResumeEvents,
reserved,
canBackground,
multiFinderAware,
backgroundAndForeground,
dontGetFrontClicks,
ignoreChildDiedEvents,
is32BitCompatible,
isHighLevelEventAware,
onlyLocalHLEvents,
isStationeryAware,
dontUseTextEditServices,
true,
reserved,
reserved,
7096000,
3584000
};
resource 'SIZE' (0) {
reserved,
acceptSuspendResumeEvents,
reserved,
canBackground,
multiFinderAware,
backgroundAndForeground,
dontGetFrontClicks,
ignoreChildDiedEvents,
is32BitCompatible,
isHighLevelEventAware,
onlyLocalHLEvents,
isStationeryAware,
dontUseTextEditServices,
true,
reserved,
reserved,
7096000,
3584000
};
resource 'ics8' (128) {
$"EFF0 EF00 0000 0000 F900 0000 0000 0000"
$"F0EF F000 0000 00F9 D257 0000 0000 0000"
$"EFF0 EF00 0000 7A00 00D2 F900 0000 0000"
$"EFF0 F000 00FA 00F9 FA00 D256 0000 0000"
$"F0EF F000 7B00 FA00 F9FF 00D2 F900 0000"
$"EFEF EFFA 00F9 0000 00F9 FF00 D2F9 0000"
$"F0F0 F900 FA00 0000 0000 FAF9 00D2 F900"
$"EFF9 00FA 00FA F9FA F9FA F9FA FF00 D2F9"
$"F0EF FAF9 FAE5 E6E6 05E5 D2D2 F9FA F900"
$"EFF0 F900 00E6 E505 0505 E6E5 D2F9 0000"
$"F0F9 0000 F7E5 E6E5 05E6 E5E6 E5D2 FF00"
$"EF00 0000 E5E6 E5D2 D2E5 E6E5 E6D2 FF00"
$"F900 FAE6 E5E6 D2E5 D2E5 E5E6 D2D2 F9FA"
$"00FA 00E6 2BD2 E5E6 E5D2 E6E5 D2D2 C9F9"
$"F9C9 2B2B F7D2 E6E5 E6D2 E5E6 F9D2 C2FA"
$"FA00 C3D2 D2D2 E5E6 C2E5 C9F9 D2C3 FAF9"
};
resource 'ics8' (129) {
$"00FF FFFF FFFF FFFF FFFF FF00 0000 0000"
$"00FF F5F5 F5F5 F5F5 F5F5 FFFF 0000 0000"
$"00FF F5EC ECEC F5F5 F5F5 FFF8 FF00 0000"
$"00FF F5EC ECEC FFFF 00FF FFFF FFFF 0000"
$"00FF F5EC ECEC 0000 0000 00F5 F5FF 0000"
$"00FF F5EC ECF5 FFFF FF00 FFF5 F5FF 0000"
$"00FF F5EC F5F5 0000 0000 00F5 F5FF 0000"
$"00FF F5EC F5F5 FF00 FFFF FFF5 F5FF 0000"
$"00FF F5EC F5F5 0000 0000 00F5 F5FF 0000"
$"00FF F5EC ECF5 FFFF FF00 FFF5 F5FF 0000"
$"00FF F5EC ECEC 0000 0000 00F5 F5FF 0000"
$"00FF F5EC ECEC FF00 FFFF FFF5 F5FF 0000"
$"00FF F5EC ECEC 0000 0000 00F5 F5FF 0000"
$"00FF F5EC ECEC FFFF FF00 FFF5 F5FF 0000"
$"00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000"
$"00FF FFFF FFFF FFFF FFFF FFFF FFFF"
};
resource 'ics8' (130) {
$"00FF FFFF FFFF FFFF FFFF FFFF 0000 0000"
$"00FF F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"00FF F5EC ECEC FFF5 FFFF F5FF FFFF 0000"
$"00FF F5EC ECEC F5F5 F5F5 F5FF F5FF 0000"
$"00FF F5EC ECEC FFFF F5FF F5FF F5FF 0000"
$"00FF F5EC ECF5 F5F5 F5F5 F5FF F5FF 0000"
$"00FF F5EC F5F5 FFF5 FFFF F5FF F5FF 0000"
$"00FF F5EC F5F5 F5F5 F5F5 F5FF F5FF 0000"
$"00FF F5EC ECF5 FFFF F5FF F5FF F5FF 0000"
$"00FF F5EC ECEC F5F5 F5F5 F5FF F5FF 0000"
$"00FF F5EC ECEC FFF5 FFFF FFFF F5FF 0000"
$"00FF F5EC ECEC F5F5 FF2B FFF5 F5FF 0000"
$"00FF F5F5 F5F5 F5F5 FFFF F5F5 F5FF 0000"
$"00FF FFFF FFFF FFFF FFF5 F5FF F5FF 0000"
$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5FF 0000"
$"0000 00FF FFFF FFFF FFFF FFFF FFFF"
};
resource 'ics8' (131) {
$"00FF FFFF FFFF FFFF FFFF FF00 0000 0000"
$"00FF F5F5 F5F5 F5F5 F5F5 FFFF 0000 0000"
$"00FF F5EC ECEC F5F5 F5F5 FF2B FF00 0000"
$"00FF F5EC ECEC F5F5 F5F5 FFFF FFFF 0000"
$"00FF F5EC ECEC F5F5 F5F5 F5F5 F5FF 0000"
$"00FF F5EC ECF5 F5F5 F5F5 F5F5 F5FF 0000"
$"00FF F5EC FFF5 FFFF F5FF FFF5 F5FF 0000"
$"00FF F5EC F5F5 F5F5 F5F5 F5F5 F5FF 0000"
$"00FF F5EC FFFF FFFF F5FF FFF5 F5FF 0000"
$"00FF F5EC ECF5 F5F5 F5F5 F5F5 F5FF 0000"
$"00FF F5EC FFFF F5FF FFF5 FFF5 F5FF 0000"
$"00FF F5EC ECEC F5F5 F5F5 F5F5 F5FF 0000"
$"00FF F5EC ECEC F5F5 F5F5 F5F5 F5FF 0000"
$"00FF F5EC ECEC F5F5 F5F5 F5F5 F5FF 0000"
$"00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000"
$"00FF FFFF FFFF FFFF FFFF FFFF FFFF"
};
resource 'ics8' (132) {
$"0000 FFFF FFFF FFFF FFFF FFFF 0000 0000"
$"0000 FF00 0000 0000 0000 FF00 FF00 0000"
$"0000 FF00 ECEC ECC0 4848 FF00 00FF 0000"
$"0000 FF00 ECEC ECC0 0000 FFFF FFFF 0000"
$"0000 FF00 ECEC ECFF 0000 0000 00FF 0000"
$"0000 FF00 ECEC C000 FFFF 00FF FFFF 0000"
$"0000 FF00 EC00 48FF 0000 FF00 00FF 0000"
$"0000 FF00 EC00 C000 FFFF 00FF FFFF 0000"
$"0000 FF00 EC00 48FF 0000 FF00 00FF 0000"
$"0000 FF00 ECEC 48FF 0000 FF00 00FF 0000"
$"0000 FF00 ECEC B000 FFFF 00FF FFFF 0000"
$"0000 FF00 ECEC ECFF 0000 FF00 00FF 0000"
$"0000 FF00 ECEC ECFF 0000 FF00 00FF 0000"
$"0000 FF00 ECEC EC00 FFFF 00FF FFFF 0000"
$"0000 FF00 0000 0000 0000 0000 00FF 0000"
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF"
};
resource 'ics8' (133) {
$"00FF FFFF FFFF FFFF FFFF FFFF 0000 0000"
$"00FF F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"00FF F5EC ECEC C048 48C0 48FF FFFF 0000"
$"00FF F5EC ECEC 00FF FF00 FFFF 00FF 0000"
$"00FF F5EC ECEC FFF5 F5FF 00FF 00FF 0000"
$"00FF F5EC EC48 FFF5 F5FF 00FF FFFF 0000"
$"00FF F5EC F5C0 00FF FF00 FFFF 00FF 0000"
$"00FF F5EC F548 FFF5 F5FF F5FF 00FF 0000"
$"00FF F5EC EC48 FFF5 F5FF F5FF FFFF 0000"
$"00FF F5EC ECEC 00FF FF00 FFFF 00FF 0000"
$"00FF F5EC ECEC FFF5 FFFF FFFF 00FF 0000"
$"00FF F5EC ECEC FFF5 FF2B FF00 FFFF 0000"
$"00FF F5F5 F5F5 F5F5 FFFF 0000 00FF 0000"
$"00FF FFFF FFFF FFFF FF00 FF00 00FF 0000"
$"0000 00FF 0000 0000 0000 0000 00FF 0000"
$"0000 00FF FFFF FFFF FFFF FFFF FFFF"
};
resource 'ics8' (134) {
$"00FF FFFF FFFF FFFF FFFF FF00 0000 0000"
$"00FF F5F5 F5F5 F5F5 F5F5 FFFF 0000 0000"
$"00FF F5EC ECEC FAFA FAFA FF00 FF00 0000"
$"00FF F5EC ECEC FAFC FCFC FFFF FFFF 0000"
$"00FF F5EC ECEC FAFC 05EC F5F5 F5FF 0000"
$"00FF F5EC ECF5 FAFC D8E3 F5F5 FFFF 0000"
$"00FF F5EC F5F5 FAFC F5F5 F5FF F5FF 0000"
$"00FF F5EC F5F5 FAFC F5FF FFF5 F5FF 0000"
$"00FF F5EC F5F5 FAFF FFF5 F5F5 F5FF 0000"
$"00FF F5EC ECF5 FFF5 F5F5 2BF5 F5FF 0000"
$"00FF F5EC ECEC F5FA FA2B 2B2B F5FF 0000"
$"00FF F5EC ECEC F5FA FAF5 2BF5 F5FF 0000"
$"00FF F5EC ECEC F5F5 F5F8 F5F5 F5FF 0000"
$"00FF F5EC ECEC F5F5 F8F8 F8F5 F5FF 0000"
$"00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000"
$"00FF FFFF FFFF FFFF FFFF FFFF FFFF"
};
resource 'ics8' (135) {
$"00FF FFFF FFFF FFFF FFFF FFFF FF00 0000"
$"00FF F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"00FF F5EC ECEC FAFA FAFA FAFA FFFF FF00"
$"00FF F5EC ECEC FAFC FCFC FCFC FFF5 FF00"
$"00FF F5EC ECF5 FAFC 05EC F5F5 FFF5 FF00"
$"00FF F5EC F5F5 FAFC D8E3 F5F5 FFF5 FF00"
$"00FF F5EC F5F5 FAFC 0000 FFFF FFF5 FF00"
$"00FF F5EC F5F5 FAFC FFFF F5F5 FFF5 FF00"
$"00FF F5EC ECF5 FFFF F5F5 F5F5 FFF5 FF00"
$"00FF F5EC ECEC F5F5 F5F5 F5F5 FFF5 FF00"
$"00FF F5EC ECEC FAFA F5FF FFFF FFF5 FF00"
$"00FF F5EC ECEC FAFA F5FF 2BFF F5F5 FF00"
$"00FF F5F5 F5F5 F5F5 F5FF FFF5 F5F5 FF00"
$"00FF FFFF FFFF FFFF FFFF F5F5 F5F5 FF00"
$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 FF00"
$"0000 00FF FFFF FFFF FFFF FFFF FFFF FF"
};
resource 'ics8' (136) {
$"00FF FFFF FFFF FFFF FFFF FF00 0000 0000"
$"00FF F5F5 F5F5 F5F5 F5F5 FFFF 0000 0000"
$"00FF F5EC ECEC FCF5 F5F5 FFF5 FF00 0000"
$"00FF F5EC ECEC FAF5 F5F5 FFFF FFFF 0000"
$"00FF F5EC ECEC FCF5 05EC ECF5 F5FF 0000"
$"00FF F5EC ECF5 FA05 05EC ECEC F5FF 0000"
$"00FF F5EC F5F5 FC05 0505 ECEC F5FF 0000"
$"00FF F5EC F5F5 FA05 05D8 13D8 F5FF 0000"
$"00FF F5EC F5F5 FCF5 D813 D8F5 F5FF 0000"
$"00FF F5EC ECF5 FAF5 F5F5 F5F5 C0FF 0000"
$"00FF F5EC ECEC FCF5 F5C0 F5C0 F5FF 0000"
$"00FF F5EC ECEC FAF5 C0F5 C0F5 F5FF 0000"
$"00FF F5EC ECEC FCF5 F5F5 F5F5 F5FF 0000"
$"00FF F5EC ECEC FAFC FAFC FAFC F5FF 0000"
$"00FF F5F5 F5F5 0000 0000 00F5 F5FF 0000"
$"00FF FFFF FFFF FFFF FFFF FFFF FFFF"
};
resource 'ics8' (137) {
$"00FF FFFF FFFF FFFF FFFF FFFF FF00 0000"
$"00FF F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"00FF F5EC ECEC F505 ECEC F5F5 FFFF FF00"
$"00FF F5EC ECC0 0505 ECEC ECF5 FFF5 FF00"
$"00FF F5EC ECFB 0505 05EC ECF5 FFF5 FF00"
$"00FF F5EC F5F9 0505 D813 D8F5 FFF5 FF00"
$"00FF F5EC F5FB F5D8 13D8 F5F5 FFF5 FF00"
$"00FF F5EC F5F9 F5F5 F5F5 F5C0 FFF5 FF00"
$"00FF F5EC ECFB F5F5 C0F5 C000 FFF5 FF00"
$"00FF F5EC ECC0 F5C0 F5C0 0000 FFF5 FF00"
$"00FF F5EC ECEC F5F5 F5FF FFFF FFF5 FF00"
$"00FF F5EC ECC0 FBF9 FBFF 2BFF F5F5 FF00"
$"00FF F5F5 F5F5 F5F5 F5FF FFF5 F5F5 FF00"
$"00FF FFFF FFFF FFFF FFFF F5F5 F5F5 FF00"
$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 FF00"
$"0000 00FF FFFF FFFF FFFF FFFF FFFF FF"
};
resource 'ics8' (138) {
$"0000 FFFF FFFF FFFF FFFF FF00 0000 0000"
$"0000 FFF5 F5F5 F5F5 F5F5 FFFF 0000 0000"
$"0000 FFF5 ECEC ECFD D8F5 FF2B FF00 0000"
$"0000 FFF5 ECEC ECFD D8D8 FFFF FFFF 0000"
$"0000 FFF5 ECEC ECFD 0505 05FD F5FF 0000"
$"0000 FFF5 ECEC F5FD 05E3 00FD F5FF 0000"
$"0000 FFF5 ECF5 F5FD FDFD FDFD F5FF 0000"
$"0000 FFF5 ECF5 F5FD E3E3 E3FD F5FF 0000"
$"0000 FFF5 ECF5 F5FD E3E3 E3FD F5FF 0000"
$"0000 FFF5 ECEC F5FD FDFD FDFD F5FF 0000"
$"0000 FFF5 ECEC ECFD 2B2B 2BFD F5FF 0000"
$"0000 FFF5 ECEC ECFD 2B00 00FD F5FF 0000"
$"0000 FFF5 ECEC ECFD FDFD FDFD F5FF 0000"
$"0000 FFF5 ECEC ECFD 05E3 E3FD F5FF 0000"
$"0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5FF 0000"
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF"
};
resource 'ics8' (139) {
$"00FF FFFF FFFF FFFF FFFF FFFF FF00 0000"
$"00FF F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"00FF F5EC ECEC F5FD ECEC FDF5 FFFF FF00"
$"00FF F5EC ECEC F5FD FDFD FDF5 FFF5 FF00"
$"00FF F5EC ECEC F5FD E3D8 FDF5 FFF5 FF00"
$"00FF F5EC EC00 F5FD D8E3 FDF5 FFF5 FF00"
$"00FF F5EC 0000 F5FD FDFD FDF5 FFF5 FF00"
$"00FF F5EC 0000 F5FD E3E3 FDF5 FFF5 FF00"
$"00FF F5EC EC00 F5FD E3E3 FDF5 FFF5 FF00"
$"00FF F5EC ECEC F5FD FDFD FDF5 FFF5 FF00"
$"00FF F5EC ECEC F5FD 05FF FFFF FFF5 FF00"
$"00FF F5EC ECEC F5FD 05FF 2BFF F5F5 FF00"
$"00FF F5F5 F5F5 F5F5 F5FF FFF5 FDF5 FF00"
$"00FF FFFF FFFF FFFF FFFF F505 FDF5 FF00"
$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 FF00"
$"0000 00FF FFFF FFFF FFFF FFFF FFFF FF"
};
resource 'ics8' (140) {
$"00FF FFFF FFFF FFFF FFFF FF00 0000 0000"
$"00FF F5F5 F5F5 F5F5 F5F5 FFFF 0000 0000"
$"00FF F5EC ECEC F5F5 F5F5 FF2B FF00 0000"
$"00FF F5EC ECEC F5F5 F5F5 FFFF FFFF 0000"
$"00FF F5EC ECB0 FFFF FFFF FFF5 F5FF 0000"
$"00FF F5EC ECFF FFF5 F5F5 FFF5 F5FF 0000"
$"00FF F5EC F500 FFFF F5F5 F5F5 F5FF 0000"
$"00FF F5EC F505 F7FF FFF5 F5F5 F5FF 0000"
$"00FF F5EC F5F7 0500 FFFF F5F5 F5FF 0000"
$"00FF F5EC EC00 0000 FFFF F5F5 F5FF 0000"
$"00FF F5EC ECEC 00FF FFF5 F5F5 F5FF 0000"
$"00FF F5EC ECEC FFFF F5F5 F5F5 F5FF 0000"
$"00FF F5EC ECB0 FFF5 F5F5 FFF5 F5FF 0000"
$"00FF F5EC ECB0 FFFF FFFF FFF5 F5FF 0000"
$"00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000"
$"00FF FFFF FFFF FFFF FFFF FFFF FFFF"
};
resource 'ics8' (141) {
$"00FF FFFF FFFF FFFF FFFF FFFF FF00 0000"
$"00FF F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"00FF F5EC ECEC FFFF FFFF FFF5 FFFF FF00"
$"00FF F5EC ECEC FFF5 F5F5 FFF5 FFF5 FF00"
$"00FF F5EC ECF5 FFFF F5F5 F5F5 FFF5 FF00"
$"00FF F5EC F5F5 F5FF FFF5 F5F5 FFF5 FF00"
$"00FF F5EC F505 2BF5 FFFF F5F5 FFF5 FF00"
$"00FF F5EC F52B 05F5 FFFF F5F5 FFF5 FF00"
$"00FF F5EC ECF5 F5FF FFF5 F5F5 FFF5 FF00"
$"00FF F5EC ECEC FFFF F5F5 F5F5 FFF5 FF00"
$"00FF F5EC ECEC FFF5 F5FF FFFF FFF5 FF00"
$"00FF F5EC ECEC FFFF FFFF 2BFF F5F5 FF00"
$"00FF F5F5 F5F5 F5F5 F5FF FFF5 F5F5 FF00"
$"00FF FFFF FFFF FFFF FFFF F5F5 F5F5 FF00"
$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 FF00"
$"0000 00FF FFFF FFFF FFFF FFFF FFFF FF"
};
resource 'ics8' (142) {
$"EFF0 EF00 0000 0000 F900 0000 0000 0000"
$"F0EF F000 0000 00F9 D257 0000 0000 0000"
$"EFF0 EF00 0000 7A00 00D2 F900 0000 0000"
$"EFF0 F000 00FA 00F9 FA00 D256 0000 0000"
$"F0EF F000 7B00 FA00 F9FF 00D2 F900 0000"
$"EFEF EFFA 00F9 0000 00F9 FF00 D2F9 0000"
$"F0F0 F900 FA00 0000 0000 FAF9 00D2 F900"
$"EFF9 00FA 00FA F9FA F9FA F9FA FF00 D2F9"
$"F0EF FAF9 FAE5 E6E6 05E5 D2D2 F9FA F900"
$"EFF0 F900 00E6 E505 0505 E6E5 D2F9 0000"
$"F0F9 0000 F7E5 E6E5 05E6 E5E6 E5D2 FF00"
$"EF00 0000 E5E6 E5D2 D2E5 E6E5 E6D2 FF00"
$"F900 FAE6 E5E6 D2E5 D2E5 E5E6 D2D2 F9FA"
$"00FA 00E6 2BD2 E5E6 E5D2 E6E5 D2D2 C9F9"
$"F9C9 2B2B F7D2 E6E5 E6D2 E5E6 F9D2 C2FA"
$"FA00 C3D2 D2D2 E5E6 C2E5 C9F9 D2C3 FAF9"
};
resource 'ics4' (128) {
$"6660 0000 D000 0000 6660 000D 6D00 0000"
$"6660 00D0 06D0 0000 6660 0D0D D06D 0000"
$"6660 D0D0 DF06 D000 666D 0D00 0DF0 6D00"
$"66D0 D000 00DD 06D0 6D0D 0DDD DDDD F06D"
$"66DD D999 1966 DDD0 66D0 0991 1199 6D00"
$"6D00 C999 1999 96F0 6000 9996 6999 96F0"
$"D0D9 9969 6999 66DD 0D09 C699 9699 669D"
$"D9CC C699 9699 D67D D086 6699 799D 68DD"
};
resource 'ics4' (129) {
$"0FFF FFFF FFF0 0000 0F00 0000 00FF 0000"
$"0F06 6600 00FC F000 0F06 66FF 0FFF FF00"
$"0F06 6600 0000 0F00 0F06 60FF F0F0 0F00"
$"0F06 0000 0000 0F00 0F06 00F0 FFF0 0F00"
$"0F06 0000 0000 0F00 0F06 60FF F0F0 0F00"
$"0F06 6600 0000 0F00 0F06 66F0 FFF0 0F00"
$"0F06 6600 0000 0F00 0F06 66FF F0F0 0F00"
$"0F00 0000 0000 0F00 0FFF FFFF FFFF FF"
};
resource 'ics4' (130) {
$"0FFF FFFF FFFF 0000 0F00 0000 000F 0000"
$"0F06 66F0 FF0F FF00 0F06 6600 000F 0F00"
$"0F06 66FF 0F0F 0F00 0F06 6000 000F 0F00"
$"0F06 00F0 FF0F 0F00 0F06 0000 000F 0F00"
$"0F06 60FF 0F0F 0F00 0F06 6600 000F 0F00"
$"0F06 66F0 FFFF 0F00 0F06 6600 FCF0 0F00"
$"0F00 0000 FF00 0F00 0FFF FFFF F00F 0F00"
$"000F 0000 0000 0F00 000F FFFF FFFF FF"
};
resource 'ics4' (131) {
$"0FFF FFFF FFF0 0000 0F00 0000 00FF 0000"
$"0F06 6600 00FC F000 0F06 6600 00FF FF00"
$"0F06 6600 0000 0F00 0F06 6000 0000 0F00"
$"0F06 F0FF 0FF0 0F00 0F06 0000 0000 0F00"
$"0F06 FFFF 0FF0 0F00 0F06 6000 0000 0F00"
$"0F06 FF0F F0F0 0F00 0F06 6600 0000 0F00"
$"0F06 6600 0000 0F00 0F06 6600 0000 0F00"
$"0F00 0000 0000 0F00 0FFF FFFF FFFF FF"
};
resource 'ics4' (132) {
$"00FF FFFF FFFF 0000 00F0 0000 00F0 F000"
$"00F0 6667 CCF0 0F00 00F0 6667 00FF FF00"
$"00F0 666F 0000 0F00 00F0 6670 FF0F FF00"
$"00F0 60CF 00F0 0F00 00F0 6070 FF0F FF00"
$"00F0 60CF 00F0 0F00 00F0 66CF 00F0 0F00"
$"00F0 6650 FF0F FF00 00F0 666F 00F0 0F00"
$"00F0 666F 00F0 0F00 00F0 6660 FF0F FF00"
$"00F0 0000 0000 0F00 00FF FFFF FFFF FF"
};
resource 'ics4' (133) {
$"0FFF FFFF FFFF 0000 0F00 0000 000F 0000"
$"0F06 6670 070F FF00 0F06 660F F0FF 0F00"
$"0F06 66F0 0F0F 0F00 0F06 60F0 0F0F FF00"
$"0F06 070F F0FF 0F00 0F06 00F0 0F0F 0F00"
$"0F06 60F0 0F0F FF00 0F06 660F F0FF 0F00"
$"0F06 66F0 FFFF 0F00 0F06 66F0 FCF0 FF00"
$"0F00 0000 FF00 0F00 0FFF FFFF F0F0 0F00"
$"000F 0000 0000 0F00 000F FFFF FFFF FF"
};
resource 'ics4' (134) {
$"0FFF FFFF FFF0 0000 0F00 0000 00FF 0000"
$"0F06 66DD DDF0 F000 0F06 66DE EEFF FF00"
$"0F06 66DE 1600 0F00 0F06 60DE 3800 FF00"
$"0F06 00DE 000F 0F00 0F06 00DE 0FF0 0F00"
$"0F06 00DF F000 0F00 0F06 60F0 00C0 0F00"
$"0F06 660D DCCC 0F00 0F06 660D D0C0 0F00"
$"0F06 6600 0C00 0F00 0F06 6600 CCC0 0F00"
$"0F00 0000 0000 0F00 0FFF FFFF FFFF FF"
};
resource 'ics4' (135) {
$"0FFF FFFF FFFF F000 0F00 0000 0000 F000"
$"0F06 66DD DDDD FFF0 0F06 66DE EEEE F0F0"
$"0F06 60DE 1600 F0F0 0F06 00DE 3800 F0F0"
$"0F06 00DE 00FF F0F0 0F06 00DE FF00 F0F0"
$"0F06 60FF 0000 F0F0 0F06 6600 0000 F0F0"
$"0F06 66FF 0FFF F0F0 0F06 66FF 0F0F 00F0"
$"0F00 0000 0FF0 00F0 0FFF FFFF FF00 00F0"
$"000F 0000 0000 00F0 000F FFFF FFFF FFF0"
};
resource 'ics4' (136) {
$"0FFF FFFF FFF0 0000 0F00 0000 00FF 0000"
$"0F06 66E0 00F0 F000 0F06 66D0 00FF FF00"
$"0F06 66E0 1660 0F00 0F06 60D1 1666 0F00"
$"0F06 00E1 1166 0F00 0F06 00D1 1343 0F00"
$"0F06 00E0 3430 0F00 0F06 60D0 0000 7F00"
$"0F06 66E0 0707 0F00 0F06 66D0 7070 0F00"
$"0F06 66E0 0000 0F00 0F06 66DE DEDE 0F00"
$"0F00 0000 0000 0F00 0FFF FFFF FFFF FF"
};
resource 'ics4' (137) {
$"0FFF FFFF FFFF F000 0F00 0000 0000 F000"
$"0F06 6601 6600 FFF0 0F06 6711 6660 F0F0"
$"0F06 6E11 1660 F0F0 0F06 0D11 3C30 F0F0"
$"0F06 0E03 C300 F0F0 0F06 0D00 0007 F0F0"
$"0F06 6E00 7070 F0F0 0F06 6707 0700 F0F0"
$"0F06 6600 0FFF F0F0 0F06 67ED EF0F 00F0"
$"0F00 0000 0FF0 00F0 0FFF FFFF FF00 00F0"
$"000F 0000 0000 00F0 000F FFFF FFFF FFF0"
};
resource 'ics4' (138) {
$"00FF FFFF FFF0 0000 00F0 0000 00FF 0000"
$"00F0 666E 30FC F000 00F0 666F 33FF FF00"
$"00F0 666E 111E 0F00 00F0 660F 180F 0F00"
$"00F0 600E FEFE 0F00 00F0 600F 888F 0F00"
$"00F0 600E 888E 0F00 00F0 660F EFEF 0F00"
$"00F0 666E CCCE 0F00 00F0 666F C00F 0F00"
$"00F0 666E FEFE 0F00 00F0 666F 188F 0F00"
$"00F0 0000 0000 0F00 00FF FFFF FFFF FF"
};
resource 'ics4' (139) {
$"0FFF FFFF FFFF F000 0F00 0000 0000 F000"
$"0F06 660A 66A0 FFF0 0F06 660A AAA0 F0F0"
$"0F06 660A 83A0 F0F0 0F06 600A 38A0 F0F0"
$"0F06 000A AAA0 F0F0 0F06 000A 88A0 F0F0"
$"0F06 600A 88A0 F0F0 0F06 660A AAA0 F0F0"
$"0F06 660A 1FFF F0F0 0F06 660A 1FCF 00F0"
$"0F00 0000 0FF0 A0F0 0FFF FFFF FF01 A0F0"
$"000F 0000 0000 00F0 000F FFFF FFFF FFF0"
};
resource 'ics4' (140) {
$"0FFF FFFF FFF0 0000 0F00 0000 00FF 0000"
$"0F06 6600 00FC F000 0F06 6600 00FF FF00"
$"0F06 6FFF FFF0 0F00 0F06 6FF0 00F0 0F00"
$"0F06 00FF 0000 0F00 0F06 01CF F000 0F00"
$"0F06 0C10 FF00 0F00 0F06 6000 FF00 0F00"
$"0F06 660F F000 0F00 0F06 66FF 0000 0F00"
$"0F06 65F0 00F0 0F00 0F06 65FF FFF0 0F00"
$"0F00 0000 0000 0F00 0FFF FFFF FFFF FF"
};
resource 'ics4' (141) {
$"0FFF FFFF FFFF F000 0F00 0000 0000 F000"
$"0F06 66FF FFF0 FFF0 0F06 66F0 00F0 F0F0"
$"0F06 60FF 0000 F0F0 0F06 000F F000 F0F0"
$"0F06 01C0 FF00 F0F0 0F06 0C10 FF00 F0F0"
$"0F06 600F F000 F0F0 0F06 66FF 0000 F0F0"
$"0F06 66F0 0FFF F0F0 0F06 66FF FFCF 00F0"
$"0F00 0000 0FF0 00F0 0FFF FFFF FF00 00F0"
$"000F 0000 0000 00F0 000F FFFF FFFF FFF0"
};
resource 'ics4' (142) {
$"6660 0000 D000 0000 6660 000D 6D00 0000"
$"6660 00D0 06D0 0000 6660 0D0D D06D 0000"
$"6660 D0D0 DF06 D000 666D 0D00 0DF0 6D00"
$"66D0 D000 00DD 06D0 6D0D 0DDD DDDD F06D"
$"66DD D999 1966 DDD0 66D0 0991 1199 6D00"
$"6D00 C999 1999 96F0 6000 9996 6999 96F0"
$"D0D9 9969 6999 66DD 0D09 C699 9699 669D"
$"D9CC C699 9699 D67D D086 6699 799D 68DD"
};
resource 'ics#' (128) {
{ /* array: 2 elements */
/* [1] */
$"E000 E080 E040 E4A0 E250 F028 C824 955A"
$"EF74 C638 8FFE 9776 3DDD 5F76 4BDF BDEA",
/* [2] */
$"E000 E180 E3C0 E7E0 EFF0 FFF8 FFFC FFFE"
$"FFFE FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
}
};
resource 'ics#' (129) {
{ /* array: 2 elements */
/* [1] */
$"7FE0 4430 4428 477C 4404 4BA4 5004 52E4"
$"5004 4BA4 4404 46E4 4404 47A4 4404 7FFC",
/* [2] */
$"7FE0 7FF0 7FF8 7FFC 7FFC 7FFC 7FFC 7FFC"
$"7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC"
}
};
resource 'ics#' (130) {
{ /* array: 2 elements */
/* [1] */
$"7FF0 4410 46DC 4414 4754 4814 52D4 5014"
$"4B54 4414 46F4 44A4 44C4 7F94 1004 1FFC",
/* [2] */
$"7FF0 7FF0 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC"
$"7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 1FFC 1FFC"
}
};
resource 'ics#' (131) {
{ /* array: 2 elements */
/* [1] */
$"7FE0 4830 4828 483C 4804 5004 6B64 6004"
$"6F64 5004 4DA4 4804 4804 4804 4804 7FFC",
/* [2] */
$"7FE0 7FF0 7FF8 7FFC 7FFC 7FFC 7FFC 7FFC"
$"7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC"
}
};
resource 'ics#' (132) {
{ /* array: 2 elements */
/* [1] */
$"3FF0 2228 2324 233C 2304 26DC 2924 2EDC"
$"2924 2524 22DC 2324 2324 22DC 2204 3FFC",
/* [2] */
$"3FF0 3FF8 3FFC 3FFC 3FFC 3FFC 3FFC 3FFC"
$"3FFC 3FFC 3FFC 3FFC 3FFC 3FFC 3FFC 3FFC"
}
};
resource 'ics#' (133) {
{ /* array: 2 elements */
/* [1] */
$"7FF0 4410 465C 45B4 4654 4A5C 55B4 5254"
$"4A5C 45B4 46F4 46AC 44C4 7FA4 1004 1FFC",
/* [2] */
$"7FF0 7FF0 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC"
$"7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 1FFC 1FFC"
}
};
resource 'ics#' (134) {
{ /* array: 2 elements */
/* [1] */
$"7FE0 4830 4BE8 4A3C 4AC4 52CC 6214 6264"
$"6184 5224 4DD4 49A4 4844 48E4 4804 7FFC",
/* [2] */
$"7FE0 7FF0 7FF8 7FFC 7FFC 7FFC 7FFC 7FFC"
$"7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC"
}
};
resource 'ics#' (135) {
{ /* array: 2 elements */
/* [1] */
$"7FF8 4808 4BFE 4A0A 4ACA 52CA 623A 60CA"
$"530A 4C0A 4B7A 4B52 4862 7FC2 1002 1FFE",
/* [2] */
$"7FF8 7FF8 7FFE 7FFE 7FFE 7FFE 7FFE 7FFE"
$"7FFE 7FFE 7FFE 7FFE 7FFE 7FFE 1FFE 1FFE"
}
};
resource 'ics#' (136) {
{ /* array: 2 elements */
/* [1] */
$"7FE0 4830 4A28 483C 4AE4 5174 6334 6154"
$"62A4 500C 4A54 48A4 4A04 4954 4804 7FFC",
/* [2] */
$"7FE0 7FF0 7FF8 7FFC 7FFC 7FFC 7FFC 7FFC"
$"7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC"
}
};
resource 'ics#' (137) {
{ /* array: 2 elements */
/* [1] */
$"7FF8 4808 4DCE 4AEA 4E6A 52AA 654A 601A"
$"52AA 494A 4C7A 4A52 4862 7FC2 1002 1FFE",
/* [2] */
$"7FF8 7FF8 7FFE 7FFE 7FFE 7FFE 7FFE 7FFE"
$"7FFE 7FFE 7FFE 7FFE 7FFE 7FFE 1FFE 1FFE"
}
};
resource 'ics#' (138) {
{ /* array: 2 elements */
/* [1] */
$"3FE0 2230 22A8 22FC 2294 2494 28F4 2894"
$"2894 24F4 2294 2294 22F4 2294 2204 3FFC",
/* [2] */
$"3FE0 3FF0 3FF8 3FFC 3FFC 3FFC 3FFC 3FFC"
$"3FFC 3FFC 3FFC 3FFC 3FFC 3FFC 3FFC 3FFC"
}
};
resource 'ics#' (139) {
{ /* array: 2 elements */
/* [1] */
$"7FF8 4408 452E 45EA 452A 492A 51EA 512A"
$"492A 45EA 457A 4552 446A 7FCA 1002 1FFE",
/* [2] */
$"7FF8 7FF8 7FFE 7FFE 7FFE 7FFE 7FFE 7FFE"
$"7FFE 7FFE 7FFE 7FFE 7FFE 7FFE 1FFE 1FFE"
}
};
resource 'ics#' (140) {
{ /* array: 2 elements */
/* [1] */
$"7FE0 4830 4828 483C 4FE4 5624 6304 6184"
$"60C4 50C4 4984 4B04 4E24 4FE4 4804 7FFC",
/* [2] */
$"7FE0 7FF0 7FF8 7FFC 7FFC 7FFC 7FFC 7FFC"
$"7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC"
}
};
resource 'ics#' (141) {
{ /* array: 2 elements */
/* [1] */
$"7FF8 4808 4FEE 4E2A 4B0A 518A 60CA 60CA"
$"518A 4B0A 4E7A 4FD2 4862 7FC2 1002 1FFE",
/* [2] */
$"7FF8 7FF8 7FFE 7FFE 7FFE 7FFE 7FFE 7FFE"
$"7FFE 7FFE 7FFE 7FFE 7FFE 7FFE 1FFE 1FFE"
}
};
resource 'ics#' (142) {
{ /* array: 2 elements */
/* [1] */
$"E000 E080 E040 E4A0 E250 F028 C824 955A"
$"EF74 C638 8FFE 9776 3DDD 5F76 4BDF BDEA",
/* [2] */
$"E000 E180 E3C0 E7E0 EFF0 FFF8 FFFC FFFE"
$"FFFE FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
}
};
resource 'ICN#' (128) {
{ /* array: 2 elements */
/* [1] */
$"0000 0000 F800 8000 F801 C000 F802 6000"
$"F804 7000 F80C 9800 F818 4C00 F824 9600"
$"F820 1700 F888 2180 F810 01C0 F920 0A60"
$"F800 0130 F401 2258 C108 995C D205 5704"
$"8450 5D87 E843 7760 C1AC 1CC6 F040 0774"
$"FA5C 1DD8 FC57 7770 FA1D 5DDC F977 7774"
$"F55D DDDC FA77 7774 F5DD DDDC FB77 7774"
$"F5DD DDDC FB77 7774 F1DD DDD8 FF77 7770",
/* [2] */
$"0000 0000 F800 8000 F801 C000 F803 E000"
$"F807 F000 F80F F800 F81F FC00 F83F FE00"
$"F83F FF00 F8FF FF80 F9FF FFC0 FBFF FFE0"
$"FFFF FFF0 FFFF FFF8 FFFF FFFC FFFF FFFE"
$"FFFF FFFE FFFF FFFE FFFF FFFE FFFF FFFE"
$"FFFF FFFC FFFF FFFC FFFF FFFC FFFF FFFC"
$"FFFF FFFC FFFF FFFC FFFF FFFC FFFF FFFC"
$"FFFF FFFC FFFF FFFC FFFF FFFC FFFF FFFC"
}
};
resource 'ICN#' (129) {
{ /* array: 2 elements */
/* [1] */
$"1FFF FE00 1040 0300 1040 0280 1040 0240"
$"1040 0220 104D 7E10 1040 03F8 105E 7688"
$"1040 0008 10AD 6B48 1100 0008 115D D748"
$"1200 0008 12D7 6DC8 1200 0008 12BE F6C8"
$"1200 0008 12DD BB08 1100 0008 1176 AAC8"
$"1080 0008 105B BD48 1040 0008 1056 F6C8"
$"1040 0008 105C EE48 1040 0008 105D 7348"
$"1040 0008 1040 0008 1040 0008 1FFF FFF8",
/* [2] */
$"1FFF FE00 1FFF FF00 1FFF FF80 1FFF FFC0"
$"1FFF FFE0 1FFF FFF0 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
}
};
resource 'ICN#' (130) {
{ /* array: 2 elements */
/* [1] */
$"3FFF FFF0 2080 0010 2080 0010 2080 001C"
$"2080 0014 20DB DD14 2080 0014 209D 6D14"
$"2100 0014 22B5 D694 2200 0014 25BD EE14"
$"2400 0014 24B7 9B94 2400 0014 25DC DD94"
$"2400 0014 22DF 3614 2200 0014 216E F594"
$"2080 0014 20E7 7A94 2080 0014 20DE 6FE4"
$"2080 0844 20CD A8A4 2080 0904 20B7 6AA4"
$"2080 0C04 3FFF F804 0800 0004 0FFF FFFC",
/* [2] */
$"3FFF FFF0 3FFF FFF0 3FFF FFF0 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 0FFF FFFC 0FFF FFFC"
}
};
resource 'ICN#' (131) {
{ /* array: 2 elements */
/* [1] */
$"3FFF FC00 2100 0600 2100 0500 2100 0480"
$"2100 0440 2100 0420 2100 07F0 2100 0010"
$"2100 0010 2200 0010 2400 0010 25DD DB10"
$"2800 0010 2800 0010 29DE F710 2800 0010"
$"2800 0010 29BF BB10 2400 0010 2400 0010"
$"2200 0010 2100 0010 2100 0010 2100 0010"
$"2100 0010 2100 0010 2100 0010 2100 0010"
$"2100 0010 2100 0010 2100 0010 3FFF FFF0",
/* [2] */
$"3FFF FC00 3FFF FE00 3FFF FF00 3FFF FF80"
$"3FFF FFC0 3FFF FFE0 3FFF FFF0 3FFF FFF0"
$"3FFF FFF0 3FFF FFF0 3FFF FFF0 3FFF FFF0"
$"3FFF FFF0 3FFF FFF0 3FFF FFF0 3FFF FFF0"
$"3FFF FFF0 3FFF FFF0 3FFF FFF0 3FFF FFF0"
$"3FFF FFF0 3FFF FFF0 3FFF FFF0 3FFF FFF0"
$"3FFF FFF0 3FFF FFF0 3FFF FFF0 3FFF FFF0"
$"3FFF FFF0 3FFF FFF0 3FFF FFF0 3FFF FFF0"
}
};
resource 'ICN#' (132) {
{ /* array: 2 elements */
/* [1] */
$"1FFF FE00 1040 0300 1075 EA80 1044 0A40"
$"107B F620 1044 0A10 1044 0BF8 1044 0808"
$"107B F7F8 1084 0808 1134 0808 1104 0808"
$"12FB F7F8 1204 0808 1274 0808 1204 0808"
$"12FB F7F8 1104 0808 1134 0808 1104 0808"
$"10FB F7F8 1044 0808 1054 0808 1044 0808"
$"107B F7F8 1044 0808 1054 0808 1044 0808"
$"107B F7F8 1044 0808 1040 0008 1FFF FFF8",
/* [2] */
$"1FFF FE00 1FFF FF00 1FFF FF80 1FFF FFC0"
$"1FFF FFE0 1FFF FFF0 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
}
};
resource 'ICN#' (133) {
{ /* array: 2 elements */
/* [1] */
$"3FFF FFF0 2080 0010 2085 EBD0 2084 081C"
$"20FB F7F4 2084 0814 2094 0814 2084 081C"
$"21FB F7F4 2204 0814 2274 0814 2404 081C"
$"25FB F7F4 2404 0814 24F4 0814 2404 081C"
$"25FB F7F4 2204 0814 2274 0814 2104 081C"
$"20FB F7F4 2084 0814 2094 0814 2084 0FEC"
$"20FB F844 2084 0884 2094 0904 2084 0AFC"
$"2080 0C04 3FFF FA04 0800 0004 0FFF FFFC",
/* [2] */
$"3FFF FFF0 3FFF FFF0 3FFF FFF0 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 0FFF FFFC 0FFF FFFC"
}
};
resource 'ICN#' (134) {
{ /* array: 2 elements */
/* [1] */
$"3FFF FC00 2100 0600 217F FD00 2140 0480"
$"2140 0440 214F FC20 2149 87F0 214A 4010"
$"214C 2790 224C 2030 244A 4ED0 2449 8110"
$"2848 0210 284B 6C10 284B 1010 284B 6010"
$"2848 8790 284B 0850 2444 1030 244B F830"
$"2233 F830 2143 F830 2103 F850 2103 FF90"
$"2103 FC10 2103 F610 2100 6B10 2100 D590"
$"2101 FFD0 2100 0010 2100 0010 3FFF FFF0",
/* [2] */
$"3FFF FC00 3FFF FE00 3FFF FF00 3FFF FF80"
$"3FFF FFC0 3FFF FFE0 3FFF FFF0 3FFF FFF0"
$"3FFF FFF0 3FFF FFF0 3FFF FFF0 3FFF FFF0"
$"3FFF FFF0 3FFF FFF0 3FFF FFF0 3FFF FFF0"
$"3FFF FFF0 3FFF FFF0 3FFF FFF0 3FFF FFF0"
$"3FFF FFF0 3FFF FFF0 3FFF FFF0 3FFF FFF0"
$"3FFF FFF0 3FFF FFF0 3FFF FFF0 3FFF FFF0"
$"3FFF FFF0 3FFF FFF0 3FFF FFF0 3FFF FFF0"
}
};
resource 'ICN#' (135) {
{ /* array: 2 elements */
/* [1] */
$"3FFF FFF0 2100 0010 217F FFD0 2140 001C"
$"2140 0014 215F FFD4 2153 0014 2154 8014"
$"2258 4F34 2458 4054 2454 9D94 2853 0214"
$"2850 0414 2856 D814 2856 2014 2856 C014"
$"2851 0F14 2456 1094 2448 2054 2217 F054"
$"2167 F054 2187 F054 2107 F094 2107 FFF4"
$"2107 E824 2107 D844 2100 A884 2101 F904"
$"2100 0A04 3FFF FC04 0800 0004 0FFF FFFC",
/* [2] */
$"3FFF FFF0 3FFF FFF0 3FFF FFF0 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 0FFF FFFC 0FFF FFFC"
}
};
resource 'ICN#' (136) {
{ /* array: 2 elements */
/* [1] */
$"1FFF FE00 1080 0300 1088 0280 1098 0240"
$"1088 0220 1088 0210 109C 1FF8 1088 6788"
$"1088 87C8 1118 87C8 1209 07E8 1209 07E8"
$"141D 0FE8 1409 1AA8 1408 B548 1418 EAD8"
$"1408 75A8 1408 1E28 121C 0048 1208 6048"
$"1108 6088 1098 9088 1088 8908 1089 0708"
$"109B 0308 108B 0008 1088 0408 108F FFE8"
$"1081 2488 1080 0008 1080 0008 1FFF FFF8",
/* [2] */
$"1FFF FE00 1FFF FF00 1FFF FF80 1FFF FFC0"
$"1FFF FFE0 1FFF FFF0 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
}
};
resource 'ICN#' (137) {
{ /* array: 2 elements */
/* [1] */
$"3FFF FFF0 2100 0010 2100 0010 2170 781C"
$"2121 9E14 2122 1F14 2162 1F14 2124 1F94"
$"2224 1F94 2474 3F94 2424 6A94 2822 D514"
$"2863 AB54 2821 D694 2820 7894 2870 0114"
$"2821 8114 2421 8214 2462 4214 2222 2414"
$"2124 1C14 216C 0C14 212C 0014 2120 0FE4"
$"213F F844 2104 9884 2100 0904 2100 0A04"
$"2100 0C04 3FFF F804 0800 0004 0FFF FFFC",
/* [2] */
$"3FFF FFF0 3FFF FFF0 3FFF FFF0 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 0FFF FFFC 0FFF FFFC"
}
};
resource 'ICN#' (138) {
{ /* array: 2 elements */
/* [1] */
$"1FFF FE00 1040 0300 105E AA80 105C 4240"
$"1056 2A20 1055 0210 105F FFF8 105F FFE8"
$"105E AAE8 109C 81E8 1116 14A8 1114 16A8"
$"121E 82E8 121C 25E8 121E 80E8 121F FFE8"
$"1217 FFA8 1214 00A8 111C AAE8 111D 54E8"
$"109C 2AE8 105D 44E8 1054 0AA8 1055 14A8"
$"105F FFE8 105F FFE8 105C 20E8 105D 52E8"
$"1054 09A8 1055 40A8 1040 0008 1FFF FFF8",
/* [2] */
$"1FFF FE00 1FFF FF00 1FFF FF80 1FFF FFC0"
$"1FFF FFE0 1FFF FFF0 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
}
};
resource 'ICN#' (139) {
{ /* array: 2 elements */
/* [1] */
$"3FFF FFF0 2080 0010 20AC 5550 20AA 2B5C"
$"20BD 55D4 20BF FFD4 20BF FFD4 20BD 03D4"
$"212C 2B54 222D 2D54 223D 05D4 243C 4BD4"
$"243D ABD4 243F FFD4 242F FF54 2428 0154"
$"2439 55D4 223A A9D4 2238 55D4 213A 89D4"
$"20A8 1554 20AA 2954 20BF FFD4 20BF FFE4"
$"20B8 4854 20BA A8B4 20A8 1974 20AA 8A74"
$"2080 0DD4 3FFF F854 0800 0004 0FFF FFFC",
/* [2] */
$"3FFF FFF0 3FFF FFF0 3FFF FFF0 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 0FFF FFFC 0FFF FFFC"
}
};
resource 'ICN#' (140) {
{ /* array: 2 elements */
/* [1] */
$"1FFF FE00 1080 0300 1080 0280 1080 0240"
$"1080 0220 1080 6210 1080 0FF8 1080 0188"
$"109F FE08 111F FF08 121E 0308 120E 0008"
$"1407 0108 1403 8008 1411 C008 1448 E008"
$"1440 F048 1400 70C8 1208 3048 1200 6008"
$"1100 C008 1081 8008 1083 0088 1086 0088"
$"108C 0188 109F FF08 109F FF08 1080 0008"
$"1098 0008 1098 0008 1080 0008 1FFF FFF8",
/* [2] */
$"1FFF FE00 1FFF FF00 1FFF FF80 1FFF FFC0"
$"1FFF FFE0 1FFF FFF0 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
$"1FFF FFF8 1FFF FFF8 1FFF FFF8 1FFF FFF8"
}
};
resource 'ICN#' (141) {
{ /* array: 2 elements */
/* [1] */
$"3FFF FFF0 2080 0010 2080 0010 2080 C01C"
$"2080 1814 2080 0314 20BF FC14 20BF FE14"
$"213C 0614 221C 0014 220E 0214 2407 0014"
$"2407 8014 2421 C014 2481 E014 2480 E114"
$"2400 6014 2210 C014 2201 8014 2103 0014"
$"2086 0114 208C 0114 2098 0314 20BF FFE4"
$"20BF F844 2080 0884 20B0 0904 20B0 0A04"
$"2080 0C04 3FFF F804 0800 0004 0FFF FFFC",
/* [2] */
$"3FFF FFF0 3FFF FFF0 3FFF FFF0 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC"
$"3FFF FFFC 3FFF FFFC 0FFF FFFC 0FFF FFFC"
}
};
resource 'ICN#' (142) {
{ /* array: 2 elements */
/* [1] */
$"0000 0000 F800 8000 F801 C000 F802 6000"
$"F804 7000 F80C 9800 F818 4C00 F824 9600"
$"F820 1700 F888 2180 F810 01C0 F920 0A60"
$"F800 0130 F401 2258 C108 995C D205 5704"
$"8450 5D87 E843 7760 C1AC 1CC6 F040 0774"
$"FA5C 1DD8 FC57 7770 FA1D 5DDC F977 7774"
$"F55D DDDC FA77 7774 F5DD DDDC FB77 7774"
$"F5DD DDDC FB77 7774 F1DD DDD8 FF77 7770",
/* [2] */
$"0000 0000 F800 8000 F801 C000 F803 E000"
$"F807 F000 F80F F800 F81F FC00 F83F FE00"
$"F83F FF00 F8FF FF80 F9FF FFC0 FBFF FFE0"
$"FFFF FFF0 FFFF FFF8 FFFF FFFC FFFF FFFE"
$"FFFF FFFE FFFF FFFE FFFF FFFE FFFF FFFE"
$"FFFF FFFC FFFF FFFC FFFF FFFC FFFF FFFC"
$"FFFF FFFC FFFF FFFC FFFF FFFC FFFF FFFC"
$"FFFF FFFC FFFF FFFC FFFF FFFC FFFF FFFC"
}
};
resource 'icl8' (128) {
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"F0EF F0EF F000 0000 0000 0000 0000 0000"
$"FA00 0000 0000 0000 0000 0000 0000 0000"
$"F0EF F0EF F000 0000 0000 0000 0000 00FA"
$"D2FA 0000 0000 0000 0000 0000 0000 0000"
$"EFF0 EFF0 EF00 0000 0000 0000 0000 FA00"
$"F9D2 FA00 0000 0000 0000 0000 0000 0000"
$"F0EF F0EF F000 0000 0000 0000 00FA 0000"
$"00FA D2FA 0000 0000 0000 0000 0000 0000"
$"EFF0 EFF0 EF00 0000 0000 0000 FAFF 0000"
$"FA00 57D2 FA00 0000 0000 0000 0000 0000"
$"EFF0 EFF0 EF00 0000 0000 00FA FF00 F7F9"
$"00FF 00F9 D2FA 0000 0000 0000 0000 0000"
$"F0EF F0EF F000 0000 0000 FA00 00FA F900"
$"FA00 00FA F9D2 FA00 0000 0000 0000 0000"
$"EFF0 EFF0 EF00 0000 007B FF00 00F9 0000"
$"00F9 00FF 00FA D2FA 0000 0000 0000 0000"
$"F0EF F0EF F000 0000 FA00 002B FA00 0000"
$"0000 FA00 0000 F9D2 FA00 0000 0000 0000"
$"EFF0 EFF0 EF00 00F9 0000 00FA 0000 0000"
$"0000 00F9 0000 00FA D2FA 0000 0000 0000"
$"F0EF F0EF F000 F9FF 0000 FA00 0000 0000"
$"0000 0000 FA00 FFF9 F9D2 FA00 0000 0000"
$"EFF0 EFF0 EFF9 0000 F7F9 0000 0000 0000"
$"0000 0000 00F9 00FF 00F9 D2FA 0000 0000"
$"F0EF EFF0 F9FF 0000 F900 0000 0000 F9FA"
$"00F9 FAF9 FA00 FA00 00FA F9D2 FA00 0000"
$"EFF0 F0F9 0000 00FA 0000 0000 FAF9 00F9"
$"FA00 F9FA FFF9 F9FA 00FF 00FA D2FA 0000"
$"EFF0 F9FF 0000 FA00 0000 00F9 00FA 00C9"
$"00D2 00D2 C2EF F0F0 F900 0000 F9D2 7B00"
$"F0F9 0000 00FA 0000 00FA 00D2 0000 C200"
$"05E6 E5E6 D2E5 EFEF F0F9 0000 00FA D2FA"
$"EFEF FA00 FA00 0000 F9D2 0000 D2F9 E6E6"
$"05E5 E6E5 E5E6 E6E5 EFF0 FA00 0000 F900"
$"F0EF EFF9 0000 00FA FA00 C300 FAE6 E505"
$"0505 E5D2 D2E5 E5F9 E6E5 EFF9 00FA 8C00"
$"F0EF F0F0 FA00 F900 00D2 00F9 E505 0505"
$"0505 0505 E5D2 E6E6 E5EF F0FF F98C 0000"
$"EFF0 EFEF F0F9 FA00 F9D2 FAD2 C8E5 E505"
$"0505 E6E5 E6E5 E6EF E6E5 E6FF FF00 0000"
$"EFF0 EFF0 EFFA 0000 D2FA 00C2 E5E5 E6E6"
$"05E6 D2E6 E5E6 E5E5 E5E6 FFE5 F000 0000"
$"F0EF F0EF F0F9 FAF9 0000 E6E6 E5E6 E5E5"
$"05E5 E6D2 E6E5 E6EF E5EF E5FF F0FF 0000"
$"EFF0 EFF0 F900 00FA D2C2 C9C2 E6E5 D2E5"
$"E6D2 D2D2 E5E5 E6E5 E6E5 FFEF E5FF 0000"
$"F0EF F0EF 00FA 00D2 F9EB D2C9 E5D2 D2E6"
$"D2D2 D2E5 E6E6 E5E6 EFE6 E5E6 EFFF 0000"
$"EFF0 EFEF FAF9 D200 D2D2 D2D2 D2D2 D2D2"
$"E5E6 E5E6 E5E5 E6E5 E6E5 F0EF F0FF 0000"
$"F0EF F0F0 00D2 00D2 D2D2 D2E5 E5E6 E5E6"
$"D2E5 D2E5 E6E5 E5E6 EFE5 EFE5 EFFF 0000"
$"EFF0 EFF0 F900 D2D2 D2D2 E5E5 E6E5 E6E5"
$"E5D2 E5E6 E5E6 E5E6 E5EF E5FF EFFF 0000"
$"EFEF F0EF 00D2 00D2 D2E5 E6E6 E5E6 E5E6"
$"E6D2 D2E5 E6E5 E6E5 EFF0 FFE5 FFFF 0000"
$"F0F0 EFF0 FAF9 D2D2 D2E6 E5E5 E6E5 E6E5"
$"E5D2 D2E5 E6E5 E6E5 F0E6 E5EF FFFF 0000"
$"EFEF F0EF F000 F0D2 D2D2 E6E5 E6E5 E6E5"
$"E6D2 D2D2 E5E6 EFE6 EFF0 EFFF FF00 0000"
$"F0F0 EFF0 EFFA C2F0 EFD2 D2D2 E5E6 E5E6"
$"D2D2 F0D2 D2EF F0EF F0EF FFFF FF"
};
resource 'icl8' (129) {
$"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 FFFF 0000 0000 0000 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 FF2B FF00 0000 0000 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 FF2B 2BFF 0000 0000 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 FF2B 2B2B FF00 0000 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 FFFF F5FF"
$"F5FF FFFF FFFF FF2B 2B2B 2BFF 0000 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 FFFF FFFF FFFF FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FF FFFF FFF5"
$"F5FF FFFF F5FF FFF5 FFF5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECF5 FFF5 FFFF F5FF"
$"F5FF FFF5 FFF5 FFFF F5FF F5F5 FF00 0000"
$"0000 00FF F5EC ECEC F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC F5FF F5FF FFFF F5FF"
$"FFFF F5FF F5FF FFFF F5FF F5F5 FF00 0000"
$"0000 00FF F5EC ECF5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECF5 FFFF F5FF F5FF FFFF"
$"F5FF FFF5 FFFF F5FF FFFF F5F5 FF00 0000"
$"0000 00FF F5EC ECF5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECF5 FFF5 FFFF FFFF FFF5"
$"FFFF FFFF F5FF FFF5 FFFF F5F5 FF00 0000"
$"0000 00FF F5EC ECF5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECF5 FFFF F5FF FFFF F5FF"
$"FFF5 FFFF FFF5 FFFF F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC F5FF FFFF F5FF FFF5"
$"FFF5 FFF5 FFF5 FFF5 FFFF F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FF FFF5 FFFF"
$"FFF5 FFFF FFFF F5FF F5FF F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FF F5FF FFF5"
$"FFFF FFFF F5FF FFF5 FFFF F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FF FFFF F5F5"
$"FFFF FFF5 FFFF FFF5 F5FF F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FF FFFF F5FF"
$"F5FF FFFF F5F5 FFFF F5FF F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF FF"
};
resource 'icl8' (130) {
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000"
$"0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF FFFF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECFF F5FF FFF5 FFFF"
$"FFFF F5FF FFFF F5FF F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5FF FFFF F5FF"
$"F5FF FFF5 FFFF F5FF F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECF5 FFF5 FFFF F5FF F5FF"
$"FFFF F5FF F5FF FFF5 FFF5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECF5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5FF FFF5 FFFF FFFF F5FF"
$"FFFF FFF5 FFFF FFF5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5F5 FFF5 FFFF F5FF FFFF"
$"FFF5 F5FF FFF5 FFFF FFF5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5FF FFFF F5FF FFFF F5F5"
$"FFFF F5FF FFFF F5FF FFF5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECF5 FFFF F5FF FFFF FFFF"
$"F5F5 FFFF F5FF FFF5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECF5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC F5FF FFF5 FFFF FFF5"
$"FFFF FFFF F5FF F5FF FFF5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECFF FFF5 F5FF FFFF"
$"F5FF FFFF FFF5 FFF5 FFF5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECFF F5FF FFFF FFF5"
$"F5FF FFF5 FFFF FFFF FFFF FFF5 F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 FF2B 2B2B 2BFF F5F5 F5FF 0000"
$"0000 FFF5 ECEC ECEC ECFF F5F5 FFFF F5FF"
$"FFF5 FFF5 FF2B 2B2B FFF5 FFF5 F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 FF2B 2BFF F5F5 F5F5 F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FFFF F5FF FFFF"
$"F5FF FFF5 FF2B FFF5 FFF5 FFF5 F5FF 0000"
$"0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 FFFF F5F5 F5F5 F5F5 F5FF 0000"
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFF5 F5F5 F5F5 F5F5 F5FF 0000"
$"0000 0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000"
$"0000 0000 FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
};
resource 'icl8' (131) {
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF 0000 0000 0000 0000 0000"
$"0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5FF FF00 0000 0000 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5FF 2BFF 0000 0000 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5FF 2B2B FF00 0000 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5FF 2B2B 2BFF 0000 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5FF 2B2B 2B2B FF00 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5FF FFFF FFFF FFFF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECF5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECFF FFFF F5FF FFFF F5FF"
$"FFFF F5FF FFF5 FFFF F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC F5FF FFFF F5FF FFFF FFF5"
$"FFFF FFFF F5FF FFFF F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC F5FF FFF5 FFFF FFFF FFFF"
$"FFF5 FFFF FFF5 FFFF F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECF5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECF5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF"
};
resource 'icl8' (132) {
$"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 FFFF 0000 0000 0000 0000"
$"0000 00FF F5EC ECEC ECEC FFFF 48C0 48FF"
$"FFFF FF48 C048 FF2B FF00 0000 0000 0000"
$"0000 00FF F5EC ECEC ECEC 4848 48C0 4848"
$"4848 4848 C048 FF2B 2BFF 0000 0000 0000"
$"0000 00FF F5EC ECEC ECEC C0C0 C000 FFFF"
$"FFFF FFFF 00FF FF2B 2B2B FF00 0000 0000"
$"0000 00FF F5EC ECEC ECEC 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 FF2B 2B2B 2BFF 0000 0000"
$"0000 00FF F5EC ECEC ECEC 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 FFFF FFFF FFFF FF00 0000"
$"0000 00FF F5EC ECEC ECEC 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC C0C0 C000 FFFF"
$"FFFF FFFF 00FF FFFF FFFF FFFF FF00 0000"
$"0000 00FF F5EC ECEC EC48 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC 4848 FFFF 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC 4848 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECF5 C0C0 C0C0 C000 FFFF"
$"FFFF FFFF 00FF FFFF FFFF FFFF FF00 0000"
$"0000 00FF F5EC ECF5 4848 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECF5 48FF FFFF 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECF5 4848 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECF5 C0C0 C0C0 C000 FFFF"
$"FFFF FFFF 00FF FFFF FFFF FFFF FF00 0000"
$"0000 00FF F5EC ECF5 4848 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC 4848 FFFF 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC 4848 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECC0 C0C0 C000 FFFF"
$"FFFF FFFF 00FF FFFF FFFF FFFF FF00 0000"
$"0000 00FF F5EC ECEC ECEC 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC 48FF 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC C0C0 C000 FFFF"
$"FFFF FFFF 00FF FFFF FFFF FFFF FF00 0000"
$"0000 00FF F5EC ECEC ECEC 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC 48FF 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC C0C0 C000 FFFF"
$"FFFF FFFF 00FF FFFF FFFF FFFF FF00 0000"
$"0000 00FF F5EC ECEC ECEC 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF FF"
};
resource 'icl8' (133) {
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000"
$"0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC EC48 4848 48C0 48FF"
$"FFFF FF48 C048 FFFF FFFF 48FF 0000 0000"
$"0000 FFF5 ECEC ECEC EC48 4848 48C0 4848"
$"4848 4848 C048 4848 4848 48FF FFFF 0000"
$"0000 FFF5 ECEC ECEC ECC0 C0C0 C000 FFFF"
$"FFFF FFFF 00FF FFFF FFFF FFFF 00FF 0000"
$"0000 FFF5 ECEC ECEC EC48 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5FF 00FF 0000"
$"0000 FFF5 ECEC ECEC EC48 48FF 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5FF 00FF 0000"
$"0000 FFF5 ECEC ECEC EC48 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5FF FFFF 0000"
$"0000 FFF5 ECEC ECEC C0C0 C0C0 C000 FFFF"
$"FFFF FFFF 00FF FFFF FFFF FFFF 00FF 0000"
$"0000 FFF5 ECEC EC48 4848 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5FF 00FF 0000"
$"0000 FFF5 ECEC EC48 48FF FFFF 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5FF 00FF 0000"
$"0000 FFF5 ECEC F548 4848 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5FF FFFF 0000"
$"0000 FFF5 ECEC F5C0 C0C0 C0C0 C000 FFFF"
$"FFFF FFFF 00FF FFFF FFFF FFFF 00FF 0000"
$"0000 FFF5 ECEC F548 4848 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5FF 00FF 0000"
$"0000 FFF5 ECEC F548 FFFF FFFF 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5FF 00FF 0000"
$"0000 FFF5 ECEC F548 4848 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5FF FFFF 0000"
$"0000 FFF5 ECEC F5C0 C0C0 C0C0 C000 FFFF"
$"FFFF FFFF 00FF FFFF FFFF FFFF 00FF 0000"
$"0000 FFF5 ECEC EC48 4848 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5FF 00FF 0000"
$"0000 FFF5 ECEC EC48 48FF FFFF 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5FF 00FF 0000"
$"0000 FFF5 ECEC ECEC 4848 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5FF FFFF 0000"
$"0000 FFF5 ECEC ECEC ECC0 C0C0 C000 FFFF"
$"FFFF FFFF 00FF FFFF FFFF FFFF 00FF 0000"
$"0000 FFF5 ECEC ECEC EC48 4848 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5FF 00FF 0000"
$"0000 FFF5 ECEC ECEC EC48 48FF 48FF F5F5"
$"F5F5 F5F5 FFF5 F5F5 F5F5 F5FF 00FF 0000"
$"0000 FFF5 ECEC ECEC EC48 4848 48FF F5F5"
$"F5F5 F5F5 FFFF FFFF FFFF FF00 FFFF 0000"
$"0000 FFF5 ECEC ECEC ECC0 C0C0 C000 FFFF"
$"FFFF FFFF FF2B 2B2B 2BFF 0000 00FF 0000"
$"0000 FFF5 ECEC ECEC EC48 4848 48FF F5F5"
$"F5F5 F5F5 FF2B 2B2B FF00 0000 00FF 0000"
$"0000 FFF5 ECEC ECEC EC48 48FF 48FF F5F5"
$"F5F5 F5F5 FF2B 2BFF 0000 0000 00FF 0000"
$"0000 FFF5 ECEC ECEC EC48 4848 48FF F5F5"
$"F5F5 F5F5 FF2B FF00 FFFF FFFF FFFF 0000"
$"0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 FFFF 0000 0000 0000 00FF 0000"
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FF00 FF00 0000 0000 00FF 0000"
$"0000 0000 FF00 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 00FF 0000"
$"0000 0000 FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
};
resource 'icl8' (134) {
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF 0000 0000 0000 0000 0000"
$"0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5FF FF00 0000 0000 0000 0000"
$"0000 FFF5 ECEC ECEC ECFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF 2BFF 0000 0000 0000 0000"
$"0000 FFF5 ECEC ECEC ECFF 2B2B 2B2B 2B2B"
$"2B2B 2B2B 2BFF 2B2B FF00 0000 0000 0000"
$"0000 FFF5 ECEC ECEC ECFF 2BF8 F8F8 F8F8"
$"F8F8 F8F8 F8FF 2B2B 2BFF 0000 0000 0000"
$"0000 FFF5 ECEC ECEC ECFF 2BF8 FFFF FFFF"
$"FFFF FFFF FFFF 2B2B 2B2B FF00 0000 0000"
$"0000 FFF5 ECEC ECEC ECFF 2BF8 FFF5 F505"
$"ECF5 F5F5 F5FF FFFF FFFF FFFF 0000 0000"
$"0000 FFF5 ECEC ECEC ECFF 2BF8 FFF5 0505"
$"ECEC F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECFF 2BF8 FF05 0505"
$"ECEC ECF5 F5FF FFFF FFF5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC F5FF 2BF8 FFD8 D8D8"
$"E3E3 E3F5 F5F5 F5F5 F5F5 FFFF 0000 0000"
$"0000 FFF5 ECEC ECF5 F5FF 2BF8 FFF5 D8D8"
$"E3E3 F5F5 FFFF FFF5 FFFF F5FF 0000 0000"
$"0000 FFF5 ECEC ECF5 F5FF 2BF8 FFF5 F5D8"
$"E3F5 F5F5 F5F5 F5FF F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC F5F5 F5FF 2BF8 FFF5 F5F5"
$"F5F5 F5F5 F5F5 FFF5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC F5F5 F5FF 2BF8 FFF5 FFFF"
$"F5FF FFF5 FFFF F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC F5F5 F5FF 2BF8 FFF5 FFFF"
$"F5F5 F5FF F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC F5F5 F5FF 2BF8 FFF5 FFFF"
$"F5FF FFF5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC F5F5 F5FF 2BF8 FFF5 F5F5"
$"FFF5 F5F5 F5FF FFFF FFF5 F5FF 0000 0000"
$"0000 FFF5 ECEC F5F5 F5FF 2BF8 FFF5 FFFF"
$"F5F5 F5F5 FFF6 F6F6 F6FF F5FF 0000 0000"
$"0000 FFF5 ECEC ECF5 F5FF 2BF8 F5FF F5F5"
$"F5F5 F5FF F6F6 F6F6 F6F6 FFFF 0000 0000"
$"0000 FFF5 ECEC ECF5 F5FF F5F5 FFF5 FFFF"
$"FFFF FFFF FFF6 F6F6 F6F6 FFFF 0000 0000"
$"0000 FFF5 ECEC ECEC F5F5 FFFF F5F5 FFFA"
$"FAFA FAFA FFF6 F6F6 F6F6 FFFF 0000 0000"
$"0000 FFF5 ECEC ECEC ECFF F5F5 F5F5 FFFA"
$"FAFA FAFA FFF6 F6F6 F6F6 FFFF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 FFFA"
$"FAFA FAFA FFF6 F6F6 F6FF F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 FFFA"
$"FAFA FAFA FFFF FFFF FFF5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 FFFA"
$"FAFA FAFF F8FF F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 FFFF"
$"FFFF FFF8 F8F8 FFF5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5FF F8F8 F8F8 F8FF F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"FFF8 F8F8 F8F8 F8F8 FFF5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5FF"
$"FFFF FFFF FFFF FFFF FFFF F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF"
};
resource 'icl8' (135) {
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000"
$"0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECFF 2B2B 2B2B 2B2B"
$"2B2B 2B2B 2B2B 2B2B 2B2B F5FF FFFF 0000"
$"0000 FFF5 ECEC ECEC ECFF 2BF8 F8F8 F8F8"
$"F8F8 F8F8 F8F8 F8F8 F8F8 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECFF 2BFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECFF 2BFF F5F5 05EC"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECFF 2BFF F505 05EC"
$"ECF5 F5F5 F5F5 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC F5FF 2BFF 0505 05EC"
$"ECEC F5F5 FFFF FFFF F5F5 FFFF F5FF 0000"
$"0000 FFF5 ECEC ECF5 F5FF 2BFF D8D8 D8E3"
$"E3E3 F5F5 F5F5 F5F5 F5FF F5FF F5FF 0000"
$"0000 FFF5 ECEC ECF5 F5FF 2BFF F5D8 D8E3"
$"E3F5 F5FF FFFF F5FF FFF5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5F5 F5FF 2BFF F5F5 D8E3"
$"F5F5 F5F5 F5F5 FFF5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5F5 F5FF 2BFF F5F5 F5F5"
$"F5F5 F5F5 F5FF F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5F5 F5FF 2BFF F5FF FFF5"
$"FFFF F5FF FFF5 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5F5 F5FF 2BFF F5FF FFF5"
$"F5F5 FFF5 F5F5 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5F5 F5FF 2BFF F5FF FFF5"
$"FFFF F5F5 F5F5 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5F5 F5FF 2BFF F5F5 F5FF"
$"F5F5 F5F5 FFFF FFFF F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECF5 F5FF 2BFF F5FF FFF5"
$"F5F5 F5FF F6F6 F6F6 FFF5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECF5 F5FF 2B00 FFF5 F5F5"
$"F5F5 FFF6 F6F6 2BF6 F6FF F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC F5F5 F5FF F5FF FFFF"
$"FFFF FFFF F6F6 F6F6 F6FF F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECFF FFF5 F5FF FAFA"
$"FAFA FAFF F6F6 F6F6 F6FF F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5FF FAFA"
$"FAFA FAFF F62B F6F6 F6FF F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5FF FAFA"
$"FAFA FAFF F6F6 F6F6 FFF5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5FF FAFA"
$"FAFA FAFF FFFF FFFF FFFF FFFF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5FF FAFA"
$"FAFA FFF8 FF2B 2B2B 2B2B FFF5 F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5FF FFFF"
$"FFFF F8F8 FF2B 2B2B 2BFF F5F5 F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"FFF8 F8F8 FF2B 2B2B FFF5 F5F5 F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5FF"
$"FFFF FFFF FF2B 2BFF F5F5 F5F5 F5FF 0000"
$"0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 FF2B FFF5 F5F5 F5F5 F5FF 0000"
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF F5F5 F5F5 F5F5 F5FF 0000"
$"0000 0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000"
$"0000 0000 FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
};
resource 'icl8' (136) {
$"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 FFFF 0000 0000 0000 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 FFF5 F5F5"
$"F5F5 F5F5 F5F5 FF2B FF00 0000 0000 0000"
$"0000 00FF F5EC ECEC ECEC F5FF FFF5 F5F5"
$"F5F5 F5F5 F5F5 FF2B 2BFF 0000 0000 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 FFF5 F5F5"
$"F5F5 F5F5 F5F5 FF2B 2B2B FF00 0000 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 FFF5 F5F5"
$"F5F5 F5F5 F5F5 FF2B 2B2B 2BFF 0000 0000"
$"0000 00FF F5EC ECEC ECEC F5FF FFFF F5F5"
$"F5F5 F5FF FFFF FFFF FFFF FFFF FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 FFF5 F5F5"
$"F5FF FF05 05FF ECFF FFF5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 FFF5 F5F5"
$"FF05 0505 05FF ECEC ECFF F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECF5 F5FF FFF5 F5F5"
$"FF05 0505 05FF ECEC ECFF F5F5 FF00 0000"
$"0000 00FF F5EC ECEC F5F5 F5F5 FFF5 F5FF"
$"0505 0505 05FF ECEC ECEC FFF5 FF00 0000"
$"0000 00FF F5EC ECEC F5F5 F5F5 FFF5 F5FF"
$"0505 0505 05FF ECEC ECEC FFF5 FF00 0000"
$"0000 00FF F5EC ECF5 F5F5 F5FF FFFF F5FF"
$"0505 0505 FFFF FFFF FFFF FFF5 FF00 0000"
$"0000 00FF F5EC ECF5 F5F5 F5F5 FFF5 F5FF"
$"0505 05FF D813 D813 D813 FFF5 FF00 0000"
$"0000 00FF F5EC ECF5 F5F5 F5F5 FFF5 F5F5"
$"FF05 FFD8 13D8 13D8 13FF F5F5 FF00 0000"
$"0000 00FF F5EC ECF5 F5F5 F5FF FFF5 F5F5"
$"FFFF D813 D813 D813 D8FF F5C0 FF00 0000"
$"0000 00FF F5EC ECF5 F5F5 F5F5 FFF5 F5F5"
$"F5FF FFD8 13D8 13FF FFF5 C0F5 FF00 0000"
$"0000 00FF F5EC ECF5 F5F5 F5F5 FFF5 F5F5"
$"F5F5 F5FF FFFF FFF5 F5F5 C0F5 FF00 0000"
$"0000 00FF F5EC ECEC F5F5 F5FF FFFF F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5C0 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC F5F5 F5F5 FFF5 F5F5"
$"F5C0 C0F5 F5F5 F5F5 F5C0 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECF5 F5F5 FFF5 F5F5"
$"F5C0 C0F5 F5F5 F5F5 C0F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FF FFF5 F5F5"
$"C0F5 F5C0 F5F5 F5F5 C0F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 FFF5 F5F5"
$"C0F5 F5F5 C0F5 F5C0 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 FFF5 F5C0"
$"F5F5 F5F5 F5C0 C0C0 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FF FFF5 C0C0"
$"F5F5 F5F5 F5F5 C0C0 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 FFF5 C0C0"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 FFF5 F5F5"
$"F5F5 F5F5 F5FF F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFF5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 F5F5 F5FF"
$"F5F5 FFF5 F5FF F5F5 FFF5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF FF"
};
resource 'icl8' (137) {
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000"
$"0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECFF FFFF F5F5 F5F5"
$"F5FF FFFF FFF5 F5F5 F5F5 F5FF FFFF 0000"
$"0000 FFF5 ECEC ECEC EC00 FFF5 F5F5 F5FF"
$"FF05 05FF ECFF FFF5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC EC00 FFF5 F5F5 FF05"
$"0505 05FF ECEC ECFF F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECFF FFF5 F5F5 FF05"
$"0505 05FF ECEC ECFF F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FFF5 F5FF 0505"
$"0505 05FF ECEC ECEC FFF5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC F5F5 FFF5 F5FF 0505"
$"0505 05FF ECEC ECEC FFF5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECF5 F5FF FFFF F5FF 0505"
$"0505 FFFF FFFF FFFF FFF5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECF5 F5F5 FFF5 F5FF 0505"
$"05FF D813 D813 D813 FFF5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5F5 F5F5 FFF5 F5F5 FF05"
$"FFD8 13D8 13D8 13FF F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5F5 F5FF FFF5 F5F5 FFFF"
$"D813 D813 D813 D8FF F5C0 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5F5 F5F5 FFF5 F5F5 F5FF"
$"FFD8 13D8 13FF FFF5 C0F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5F5 F5F5 FFF5 F5F5 F5F5"
$"F5FF FFFF FFF5 F5F5 C0F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5F5 F5FF FFFF F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5C0 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5F5 F5F5 FFF5 F5F5 F5C0"
$"C0F5 F5F5 F5F5 F5C0 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECF5 F5F5 FFF5 F5F5 F5C0"
$"C0F5 F5F5 F5F5 C0F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECF5 F5FF FFF5 F5F5 C0F5"
$"F5C0 F5F5 F5F5 C0F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC F5F5 FFF5 F5F5 C0F5"
$"F5F5 C0F5 F5C0 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FFF5 F5C0 F5F5"
$"F5F5 F5C0 C0C0 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECFF FFF5 C0C0 F5F5"
$"F5F5 F5F5 C0C0 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FFF5 C0C0 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FFF5 F5F5 F5F5"
$"F5F5 F5F5 FFFF FFFF FFFF FFF5 F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FFFF FFFF FFFF"
$"FFFF FFFF FF2B 2B2B 2BFF F5F5 F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5FF F5F5"
$"FFF5 F5FF FF2B 2B2B FFF5 F5F5 F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 FF2B 2BFF F5F5 F5F5 F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 FF2B FFF5 F5F5 F5F5 F5FF 0000"
$"0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 FFFF F5F5 F5F5 F5F5 F5FF 0000"
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFF5 F5F5 F5F5 F5F5 F5FF 0000"
$"0000 0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000"
$"0000 0000 FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
};
resource 'icl8' (138) {
$"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 FFFF 0000 0000 0000 0000"
$"0000 00FF F5EC ECEC ECEC F5FD FDFD D8D8"
$"D8D8 D8D8 D8D8 FF2B FF00 0000 0000 0000"
$"0000 00FF F5EC ECEC ECEC F5FD FDFD D8F9"
$"F9D8 F9F9 D8D8 FF2B 2BFF 0000 0000 0000"
$"0000 00FF F5EC ECEC ECEC F5FD 00FD D8D8"
$"F9F9 D8D8 D8F9 FF2B 2B2B FF00 0000 0000"
$"0000 00FF F5EC ECEC ECEC F5FD 00FD F9D8"
$"D8F9 F9D8 F9D8 FF2B 2B2B 2BFF 0000 0000"
$"0000 00FF F5EC ECEC ECEC F5FD FDFD FDFD"
$"FDFD FDFD FDFD FFFF FFFF FFFF FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FD FDFD FDFD"
$"FDFD FDFD FDFD FDFD FDFD FDF5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FD FDFD E3E3"
$"E3E3 E3E3 E3E3 E3E3 FDFD FDF5 FF00 0000"
$"0000 00FF F5EC ECEC ECF5 F5FD FDFD E3F9"
$"E3F9 F9F9 F9F9 F9E3 FDFD FDF5 FF00 0000"
$"0000 00FF F5EC ECEC F5F5 F5FD 00FD E3F9"
$"F9F9 F9E3 F9E3 F9E3 FD00 FDF5 FF00 0000"
$"0000 00FF F5EC ECEC F5F5 F5FD 00FD E3F9"
$"E3F9 F9E3 F9E3 E3F9 FD00 FDF5 FF00 0000"
$"0000 00FF F5EC ECF5 F5F5 F5FD FDFD E3F9"
$"E3F9 F9F9 F9F9 E3F9 FDFD FDF5 FF00 0000"
$"0000 00FF F5EC ECF5 F5F5 F5FD FDFD E3F9"
$"F9F9 E3F9 F9E3 F9E3 FDFD FDF5 FF00 0000"
$"0000 00FF F5EC ECF5 F5F5 F5FD FDFD E3F9"
$"E3E3 F9E3 F9E3 F9E3 FDFD FDF5 FF00 0000"
$"0000 00FF F5EC ECF5 F5F5 F5FD FDFD FDFD"
$"FDFD FDFD FDFD FDFD FDFD FDF5 FF00 0000"
$"0000 00FF F5EC ECF5 F5F5 F5FD 00FD FDFD"
$"FDFD FDFD FDFD FDFD FD00 FDF5 FF00 0000"
$"0000 00FF F5EC ECF5 F5F5 F5FD 00FD 2B2B"
$"2B2B 2B2B 2B2B 2B2B FD00 FDF5 FF00 0000"
$"0000 00FF F5EC ECEC F5F5 F5FD FDFD 2BF9"
$"F92B F9F9 F9F9 F92B FDFD FDF5 FF00 0000"
$"0000 00FF F5EC ECEC F5F5 F5FD FDFD 2BF9"
$"F9F9 2BF9 F9F9 F92B FDFD FDF5 FF00 0000"
$"0000 00FF F5EC ECEC ECF5 F5FD FDFD 2BF9"
$"2BF9 F92B F92B F92B FDFD FDF5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FD FDFD 2BF9"
$"F9F9 F92B F9F9 F92B FDFD FDF5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FD 00FD 2BF9"
$"2B2B 2BF9 F92B F92B FD00 FDF5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FD 00FD 2BF9"
$"F92B 2BF9 F9F9 F92B FD00 FDF5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FD FDFD FDFD"
$"FDFD FDFD FDFD FDFD FDFD FDF5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FD FDFD FDFD"
$"FDFD FDFD FDFD FDFD FDFD FDF5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FD FDFD 0505"
$"0505 FC05 0505 0505 FDFD FDF5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FD FDFD 05FC"
$"FCFC FCFC 0505 FC05 FDFD FDF5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FD F5FD 05FC"
$"05FC 05FC FC05 FCFC FDF5 FDF5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FD F5FD 05FC"
$"05FC 0505 0505 0505 FDF5 FDF5 FF00 0000"
$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF FF"
};
resource 'icl8' (139) {
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000"
$"0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 FDF5 FDD8 D8F9"
$"F9D8 D8D8 F9D8 D8FD F5FD F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 FDF5 FDF9 D8D8"
$"F9F9 D8F9 D8D8 D8FD F5FD F5FF FFFF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FDFD FDFD FDFD"
$"FDFD FDFD FDFD FDFD FDFD F5FF 00FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FDFD FDFD FDFD"
$"FDFD FDFD FDFD FDFD FDFD F5FF 00FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FDFD FDE3 E3E3"
$"E3E3 E3E3 E3E3 E3FD FDFD F5FF 00FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FDFD FDE3 F9E3"
$"F9F9 F9F9 F9F9 E3FD FDFD F5FF 00FF 0000"
$"0000 FFF5 ECEC ECEC F5F5 FD00 FDE3 F9F9"
$"F9F9 E3F9 E3F9 E3FD 00FD F5FF 00FF 0000"
$"0000 FFF5 ECEC ECF5 F5F5 FD00 FDE3 F9E3"
$"F9F9 E3F9 E3E3 F9FD 00FD F5FF 00FF 0000"
$"0000 FFF5 ECEC ECF5 F5F5 FDFD FDE3 F9E3"
$"F9F9 F9F9 F9E3 F9FD FDFD F5FF 00FF 0000"
$"0000 FFF5 ECEC F5F5 F5F5 FDFD FDE3 F9F9"
$"F9E3 F9F9 E3F9 E3FD FDFD F5FF 00FF 0000"
$"0000 FFF5 ECEC F5F5 F5F5 FDFD FDE3 F9E3"
$"E3F9 E3F9 E3F9 E3FD FDFD F5FF 00FF 0000"
$"0000 FFF5 ECEC F5F5 F5F5 FDFD FDFD FDFD"
$"FDFD FDFD FDFD FDFD FDFD F5FF 00FF 0000"
$"0000 FFF5 ECEC F5F5 F5F5 FD00 FDFD FDFD"
$"FDFD FDFD FDFD FDFD 00FD F5FF 00FF 0000"
$"0000 FFF5 ECEC F5F5 F5F5 FD00 FD2B 2B2B"
$"2B2B 2B2B 2B2B 2BFD 00FD F5FF 00FF 0000"
$"0000 FFF5 ECEC F5F5 F5F5 FDFD FD2B F9F9"
$"2BF9 F9F9 F9F9 2BFD FDFD F5FF 00FF 0000"
$"0000 FFF5 ECEC ECF5 F5F5 FDFD FD2B F9F9"
$"F92B F9F9 F9F9 2BFD FDFD F5FF 00FF 0000"
$"0000 FFF5 ECEC ECF5 F5F5 FDFD FD2B F92B"
$"F9F9 2BF9 2BF9 2BFD FDFD F5FF 00FF 0000"
$"0000 FFF5 ECEC ECEC F5F5 FDFD FD2B F9F9"
$"F9F9 2BF9 F9F9 2BFD FDFD F5FF 00FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FD00 FD2B F92B"
$"2B2B F9F9 2BF9 2BFD 00FD F5FF 00FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FD00 FD2B F9F9"
$"2B2B F9F9 F9F9 2BFD 00FD F5FF 00FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FDFD FDFD FDFD"
$"FDFD FDFD FDFD FDFD FDFD F5FF 00FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FDFD FDFD FDFD"
$"FDFD FDFD FFFF FFFF FFFF FFF5 00FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FDFD FD05 0505"
$"05F9 0505 FF2B 2B2B 2BFF F5FD 00FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FDFD FD05 F9F9"
$"F9F9 F905 FF2B 2B2B FFF5 FDFD 00FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FDF5 FD05 F905"
$"F905 F9F9 FF2B 2BFF F5FD FDFD 00FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FDF5 FD05 F905"
$"F905 0505 FF2B FFF5 05FD FDFD 00FF 0000"
$"0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 FFFF F5FC FCFD F5FD 00FF 0000"
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFF5 0505 05FD F5FD 00FF 0000"
$"0000 0000 FF00 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 00FF 0000"
$"0000 0000 FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
};
resource 'icl8' (140) {
$"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 FFFF 0000 0000 0000 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 FF2B FF00 0000 0000 0000"
$"0000 00FF F5EC ECEC ECEC F5F9 F52B F5F5"
$"2B2B F5F5 F5F5 FF2B 2BFF 0000 0000 0000"
$"0000 00FF F5EC ECEC ECEC F52B F52B F5F9"
$"F5F5 F5F5 F5F5 FF2B 2B2B FF00 0000 0000"
$"0000 00FF F5EC ECEC ECEC F52B F52B F5F5"
$"F5E3 E3F5 F5F5 FF2B 2B2B 2BFF 0000 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 F5F5 F52B"
$"2BF5 F5F5 E3E3 FFFF FFFF FFFF FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 F5F5 F5F5"
$"F5F5 F52B 0000 2BE3 E3F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FF FFFF FFFF"
$"FFFF FFFF FFFF FFF5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECF5 F5FF FFFF FFFF"
$"FFFF FFFF FFFF FFFF F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC F5F5 F5FF FFFF FFF5"
$"F5F5 F52B F5F5 FFFF F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC F5F9 F5F5 FFFF FFF9"
$"F5F5 F5F9 F5F5 F52B F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECF5 F5F5 F52B 00FF FFFF"
$"F5F5 F52B F5F5 F5FF F52B F5F5 FF00 0000"
$"0000 00FF F5EC ECF5 0505 0505 0500 FFFF"
$"FFF5 F5F5 2BF9 F52B F52B F5F5 FF00 0000"
$"0000 00FF F5EC ECF5 05F9 F9FF F905 00FF"
$"FFFF F5F5 F5F5 F5F5 F52B F5F5 FF00 0000"
$"0000 00FF F5EC ECF5 05FF F905 E305 0500"
$"FFFF FFF5 F5F5 F52B F5F5 2BF5 FF00 0000"
$"0000 00FF F5EC ECF5 05FF 05F9 F9F9 052B"
$"FFFF FFFF F52B F5F5 F5FF F5F5 FF00 0000"
$"0000 00FF F5EC ECF5 F5F9 0505 F905 052B"
$"00FF FFFF F5F5 F5F5 FFFF F5F5 FF00 0000"
$"0000 00FF F5EC ECEC F5F5 0505 FF05 0500"
$"0000 FFFF F5F5 2BF5 F5FF F5F5 FF00 0000"
$"0000 00FF F5EC ECEC F5F5 0505 0505 0500"
$"00FF FF2B F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECF5 F5F5 F5F5 F52B"
$"FFFF F52B F5F5 2BF5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5F9 F9F5 F5FF"
$"FFF5 F5F5 F5F5 2BF5 F5F5 2BF5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5F5 F52B FFFF"
$"F5F5 F5F5 F5F5 F5F5 FFF5 2BF5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F52B F5FF FF2B"
$"F5F5 F5F5 F5F5 F5F5 FFF5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F52B FFFF F5F5"
$"F52B F5F5 2BF5 2BFF FFF5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FF FFFF FFFF"
$"FFFF FFFF FFFF FFFF F9F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5FF FFFF FFFF"
$"FFFF FFFF FFFF FFFF 2BF5 2BF5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F52B 2BF5 F52B"
$"F5F5 2BF5 F52B 2BF5 F5F5 F5F5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5D8 D8F9 F5F5"
$"F5F5 F5F5 F5F5 F5F9 F9F5 2BF5 FF00 0000"
$"0000 00FF F5EC ECEC ECEC F5D8 D8F9 F52B"
$"F9F5 F52B F5F5 F5F9 2B2B F5F5 FF00 0000"
$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F52B F5F5 F5F5 F5F5 F5F5 FF00 0000"
$"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF FF"
};
resource 'icl8' (141) {
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF 0000 0000"
$"0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 2BF5 2BF5 F9F5"
$"F52B F5F5 F52B F5F5 F5F5 F5FF 0000 0000"
$"0000 FFF5 ECEC ECEC ECF5 2BF5 2BF5 F5F5"
$"E3E3 F5F5 F52B 2BF5 F52B F5FF FFFF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 2B2B"
$"F5F5 F5E3 E3F5 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F5F5 F5F5"
$"F5F5 2B00 002B E3E3 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FFFF FFFF FFFF"
$"FFFF FFFF FFFF F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFF5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC F5F5 FFFF FFFF F5F5"
$"F5F5 2BF5 F5FF FFF5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECF5 2BF5 F5FF FFFF F9F5"
$"F5F5 F9F5 F5F5 2BF5 2BF5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECF5 2BF5 2BF5 FFFF FFF5"
$"F5F5 2BF5 F5F5 FFF5 2BF5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5F5 F5F5 F5F5 F5FF FFFF"
$"F5F5 F52B F9F5 2BF5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F505 0505 0505 F5FF FFFF"
$"FFF5 F5F5 F5F5 F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F505 F9F9 FFF9 0500 00FF"
$"FFFF F5F5 F5F5 2BF5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F505 FFF9 0505 0505 2BFF"
$"FFFF FFF5 2BF5 F5F5 2BF5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F505 FF05 F9F9 F905 2B00"
$"FFFF FFF5 F5F5 F5FF 2BF5 F5FF F5FF 0000"
$"0000 FFF5 ECEC F5F5 F905 05F9 0505 0000"
$"00FF FFF5 F52B F5F5 F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECF5 F505 05FF 0505 0000"
$"FFFF 2BF5 F5F5 F5F5 F52B F5FF F5FF 0000"
$"0000 FFF5 ECEC ECF5 F5F5 F5F5 F5F5 2BFF"
$"FFF5 2BF5 F52B F5F5 F52B F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC F5F5 F5F5 F5F5 FFFF"
$"F5F5 F5F5 F52B F5F5 F52B F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 2BFF FFF5"
$"F5F5 2BF5 F5F5 F5FF F52B F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 2BF5 FFFF 2BF5"
$"F5F5 F5F5 F5F5 F5FF F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 2BFF FFF5 F5F5"
$"2BF5 F52B F52B FFFF F5F5 F5FF F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFF5 F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 FFFF FFFF FFFF"
$"FFFF FFFF FF2B 2B2B 2BFF F5F5 F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 F5F5 F500 F5F5"
$"F5F5 F5F5 FF2B 2B2B FFF5 F5F5 F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 D8D8 F52B 2BF5"
$"F52B F5F5 FF2B 2BFF F5F5 F5F5 F5FF 0000"
$"0000 FFF5 ECEC ECEC ECF5 D8D8 2BF5 2BF5"
$"F5F5 F5F5 FF2B FFF5 F5F5 F5F5 F5FF 0000"
$"0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 FFFF F5F5 F5F5 F5F5 F5FF 0000"
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFF5 F5F5 F5F5 F5F5 F5FF 0000"
$"0000 0000 FFF5 F5F5 F5F5 F5F5 F5F5 F5F5"
$"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000"
$"0000 0000 FFFF FFFF FFFF FFFF FFFF FFFF"
$"FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
};
resource 'icl8' (142) {
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"F0EF F0EF F000 0000 0000 0000 0000 0000"
$"FA00 0000 0000 0000 0000 0000 0000 0000"
$"F0EF F0EF F000 0000 0000 0000 0000 00FA"
$"D2FA 0000 0000 0000 0000 0000 0000 0000"
$"EFF0 EFF0 EF00 0000 0000 0000 0000 FA00"
$"F9D2 FA00 0000 0000 0000 0000 0000 0000"
$"F0EF F0EF F000 0000 0000 0000 00FA 0000"
$"00FA D2FA 0000 0000 0000 0000 0000 0000"
$"EFF0 EFF0 EF00 0000 0000 0000 FAFF 0000"
$"FA00 57D2 FA00 0000 0000 0000 0000 0000"
$"EFF0 EFF0 EF00 0000 0000 00FA FF00 F7F9"
$"00FF 00F9 D2FA 0000 0000 0000 0000 0000"
$"F0EF F0EF F000 0000 0000 FA00 00FA F900"
$"FA00 00FA F9D2 FA00 0000 0000 0000 0000"
$"EFF0 EFF0 EF00 0000 007B FF00 00F9 0000"
$"00F9 00FF 00FA D2FA 0000 0000 0000 0000"
$"F0EF F0EF F000 0000 FA00 002B FA00 0000"
$"0000 FA00 0000 F9D2 FA00 0000 0000 0000"
$"EFF0 EFF0 EF00 00F9 0000 00FA 0000 0000"
$"0000 00F9 0000 00FA D2FA 0000 0000 0000"
$"F0EF F0EF F000 F9FF 0000 FA00 0000 0000"
$"0000 0000 FA00 FFF9 F9D2 FA00 0000 0000"
$"EFF0 EFF0 EFF9 0000 F7F9 0000 0000 0000"
$"0000 0000 00F9 00FF 00F9 D2FA 0000 0000"
$"F0EF EFF0 F9FF 0000 F900 0000 0000 F9FA"
$"00F9 FAF9 FA00 FA00 00FA F9D2 FA00 0000"
$"EFF0 F0F9 0000 00FA 0000 0000 FAF9 00F9"
$"FA00 F9FA FFF9 F9FA 00FF 00FA D2FA 0000"
$"EFF0 F9FF 0000 FA00 0000 00F9 00FA 00C9"
$"00D2 00D2 C2EF F0F0 F900 0000 F9D2 7B00"
$"F0F9 0000 00FA 0000 00FA 00D2 0000 C200"
$"05E6 E5E6 D2E5 EFEF F0F9 0000 00FA D2FA"
$"EFEF FA00 FA00 0000 F9D2 0000 D2F9 E6E6"
$"05E5 E6E5 E5E6 E6E5 EFF0 FA00 0000 F900"
$"F0EF EFF9 0000 00FA FA00 C300 FAE6 E505"
$"0505 E5D2 D2E5 E5F9 E6E5 EFF9 00FA 8C00"
$"F0EF F0F0 FA00 F900 00D2 00F9 E505 0505"
$"0505 0505 E5D2 E6E6 E5EF F0FF F98C 0000"
$"EFF0 EFEF F0F9 FA00 F9D2 FAD2 C8E5 E505"
$"0505 E6E5 E6E5 E6EF E6E5 E6FF FF00 0000"
$"EFF0 EFF0 EFFA 0000 D2FA 00C2 E5E5 E6E6"
$"05E6 D2E6 E5E6 E5E5 E5E6 FFE5 F000 0000"
$"F0EF F0EF F0F9 FAF9 0000 E6E6 E5E6 E5E5"
$"05E5 E6D2 E6E5 E6EF E5EF E5FF F0FF 0000"
$"EFF0 EFF0 F900 00FA D2C2 C9C2 E6E5 D2E5"
$"E6D2 D2D2 E5E5 E6E5 E6E5 FFEF E5FF 0000"
$"F0EF F0EF 00FA 00D2 F9EB D2C9 E5D2 D2E6"
$"D2D2 D2E5 E6E6 E5E6 EFE6 E5E6 EFFF 0000"
$"EFF0 EFEF FAF9 D200 D2D2 D2D2 D2D2 D2D2"
$"E5E6 E5E6 E5E5 E6E5 E6E5 F0EF F0FF 0000"
$"F0EF F0F0 00D2 00D2 D2D2 D2E5 E5E6 E5E6"
$"D2E5 D2E5 E6E5 E5E6 EFE5 EFE5 EFFF 0000"
$"EFF0 EFF0 F900 D2D2 D2D2 E5E5 E6E5 E6E5"
$"E5D2 E5E6 E5E6 E5E6 E5EF E5FF EFFF 0000"
$"EFEF F0EF 00D2 00D2 D2E5 E6E6 E5E6 E5E6"
$"E6D2 D2E5 E6E5 E6E5 EFF0 FFE5 FFFF 0000"
$"F0F0 EFF0 FAF9 D2D2 D2E6 E5E5 E6E5 E6E5"
$"E5D2 D2E5 E6E5 E6E5 F0E6 E5EF FFFF 0000"
$"EFEF F0EF F000 F0D2 D2D2 E6E5 E6E5 E6E5"
$"E6D2 D2D2 E5E6 EFE6 EFF0 EFFF FF00 0000"
$"F0F0 EFF0 EFFA C2F0 EFD2 D2D2 E5E6 E5E6"
$"D2D2 F0D2 D2EF F0EF F0EF FFFF FF"
};
resource 'icl4' (128) {
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"6666 6000 0000 0000 D000 0000 0000 0000"
$"6666 6000 0000 000D 6D00 0000 0000 0000"
$"6666 6000 0000 00D0 D6D0 0000 0000 0000"
$"6666 6000 0000 0D00 0D6D 0000 0000 0000"
$"6666 6000 0000 DF00 D0D6 D000 0000 0000"
$"6666 6000 000D F0CD 0F0D 6D00 0000 0000"
$"6666 6000 00D0 0DD0 D00D D6D0 0000 0000"
$"6666 6000 0DF0 0D00 0D0F 0D6D 0000 0000"
$"6666 6000 D00C D000 00D0 00D6 D000 0000"
$"6666 600D 000D 0000 000D 000D 6D00 0000"
$"6666 60DF 00D0 0000 0000 D0FD D6D0 0000"
$"6666 6D00 CD00 0000 0000 0D0F 0D6D 0000"
$"6666 DF00 D000 00DD 0DDD D0D0 0DD6 D000"
$"666D 000D 0000 DD0D D0DD FDDD 0F0D 6D00"
$"66DF 00D0 000D 0D09 0606 7666 D000 D6D0"
$"6D00 0D00 0D06 0070 1999 6966 6D00 0D6D"
$"66D0 D000 D600 6D99 1999 9999 66D0 00D0"
$"666D 000D D080 D991 1196 699D 996D 0D50"
$"6666 D0D0 060D 9111 1111 9699 966F D500"
$"6666 6DD0 D6D6 9991 1199 9996 999F F000"
$"6666 6D00 6D07 9999 1969 9999 99F9 6000"
$"6666 6DDD 0099 9999 1996 9996 969F 6F00"
$"6666 D00D 6797 9969 9666 9999 99F6 9F00"
$"6666 0D06 D669 9669 6669 9999 6999 6F00"
$"6666 DD60 6666 6666 9999 9999 9966 6F00"
$"6666 0606 6669 9999 6969 9999 6969 6F00"
$"6666 D066 6699 9999 9699 9999 969F 6F00"
$"6666 0606 6999 9999 9669 9999 66F9 FF00"
$"6666 DD66 6999 9999 9669 9999 6996 FF00"
$"6666 6066 6699 9999 9666 9969 666F F000"
$"6666 6D76 6666 9999 6666 6666 66FF F0"
};
resource 'icl4' (129) {
$"000F FFFF FFFF FFFF FFFF FFF0 0000 0000"
$"000F 0000 0000 0000 0000 00FF 0000 0000"
$"000F 0666 6600 0000 0000 00FC F000 0000"
$"000F 0666 6600 0000 0000 00FC CF00 0000"
$"000F 0666 6600 0000 0000 00FC CCF0 0000"
$"000F 0666 6600 FF0F 0FFF FFFC CCCF 0000"
$"000F 0666 6600 0000 0000 00FF FFFF F000"
$"000F 0666 660F FFF0 0FFF 0FF0 F000 F000"
$"000F 0666 6600 0000 0000 0000 0000 F000"
$"000F 0666 60F0 FF0F 0FF0 F0FF 0F00 F000"
$"000F 0666 0000 0000 0000 0000 0000 F000"
$"000F 0666 0F0F FF0F FF0F 0FFF 0F00 F000"
$"000F 0660 0000 0000 0000 0000 0000 F000"
$"000F 0660 FF0F 0FFF 0FF0 FF0F FF00 F000"
$"000F 0660 0000 0000 0000 0000 0000 F000"
$"000F 0660 F0FF FFF0 FFFF 0FF0 FF00 F000"
$"000F 0660 0000 0000 0000 0000 0000 F000"
$"000F 0660 FF0F FF0F F0FF F0FF 0000 F000"
$"000F 0666 0000 0000 0000 0000 0000 F000"
$"000F 0666 0FFF 0FF0 F0F0 F0F0 FF00 F000"
$"000F 0666 6000 0000 0000 0000 0000 F000"
$"000F 0666 660F F0FF F0FF FF0F 0F00 F000"
$"000F 0666 6600 0000 0000 0000 0000 F000"
$"000F 0666 660F 0FF0 FFFF 0FF0 FF00 F000"
$"000F 0666 6600 0000 0000 0000 0000 F000"
$"000F 0666 660F FF00 FFF0 FFF0 0F00 F000"
$"000F 0666 6600 0000 0000 0000 0000 F000"
$"000F 0666 660F FF0F 0FFF 00FF 0F00 F000"
$"000F 0666 6600 0000 0000 0000 0000 F000"
$"000F 0666 6600 0000 0000 0000 0000 F000"
$"000F 0000 0000 0000 0000 0000 0000 F000"
$"000F FFFF FFFF FFFF FFFF FFFF FFFF F0"
};
resource 'icl4' (130) {
$"00FF FFFF FFFF FFFF FFFF FFFF FFFF 0000"
$"00F0 0000 0000 0000 0000 0000 000F 0000"
$"00F0 6666 6000 0000 0000 0000 000F 0000"
$"00F0 6666 6000 0000 0000 0000 000F FF00"
$"00F0 6666 6000 0000 0000 0000 000F 0F00"
$"00F0 6666 6F0F F0FF FF0F FF0F 000F 0F00"
$"00F0 6666 6000 0000 0000 0000 000F 0F00"
$"00F0 6666 600F FF0F 0FF0 FF0F 000F 0F00"
$"00F0 6666 0000 0000 0000 0000 000F 0F00"
$"00F0 6660 F0FF 0F0F FF0F 0FF0 F00F 0F00"
$"00F0 6660 0000 0000 0000 0000 000F 0F00"
$"00F0 660F F0FF FF0F FFF0 FFF0 000F 0F00"
$"00F0 6600 0000 0000 0000 0000 000F 0F00"
$"00F0 6600 F0FF 0FFF F00F F0FF F00F 0F00"
$"00F0 6600 0000 0000 0000 0000 000F 0F00"
$"00F0 660F FF0F FF00 FF0F FF0F F00F 0F00"
$"00F0 6600 0000 0000 0000 0000 000F 0F00"
$"00F0 6660 FF0F FFFF 00FF 0FF0 000F 0F00"
$"00F0 6660 0000 0000 0000 0000 000F 0F00"
$"00F0 6666 0FF0 FFF0 FFFF 0F0F F00F 0F00"
$"00F0 6666 6000 0000 0000 0000 000F 0F00"
$"00F0 6666 6FF0 0FFF 0FFF F0F0 F00F 0F00"
$"00F0 6666 6000 0000 0000 0000 000F 0F00"
$"00F0 6666 6F0F FFF0 0FF0 FFFF FFF0 0F00"
$"00F0 6666 6000 0000 0000 FCCC CF00 0F00"
$"00F0 6666 6F00 FF0F F0F0 FCCC F0F0 0F00"
$"00F0 6666 6000 0000 0000 FCCF 0000 0F00"
$"00F0 6666 60FF 0FFF 0FF0 FCF0 F0F0 0F00"
$"00F0 0000 0000 0000 0000 FF00 0000 0F00"
$"00FF FFFF FFFF FFFF FFFF F000 0000 0F00"
$"0000 F000 0000 0000 0000 0000 0000 0F00"
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FF"
};
resource 'icl4' (131) {
$"00FF FFFF FFFF FFFF FFFF FF00 0000 0000"
$"00F0 0000 0000 0000 0000 0FF0 0000 0000"
$"00F0 6666 6000 0000 0000 0FCF 0000 0000"
$"00F0 6666 6000 0000 0000 0FCC F000 0000"
$"00F0 6666 6000 0000 0000 0FCC CF00 0000"
$"00F0 6666 6000 0000 0000 0FCC CCF0 0000"
$"00F0 6666 6000 0000 0000 0FFF FFFF 0000"
$"00F0 6666 6000 0000 0000 0000 000F 0000"
$"00F0 6666 6000 0000 0000 0000 000F 0000"
$"00F0 6666 0000 0000 0000 0000 000F 0000"
$"00F0 6660 0000 0000 0000 0000 000F 0000"
$"00F0 666F FF0F FF0F FF0F F0FF 000F 0000"
$"00F0 6600 0000 0000 0000 0000 000F 0000"
$"00F0 6600 0000 0000 0000 0000 000F 0000"
$"00F0 660F FF0F FFF0 FFFF 0FFF 000F 0000"
$"00F0 6600 0000 0000 0000 0000 000F 0000"
$"00F0 6600 0000 0000 0000 0000 000F 0000"
$"00F0 660F F0FF FFFF F0FF F0FF 000F 0000"
$"00F0 6660 0000 0000 0000 0000 000F 0000"
$"00F0 6660 0000 0000 0000 0000 000F 0000"
$"00F0 6666 0000 0000 0000 0000 000F 0000"
$"00F0 6666 6000 0000 0000 0000 000F 0000"
$"00F0 6666 6000 0000 0000 0000 000F 0000"
$"00F0 6666 6000 0000 0000 0000 000F 0000"
$"00F0 6666 6000 0000 0000 0000 000F 0000"
$"00F0 6666 6000 0000 0000 0000 000F 0000"
$"00F0 6666 6000 0000 0000 0000 000F 0000"
$"00F0 6666 6000 0000 0000 0000 000F 0000"
$"00F0 6666 6000 0000 0000 0000 000F 0000"
$"00F0 6666 6000 0000 0000 0000 000F 0000"
$"00F0 0000 0000 0000 0000 0000 000F 0000"
$"00FF FFFF FFFF FFFF FFFF FFFF FFFF"
};
resource 'icl4' (132) {
$"000F FFFF FFFF FFFF FFFF FFF0 0000 0000"
$"000F 0000 0000 0000 0000 00FF 0000 0000"
$"000F 0666 66FF 070F FFF0 70FC F000 0000"
$"000F 0666 6600 0700 0000 70FC CF00 0000"
$"000F 0666 6677 70FF FFFF 0FFC CCF0 0000"
$"000F 0666 6600 0F00 0000 F0FC CCCF 0000"
$"000F 0666 6600 0F00 0000 F0FF FFFF F000"
$"000F 0666 6600 0F00 0000 F000 0000 F000"
$"000F 0666 6677 70FF FFFF 0FFF FFFF F000"
$"000F 0666 6000 0F00 0000 F000 0000 F000"
$"000F 0666 00FF 0F00 0000 F000 0000 F000"
$"000F 0666 0000 0F00 0000 F000 0000 F000"
$"000F 0660 7777 70FF FFFF 0FFF FFFF F000"
$"000F 0660 0000 0F00 0000 F000 0000 F000"
$"000F 0660 0FFF 0F00 0000 F000 0000 F000"
$"000F 0660 0000 0F00 0000 F000 0000 F000"
$"000F 0660 7777 70FF FFFF 0FFF FFFF F000"
$"000F 0660 0000 0F00 0000 F000 0000 F000"
$"000F 0666 00FF 0F00 0000 F000 0000 F000"
$"000F 0666 0000 0F00 0000 F000 0000 F000"
$"000F 0666 6777 70FF FFFF 0FFF FFFF F000"
$"000F 0666 6600 0F00 0000 F000 0000 F000"
$"000F 0666 660F 0F00 0000 F000 0000 F000"
$"000F 0666 6600 0F00 0000 F000 0000 F000"
$"000F 0666 6677 70FF FFFF 0FFF FFFF F000"
$"000F 0666 6600 0F00 0000 F000 0000 F000"
$"000F 0666 660F 0F00 0000 F000 0000 F000"
$"000F 0666 6600 0F00 0000 F000 0000 F000"
$"000F 0666 6677 70FF FFFF 0FFF FFFF F000"
$"000F 0666 6600 0F00 0000 F000 0000 F000"
$"000F 0000 0000 0000 0000 0000 0000 F000"
$"000F FFFF FFFF FFFF FFFF FFFF FFFF F0"
};
resource 'icl4' (133) {
$"00FF FFFF FFFF FFFF FFFF FFFF FFFF 0000"
$"00F0 0000 0000 0000 0000 0000 000F 0000"
$"00F0 6666 6000 070F FFF0 70FF FF0F 0000"
$"00F0 6666 6000 0700 0000 7000 000F FF00"
$"00F0 6666 6777 70FF FFFF 0FFF FFFF 0F00"
$"00F0 6666 6000 0F00 0000 F000 000F 0F00"
$"00F0 6666 600F 0F00 0000 F000 000F 0F00"
$"00F0 6666 6000 0F00 0000 F000 000F FF00"
$"00F0 6666 7777 70FF FFFF 0FFF FFFF 0F00"
$"00F0 6660 0000 0F00 0000 F000 000F 0F00"
$"00F0 6660 0FFF 0F00 0000 F000 000F 0F00"
$"00F0 6600 0000 0F00 0000 F000 000F FF00"
$"00F0 6607 7777 70FF FFFF 0FFF FFFF 0F00"
$"00F0 6600 0000 0F00 0000 F000 000F 0F00"
$"00F0 6600 FFFF 0F00 0000 F000 000F 0F00"
$"00F0 6600 0000 0F00 0000 F000 000F FF00"
$"00F0 6607 7777 70FF FFFF 0FFF FFFF 0F00"
$"00F0 6660 0000 0F00 0000 F000 000F 0F00"
$"00F0 6660 0FFF 0F00 0000 F000 000F 0F00"
$"00F0 6666 0000 0F00 0000 F000 000F FF00"
$"00F0 6666 6777 70FF FFFF 0FFF FFFF 0F00"
$"00F0 6666 6000 0F00 0000 F000 000F 0F00"
$"00F0 6666 600F 0F00 0000 F000 000F 0F00"
$"00F0 6666 6000 0F00 0000 FFFF FFF0 FF00"
$"00F0 6666 6777 70FF FFFF F000 0F00 0F00"
$"00F0 6666 6000 0F00 0000 F000 F000 0F00"
$"00F0 6666 600F 0F00 0000 F00F 0000 0F00"
$"00F0 6666 6000 0F00 0000 F0F0 FFFF FF00"
$"00F0 0000 0000 0000 0000 FF00 0000 0F00"
$"00FF FFFF FFFF FFFF FFFF F0F0 0000 0F00"
$"0000 F000 0000 0000 0000 0000 0000 0F00"
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FF"
};
resource 'icl4' (134) {
$"00FF FFFF FFFF FFFF FFFF FF00 0000 0000"
$"00F0 0000 0000 0000 0000 0FF0 0000 0000"
$"00F0 6666 6FFF FFFF FFFF FF0F 0000 0000"
$"00F0 6666 6FCC CCCC CCCC CF00 F000 0000"
$"00F0 6666 6FCD DDDD DDDD DF00 0F00 0000"
$"00F0 6666 6FCD FFFF FFFF FF00 00F0 0000"
$"00F0 6666 6FCD F001 6000 0FFF FFFF 0000"
$"00F0 6666 6FCD F011 6600 0000 000F 0000"
$"00F0 6666 6FCD F111 6660 0FFF F00F 0000"
$"00F0 6666 0FCD F333 8880 0000 00FF 0000"
$"00F0 6660 0FCD F033 8800 FFF0 FF0F 0000"
$"00F0 6660 0FCD F003 8000 000F 000F 0000"
$"00F0 6600 0FCD F000 0000 00F0 000F 0000"
$"00F0 6600 0FCD F0FF 0FF0 FF00 000F 0000"
$"00F0 6600 0FCD F0FF 000F 0000 000F 0000"
$"00F0 6600 0FCD F0FF 0FF0 0000 000F 0000"
$"00F0 6600 0FCD F000 F000 0FFF F00F 0000"
$"00F0 6600 0FCD F0FF 0000 F0C0 CF0F 0000"
$"00F0 6660 0FCD 0F00 000F 0C0C 0CFF 0000"
$"00F0 6660 0F00 F0FF FFFF F0C0 C0FF 0000"
$"00F0 6666 00FF 00FD DDDD FC0C 0CFF 0000"
$"00F0 6666 6F00 00FD DDDD F0C0 C0FF 0000"
$"00F0 6666 6000 00FD DDDD FC0C 0F0F 0000"
$"00F0 6666 6000 00FD DDDD FFFF F00F 0000"
$"00F0 6666 6000 00FD DDDF CF00 000F 0000"
$"00F0 6666 6000 00FF FFFC DCF0 000F 0000"
$"00F0 6666 6000 0000 0FCD CDCF 000F 0000"
$"00F0 6666 6000 0000 FCDC DCDC F00F 0000"
$"00F0 6666 6000 000F FFFF FFFF FF0F 0000"
$"00F0 6666 6000 0000 0000 0000 000F 0000"
$"00F0 0000 0000 0000 0000 0000 000F 0000"
$"00FF FFFF FFFF FFFF FFFF FFFF FFFF"
};
resource 'icl4' (135) {
$"00FF FFFF FFFF FFFF FFFF FFFF FFFF 0000"
$"00F0 0000 0000 0000 0000 0000 000F 0000"
$"00F0 6666 6FFF FFFF FFFF FFFF FF0F 0000"
$"00F0 6666 6FCC CCCC CCCC CCCC CC0F FF00"
$"00F0 6666 6FCC CCCC CCCC CCCC CC0F 0F00"
$"00F0 6666 6FCF FFFF FFFF FFFF FF0F 0F00"
$"00F0 6666 6FCF 0016 0000 0000 000F 0F00"
$"00F0 6666 6FCF 0116 6000 0000 000F 0F00"
$"00F0 6666 0FCF 1116 6600 FFFF 00FF 0F00"
$"00F0 6660 0FCF 3338 8800 0000 0F0F 0F00"
$"00F0 6660 0FCF 0338 800F FF0F F00F 0F00"
$"00F0 6600 0FCF 0038 0000 00F0 000F 0F00"
$"00F0 6600 0FCF 0000 0000 0F00 000F 0F00"
$"00F0 6600 0FCF 0FF0 FF0F F000 000F 0F00"
$"00F0 6600 0FCF 0FF0 00F0 0000 000F 0F00"
$"00F0 6600 0FCF 0FF0 FF00 0000 000F 0F00"
$"00F0 6600 0FCF 000F 0000 FFFF 000F 0F00"
$"00F0 6660 0FCF 0FF0 000F 0C0C F00F 0F00"
$"00F0 6660 0FC0 F000 00F0 C0C0 CF0F 0F00"
$"00F0 6666 000F 0FFF FFFF 0C0C 0F0F 0F00"
$"00F0 6666 6FF0 0FDD DDDF C0C0 CF0F 0F00"
$"00F0 6666 6000 0FDD DDDF 0C0C 0F0F 0F00"
$"00F0 6666 6000 0FDD DDDF C0C0 F00F 0F00"
$"00F0 6666 6000 0FDD DDDF FFFF FFFF 0F00"
$"00F0 6666 6000 0FDD DDFC F000 00F0 0F00"
$"00F0 6666 6000 0FFF FFCD F000 0F00 0F00"
$"00F0 6666 6000 0000 FCDC F000 F000 0F00"
$"00F0 6666 6000 000F FFFF F00F 0000 0F00"
$"00F0 0000 0000 0000 0000 F0F0 0000 0F00"
$"00FF FFFF FFFF FFFF FFFF FF00 0000 0F00"
$"0000 F000 0000 0000 0000 0000 0000 0F00"
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FF"
};
resource 'icl4' (136) {
$"000F FFFF FFFF FFFF FFFF FFF0 0000 0000"
$"000F 0000 0000 0000 0000 00FF 0000 0000"
$"000F 0666 6600 F000 0000 00FC F000 0000"
$"000F 0666 660F F000 0000 00FC CF00 0000"
$"000F 0666 6600 F000 0000 00FC CCF0 0000"
$"000F 0666 6600 F000 0000 00FC CCCF 0000"
$"000F 0666 660F FF00 000F FFFF FFFF F000"
$"000F 0666 6600 F000 0FF1 1F6F F000 F000"
$"000F 0666 6600 F000 F111 1F66 6F00 F000"
$"000F 0666 600F F000 F111 1F66 6F00 F000"
$"000F 0666 0000 F00F 1111 1F66 66F0 F000"
$"000F 0666 0000 F00F 1111 1F66 66F0 F000"
$"000F 0660 000F FF0F 1111 FFFF FFF0 F000"
$"000F 0660 0000 F00F 111F 3C3C 3CF0 F000"
$"000F 0660 0000 F000 F1F3 C3C3 CF00 F000"
$"000F 0660 000F F000 FF3C 3C3C 3F07 F000"
$"000F 0660 0000 F000 0FF3 C3CF F070 F000"
$"000F 0660 0000 F000 000F FFF0 0070 F000"
$"000F 0666 000F FF00 0000 0000 0700 F000"
$"000F 0666 0000 F000 0770 0000 0700 F000"
$"000F 0666 6000 F000 0770 0000 7000 F000"
$"000F 0666 660F F000 7007 0000 7000 F000"
$"000F 0666 6600 F000 7000 7007 0000 F000"
$"000F 0666 6600 F007 0000 0777 0000 F000"
$"000F 0666 660F F077 0000 0077 0000 F000"
$"000F 0666 6600 F077 0000 0000 0000 F000"
$"000F 0666 6600 F000 0000 0F00 0000 F000"
$"000F 0666 6600 FFFF FFFF FFFF FFF0 F000"
$"000F 0666 6600 000F 00F0 0F00 F000 F000"
$"000F 0666 6600 0000 0000 0000 0000 F000"
$"000F 0000 0000 0000 0000 0000 0000 F000"
$"000F FFFF FFFF FFFF FFFF FFFF FFFF F0"
};
resource 'icl4' (137) {
$"00FF FFFF FFFF FFFF FFFF FFFF FFFF 0000"
$"00F0 0000 0000 0000 0000 0000 000F 0000"
$"00F0 6666 6000 0000 0000 0000 000F 0000"
$"00F0 6666 6FFF 0000 0FFF F000 000F FF00"
$"00F0 6666 60F0 000F F11F 6FF0 000F 0F00"
$"00F0 6666 60F0 00F1 111F 666F 000F 0F00"
$"00F0 6666 6FF0 00F1 111F 666F 000F 0F00"
$"00F0 6666 60F0 0F11 111F 6666 F00F 0F00"
$"00F0 6666 00F0 0F11 111F 6666 F00F 0F00"
$"00F0 6660 0FFF 0F11 11FF FFFF F00F 0F00"
$"00F0 6660 00F0 0F11 1F3C 3C3C F00F 0F00"
$"00F0 6600 00F0 00F1 F3C3 C3CF 000F 0F00"
$"00F0 6600 0FF0 00FF 3C3C 3C3F 070F 0F00"
$"00F0 6600 00F0 000F F3C3 CFF0 700F 0F00"
$"00F0 6600 00F0 0000 0FFF F000 700F 0F00"
$"00F0 6600 0FFF 0000 0000 0007 000F 0F00"
$"00F0 6600 00F0 0007 7000 0007 000F 0F00"
$"00F0 6660 00F0 0007 7000 0070 000F 0F00"
$"00F0 6660 0FF0 0070 0700 0070 000F 0F00"
$"00F0 6666 00F0 0070 0070 0700 000F 0F00"
$"00F0 6666 60F0 0700 0007 7700 000F 0F00"
$"00F0 6666 6FF0 7700 0000 7700 000F 0F00"
$"00F0 6666 60F0 7700 0000 0000 000F 0F00"
$"00F0 6666 60F0 0000 0000 FFFF FFF0 0F00"
$"00F0 6666 60FF FFFF FFFF FCCC CF00 0F00"
$"00F0 6666 6000 0F00 F00F FCCC F000 0F00"
$"00F0 6666 6000 0000 0000 FCCF 0000 0F00"
$"00F0 6666 6000 0000 0000 FCF0 0000 0F00"
$"00F0 0000 0000 0000 0000 FF00 0000 0F00"
$"00FF FFFF FFFF FFFF FFFF F000 0000 0F00"
$"0000 F000 0000 0000 0000 0000 0000 0F00"
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FF"
};
resource 'icl4' (138) {
$"000F FFFF FFFF FFFF FFFF FFF0 0000 0000"
$"000F 0000 0000 0000 0000 00FF 0000 0000"
$"000F 0666 660E FE33 3333 33FC F000 0000"
$"000F 0666 660F EF3D D3DD 33FC CF00 0000"
$"000F 0666 660E 0E33 DD33 3DFC CCF0 0000"
$"000F 0666 660F 0FD3 3DD3 D3FC CCCF 0000"
$"000F 0666 660E FEFE FEFE FEFF FFFF F000"
$"000F 0666 660F EFEF EFEF EFEF EFE0 F000"
$"000F 0666 660E FE88 8888 8888 FEF0 F000"
$"000F 0666 600F EF8D 8DDD DDD8 EFE0 F000"
$"000F 0666 000E 0E8D DDD8 D8D8 F0F0 F000"
$"000F 0666 000F 0F8D 8DD8 D88D E0E0 F000"
$"000F 0660 000E FE8D 8DDD DD8D FEF0 F000"
$"000F 0660 000F EF8D DD8D D8D8 EFE0 F000"
$"000F 0660 000E FE8D 88D8 D8D8 FEF0 F000"
$"000F 0660 000F EFEF EFEF EFEF EFE0 F000"
$"000F 0660 000E 0EFE FEFE FEFE F0F0 F000"
$"000F 0660 000F 0FCC CCCC CCCC E0E0 F000"
$"000F 0666 000E FECD DCDD DDDC FEF0 F000"
$"000F 0666 000F EFCD DDCD DDDC EFE0 F000"
$"000F 0666 600E FECD CDDC DCDC FEF0 F000"
$"000F 0666 660F EFCD DDDC DDDC EFE0 F000"
$"000F 0666 660E 0ECD CCCD DCDC F0F0 F000"
$"000F 0666 660F 0FCD DCCD DDDC E0E0 F000"
$"000F 0666 660E FEFE FEFE FEFE FEF0 F000"
$"000F 0666 660F EFEF EFEF EFEF EFE0 F000"
$"000F 0666 660E FE11 11F1 1111 FEF0 F000"
$"000F 0666 660F EF1F EFEF 11E1 EFE0 F000"
$"000F 0666 660E 0E1E 1E1E F1FE F0F0 F000"
$"000F 0666 660F 0F1F 1F11 1111 E0E0 F000"
$"000F 0000 0000 0000 0000 0000 0000 F000"
$"000F FFFF FFFF FFFF FFFF FFFF FFFF F0"
};
resource 'icl4' (139) {
$"00FF FFFF FFFF FFFF FFFF FFFF FFFF 0000"
$"00F0 0000 0000 0000 0000 0000 000F 0000"
$"00F0 6666 60F0 F33D D333 D33E 0E0F 0000"
$"00F0 6666 60E0 ED33 DD3D 333F 0F0F FF00"
$"00F0 6666 60FE FEFE FEFE FEFE FE0F 0F00"
$"00F0 6666 60EF EFEF EFEF EFEF EF0F 0F00"
$"00F0 6666 60FE F888 8888 888E FE0F 0F00"
$"00F0 6666 60EF E8D8 DDDD DD8F EF0F 0F00"
$"00F0 6666 00F0 F8DD DD8D 8D8E 0E0F 0F00"
$"00F0 6660 00E0 E8D8 DD8D 88DF 0F0F 0F00"
$"00F0 6660 00FE F8D8 DDDD D8DE FE0F 0F00"
$"00F0 6600 00EF E8DD D8DD 8D8F EF0F 0F00"
$"00F0 6600 00FE F8D8 8D8D 8D8E FE0F 0F00"
$"00F0 6600 00EF EFEF EFEF EFEF EF0F 0F00"
$"00F0 6600 00F0 FEFE FEFE FEFE 0E0F 0F00"
$"00F0 6600 00E0 ECCC CCCC CCCF 0F0F 0F00"
$"00F0 6600 00FE FCDD CDDD DDCE FE0F 0F00"
$"00F0 6660 00EF ECDD DCDD DDCF EF0F 0F00"
$"00F0 6660 00FE FCDC DDCD CDCE FE0F 0F00"
$"00F0 6666 00EF ECDD DDCD DDCF EF0F 0F00"
$"00F0 6666 60F0 FCDC CCDD CDCE 0E0F 0F00"
$"00F0 6666 60E0 ECDD CCDD DDCF 0F0F 0F00"
$"00F0 6666 60FE FEFE FEFE FEFE FE0F 0F00"
$"00F0 6666 60EF EFEF EFEF FFFF FFF0 0F00"
$"00F0 6666 60FE F111 1D11 FCCC CF0E 0F00"
$"00F0 6666 60EF E1DD DDD1 FCCC F0EF 0F00"
$"00F0 6666 60F0 F1D1 D1DD FCCF 0EFE 0F00"
$"00F0 6666 60E0 E1D1 D111 FCF0 1FEF 0F00"
$"00F0 0000 0000 0000 0000 FF0E EE0E 0F00"
$"00FF FFFF FFFF FFFF FFFF F011 1F0F 0F00"
$"0000 F000 0000 0000 0000 0000 0000 0F00"
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FF"
};
resource 'icl4' (140) {
$"000F FFFF FFFF FFFF FFFF FFF0 0000 0000"
$"000F 0000 0000 0000 0000 00FF 0000 0000"
$"000F 0666 6600 0000 0000 00FC F000 0000"
$"000F 0666 660D 0C00 CC00 00FC CF00 0000"
$"000F 0666 660C 0C0D 0000 00FC CCF0 0000"
$"000F 0666 660C 0C00 0880 00FC CCCF 0000"
$"000F 0666 6600 000C C000 88FF FFFF F000"
$"000F 0666 6600 0000 000C 00C8 8000 F000"
$"000F 0666 660F FFFF FFFF FFF0 0000 F000"
$"000F 0666 600F FFFF FFFF FFFF 0000 F000"
$"000F 0666 000F FFF0 000C 00FF 0000 F000"
$"000F 0666 0D00 FFFD 000D 000C 0000 F000"
$"000F 0660 000C 0FFF 000C 000F 0C00 F000"
$"000F 0660 1111 10FF F000 CD0C 0C00 F000"
$"000F 0660 1DDF D10F FF00 0000 0C00 F000"
$"000F 0660 1FD1 8110 FFF0 000C 00C0 F000"
$"000F 0660 1F1D DD1C FFFF 0C00 0F00 F000"
$"000F 0660 0D11 D11C 0FFF 0000 FF00 F000"
$"000F 0666 0011 F110 00FF 00C0 0F00 F000"
$"000F 0666 0011 1110 0FFC 0000 0000 F000"
$"000F 0666 6000 000C FF0C 00C0 0000 F000"
$"000F 0666 660D D00F F000 00C0 00C0 F000"
$"000F 0666 6600 0CFF 0000 0000 F0C0 F000"
$"000F 0666 660C 0FFC 0000 0000 F000 F000"
$"000F 0666 660C FF00 0C00 C0CF F000 F000"
$"000F 0666 660F FFFF FFFF FFFF D000 F000"
$"000F 0666 660F FFFF FFFF FFFF C0C0 F000"
$"000F 0666 660C C00C 00C0 0CC0 0000 F000"
$"000F 0666 6603 3D00 0000 000D D0C0 F000"
$"000F 0666 6603 3D0C D00C 000D CC00 F000"
$"000F 0000 0000 0000 000C 0000 0000 F000"
$"000F FFFF FFFF FFFF FFFF FFFF FFFF F0"
};
resource 'icl4' (141) {
$"00FF FFFF FFFF FFFF FFFF FFFF FFFF 0000"
$"00F0 0000 0000 0000 0000 0000 000F 0000"
$"00F0 6666 60C0 C0D0 0C00 0C00 000F 0000"
$"00F0 6666 60C0 C000 8800 0CC0 0C0F FF00"
$"00F0 6666 6000 00CC 0008 8000 000F 0F00"
$"00F0 6666 6000 0000 00C0 0C88 000F 0F00"
$"00F0 6666 60FF FFFF FFFF FF00 000F 0F00"
$"00F0 6666 60FF FFFF FFFF FFF0 000F 0F00"
$"00F0 6666 00FF FF00 00C0 0FF0 000F 0F00"
$"00F0 6660 C00F FFD0 00D0 00C0 C00F 0F00"
$"00F0 6660 C0C0 FFF0 00C0 00F0 C00F 0F00"
$"00F0 6600 0000 0FFF 000C D0C0 000F 0F00"
$"00F0 6601 1111 0FFF F000 0000 000F 0F00"
$"00F0 6601 DDFD 100F FF00 00C0 000F 0F00"
$"00F0 6601 FD11 11CF FFF0 C000 C00F 0F00"
$"00F0 6601 F1DD D1C0 FFF0 000F C00F 0F00"
$"00F0 6600 D11D 1100 0FF0 0C00 000F 0F00"
$"00F0 6660 011F 1100 FFC0 0000 0C0F 0F00"
$"00F0 6660 0000 00CF F0C0 0C00 0C0F 0F00"
$"00F0 6666 0000 00FF 0000 0C00 0C0F 0F00"
$"00F0 6666 6000 CFF0 00C0 000F 0C0F 0F00"
$"00F0 6666 60C0 FFC0 0000 000F 000F 0F00"
$"00F0 6666 60CF F000 C00C 0CFF 000F 0F00"
$"00F0 6666 60FF FFFF FFFF FFFF FFF0 0F00"
$"00F0 6666 60FF FFFF FFFF F000 0F00 0F00"
$"00F0 6666 6000 0000 0000 F000 F000 0F00"
$"00F0 6666 6033 0CC0 0C00 F00F 0000 0F00"
$"00F0 6666 6033 C0C0 0000 F0F0 0000 0F00"
$"00F0 0000 0000 0000 0000 FF00 0000 0F00"
$"00FF FFFF FFFF FFFF FFFF F000 0000 0F00"
$"0000 F000 0000 0000 0000 0000 0000 0F00"
$"0000 FFFF FFFF FFFF FFFF FFFF FFFF FF"
};
resource 'icl4' (142) {
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"6666 6000 0000 0000 D000 0000 0000 0000"
$"6666 6000 0000 000D 6D00 0000 0000 0000"
$"6666 6000 0000 00D0 D6D0 0000 0000 0000"
$"6666 6000 0000 0D00 0D6D 0000 0000 0000"
$"6666 6000 0000 DF00 D0D6 D000 0000 0000"
$"6666 6000 000D F0CD 0F0D 6D00 0000 0000"
$"6666 6000 00D0 0DD0 D00D D6D0 0000 0000"
$"6666 6000 0DF0 0D00 0D0F 0D6D 0000 0000"
$"6666 6000 D00C D000 00D0 00D6 D000 0000"
$"6666 600D 000D 0000 000D 000D 6D00 0000"
$"6666 60DF 00D0 0000 0000 D0FD D6D0 0000"
$"6666 6D00 CD00 0000 0000 0D0F 0D6D 0000"
$"6666 DF00 D000 00DD 0DDD D0D0 0DD6 D000"
$"666D 000D 0000 DD0D D0DD FDDD 0F0D 6D00"
$"66DF 00D0 000D 0D09 0606 7666 D000 D6D0"
$"6D00 0D00 0D06 0070 1999 6966 6D00 0D6D"
$"66D0 D000 D600 6D99 1999 9999 66D0 00D0"
$"666D 000D D080 D991 1196 699D 996D 0D50"
$"6666 D0D0 060D 9111 1111 9699 966F D500"
$"6666 6DD0 D6D6 9991 1199 9996 999F F000"
$"6666 6D00 6D07 9999 1969 9999 99F9 6000"
$"6666 6DDD 0099 9999 1996 9996 969F 6F00"
$"6666 D00D 6797 9969 9666 9999 99F6 9F00"
$"6666 0D06 D669 9669 6669 9999 6999 6F00"
$"6666 DD60 6666 6666 9999 9999 9966 6F00"
$"6666 0606 6669 9999 6969 9999 6969 6F00"
$"6666 D066 6699 9999 9699 9999 969F 6F00"
$"6666 0606 6999 9999 9669 9999 66F9 FF00"
$"6666 DD66 6999 9999 9669 9999 6996 FF00"
$"6666 6066 6699 9999 9666 9969 666F F000"
$"6666 6D76 6666 9999 6666 6666 66FF F0"
};
resource 'FREF' (128) {
'APPL',
0,
""
};
resource 'FREF' (129) {
'SW/©',
1,
""
};
resource 'FREF' (130) {
'TEXT',
2,
""
};
resource 'FREF' (131) {
'sW/©',
3,
""
};
// Writer 2.0
resource 'FREF' (132) {
'SDwr',
4,
""
};
// Writer 2.0 Vorlage
resource 'FREF' (133) {
'SWwv',
5,
""
};
// Excel
resource 'FREF' (134) {
'XLS ',
6,
""
};
resource 'FREF' (135) {
'RTF ',
7,
""
};
// Word 6
resource 'FREF' (136) {
'W6BN',
8,
""
};
resource 'FREF' (137) {
'SVsc',
9,
""
};
resource 'FREF' (138) {
'sVsc',
10,
""
};
resource 'FREF' (139) {
'SVsd',
11,
""
};
resource 'FREF' (140) {
'sVsd',
12,
""
};
resource 'FREF' (141) {
'SVsh',
13,
""
};
resource 'FREF' (142) {
'sVsh',
14,
""
};
resource 'FREF' (143) {
'SVsi',
15,
""
};
resource 'FREF' (144) {
'sVsi',
16,
""
};
resource 'FREF' (145) {
'SVsm',
17,
""
};
resource 'FREF' (146) {
'sVsm',
18,
""
};
resource 'FREF' (147) {
'SVfs',
19,
""
};
resource 'BNDL' (128) {
'SVdt',
0,
{ /* array TypeArray: 2 elements */
/* [1] */
'FREF',
{ /* array IDArray: 20 elements */
/* [1] */
0, 128,
/* [2] */
1, 129,
/* [3] */
2, 130,
/* [4] */
3, 131,
/* [5] */
4, 132,
/* [6] */
5, 133,
/* [7] */
6, 134,
/* [8] */
7, 135,
/* [9] */
8, 136,
/* [10] */
9, 137,
/* [11] */
10, 138,
/* [12] */
11, 139,
/* [13] */
12, 140,
/* [14] */
13, 141,
/* [15] */
14, 142,
/* [16] */
15, 143,
/* [17] */
16, 144,
/* [18] */
17, 145,
/* [19] */
18, 146,
/* [20] */
19, 147
},
/* [2] */
'ICN#',
{ /* array IDArray: 20 elements */
/* [1] */
0, 128,
/* [2] */
1, 129,
/* [3] */
2, 131,
/* [4] */
3, 130,
/* [5] */
4, 0,
/* [6] */
5, 0,
/* [7] */
6, 0,
/* [8] */
7, 0,
/* [9] */
8, 0,
/* [10] */
9, 132,
/* [11] */
10, 133,
/* [12] */
11, 134,
/* [13] */
12, 135,
/* [14] */
13, 136,
/* [15] */
14, 137,
/* [16] */
15, 138,
/* [17] */
16, 139,
/* [18] */
17, 140,
/* [19] */
18, 141,
/* [20] */
19, 142
}
}
};
data 'cicn' (2001, "mrj bar") {
$"0000 0000 8010 0000 0000 0020 0020 0000"
$"0000 0000 0000 0048 0000 0048 0000 0000"
$"0004 0001 0004 0000 0000 0000 0000 0000"
$"0000 0000 0000 0004 0000 0000 0020 0020"
$"0000 0000 0004 0000 0000 0020 0020 0000"
$"0000 FC00 0000 FC00 0000 FC00 0000 FC00"
$"0000 FC00 0000 FC00 0000 FC00 0000 FC00"
$"0000 FC00 0000 FC00 0000 FC00 0000 FC00"
$"0000 FC00 0000 FC00 0000 FC00 0000 FC00"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 FC00 0000 8400 0000 C400 0000 E400"
$"0000 F400 0000 FC00 0000 9C00 0000 8C00"
$"0000 C400 0000 E400 0000 F400 0000 FC00"
$"0000 9C00 0000 8C00 0000 C400 0000 E400"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0007 0000 FFFF FFFF"
$"FFFF 0001 FFFF FFFF 3333 0002 FFFF CCCC"
$"0000 0003 3333 3333 3333 0004 4444 4444"
$"4444 0005 2222 2222 2222 0006 1111 1111"
$"1111 000F 0000 0000 0000 FFFF FF00 0000"
$"0000 0000 0000 0000 0000 F122 4300 0000"
$"0000 0000 0000 0000 0000 F422 2600 0000"
$"0000 0000 0000 0000 0000 F5F2 2F00 0000"
$"0000 0000 0000 0000 0000 F5FF FF00 0000"
$"0000 0000 0000 0000 0000 F1FF FF00 0000"
$"0000 0000 0000 0000 0000 F22F FF00 0000"
$"0000 0000 0000 0000 0000 F222 FF00 0000"
$"0000 0000 0000 0000 0000 F422 2F00 0000"
$"0000 0000 0000 0000 0000 F5F2 2F00 0000"
$"0000 0000 0000 0000 0000 F5FF FF00 0000"
$"0000 0000 0000 0000 0000 F1FF FF00 0000"
$"0000 0000 0000 0000 0000 F22F FF00 0000"
$"0000 0000 0000 0000 0000 F222 FF00 0000"
$"0000 0000 0000 0000 0000 F422 2F00 0000"
$"0000 0000 0000 0000 0000 F5F2 2F00 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000 0000 0000 0000"
$"0000 0000 0000 0000 0000"
}; diff --git a/desktop/win32/source/applauncher/launcher.cxx b/desktop/win32/source/applauncher/launcher.cxx new file mode 100644 index 000000000000..dd50c351a9ff --- /dev/null +++ b/desktop/win32/source/applauncher/launcher.cxx @@ -0,0 +1,148 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "launcher.hxx" + + +#ifndef _WINDOWS_ +# define WIN32_LEAN_AND_MEAN +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +# include <windows.h> +# include <shellapi.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#endif + + +#include <stdlib.h> +#include <malloc.h> + + +#ifdef __MINGW32__ +extern "C" int APIENTRY WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) +#else +extern "C" int APIENTRY _tWinMain( HINSTANCE, HINSTANCE, LPTSTR, int ) +#endif +{ + // Retreive startup info + + STARTUPINFO aStartupInfo; + + ZeroMemory( &aStartupInfo, sizeof(aStartupInfo) ); + aStartupInfo.cb = sizeof( aStartupInfo ); + GetStartupInfo( &aStartupInfo ); + + // Retrieve command line + + LPTSTR lpCommandLine = GetCommandLine(); + + LPTSTR *ppArguments = NULL; + int nArguments = 0; + + ppArguments = GetArgv( &nArguments ); + + // if ( 1 == nArguments ) + { + lpCommandLine = (LPTSTR)_alloca( sizeof(_TCHAR) * (_tcslen(lpCommandLine) + _tcslen(APPLICATION_SWITCH) + 2) ); + + _tcscpy( lpCommandLine, GetCommandLine() ); + _tcscat( lpCommandLine, _T(" ") ); + _tcscat( lpCommandLine, APPLICATION_SWITCH ); + } + + + // Calculate application name + + TCHAR szApplicationName[MAX_PATH]; + TCHAR szDrive[MAX_PATH]; + TCHAR szDir[MAX_PATH]; + TCHAR szFileName[MAX_PATH]; + TCHAR szExt[MAX_PATH]; + + GetModuleFileName( NULL, szApplicationName, MAX_PATH ); + _tsplitpath( szApplicationName, szDrive, szDir, szFileName, szExt ); + _tmakepath( szApplicationName, szDrive, szDir, OFFICE_IMAGE_NAME, _T(".exe") ); + + PROCESS_INFORMATION aProcessInfo; + + BOOL fSuccess = CreateProcess( + szApplicationName, + lpCommandLine, + NULL, + NULL, + TRUE, + 0, + NULL, + NULL, + &aStartupInfo, + &aProcessInfo ); + + if ( fSuccess ) + { + // Wait for soffice process to be terminated to allow other applications + // to wait for termination of started process + + WaitForSingleObject( aProcessInfo.hProcess, INFINITE ); + + CloseHandle( aProcessInfo.hProcess ); + CloseHandle( aProcessInfo.hThread ); + + return 0; + } + + DWORD dwError = GetLastError(); + + LPVOID lpMsgBuf; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dwError, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR)&lpMsgBuf, + 0, + NULL + ); + + // Display the string. + MessageBox( NULL, (LPCTSTR)lpMsgBuf, NULL, MB_OK | MB_ICONERROR ); + + // Free the buffer. + LocalFree( lpMsgBuf ); + + return GetLastError(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/launcher.hxx b/desktop/win32/source/applauncher/launcher.hxx new file mode 100644 index 000000000000..444789c96a5a --- /dev/null +++ b/desktop/win32/source/applauncher/launcher.hxx @@ -0,0 +1,24 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#pragma once +#ifndef __cplusplus +#error Need C++ to compile +#endif + +#ifndef _INC_TCHAR +# ifdef UNICODE +# define _UNICODE +# endif +# include <tchar.h> +#endif + +#ifdef UNICODE +# define GetArgv( pArgc ) CommandLineToArgvW( GetCommandLine(), pArgc ) +#else +# define GetArgv( pArgc ) (*pArgc = __argc, __argv) +#endif + +#define OFFICE_IMAGE_NAME _T("soffice") + +extern _TCHAR APPLICATION_SWITCH[]; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/makefile.mk b/desktop/win32/source/applauncher/makefile.mk new file mode 100644 index 000000000000..f0f5743f38a1 --- /dev/null +++ b/desktop/win32/source/applauncher/makefile.mk @@ -0,0 +1,148 @@ +#************************************************************************* +# +# 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=applauncher +LIBTARGET=NO +TARGETTYPE=GUI +UWINAPILIB= + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +CDEFS+=-DUNICODE + + +OBJFILES= \ + $(OBJ)$/launcher.obj \ + $(OBJ)$/swriter.obj \ + $(OBJ)$/scalc.obj \ + $(OBJ)$/sdraw.obj \ + $(OBJ)$/simpress.obj \ + $(OBJ)$/sbase.obj \ + $(OBJ)$/smath.obj \ + $(OBJ)$/sweb.obj + +# SO launcher +.IF "$(BUILD_SPECIAL)"!="" +APP1DEPN= $(APP1RES) verinfo.rc +APP1TARGET=so$/swriter +APP1NOSAL=TRUE +APP1LINKRES=$(MISC)$/$(TARGET)1.res +APP1ICON=$(SOLARRESDIR)$/icons/so9_writer_app.ico +APP1OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/swriter.obj +APP1STDLIBS = $(SHELL32LIB) +APP1VERINFO=verinfo.rc +APP1PRODUCTDEF+=-DRES_APP_NAME=swriter + +APP2TARGET=so$/scalc +APP2NOSAL=TRUE +APP2LINKRES=$(MISC)$/$(TARGET)2.res +APP2ICON=$(SOLARRESDIR)$/icons/so9_calc_app.ico +APP2OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/scalc.obj +APP2STDLIBS = $(SHELL32LIB) +APP2DEPN=verinfo.rc +APP2VERINFO=verinfo.rc +APP2PRODUCTDEF+=-DRES_APP_NAME=scalc + +APP3TARGET=so$/sdraw +APP3NOSAL=TRUE +APP3LINKRES=$(MISC)$/$(TARGET)3.res +APP3ICON=$(SOLARRESDIR)$/icons/so9_draw_app.ico +APP3OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/sdraw.obj +APP3STDLIBS = $(SHELL32LIB) +APP3DEPN=verinfo.rc +APP3VERINFO=verinfo.rc +APP3PRODUCTDEF+=-DRES_APP_NAME=sdraw + +APP4TARGET=so$/simpress +APP4NOSAL=TRUE +APP4LINKRES=$(MISC)$/$(TARGET)4.res +APP4ICON=$(SOLARRESDIR)$/icons/so9_impress_app.ico +APP4OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/simpress.obj +APP4STDLIBS = $(SHELL32LIB) +APP4DEPN=verinfo.rc +APP4VERINFO=verinfo.rc +APP4PRODUCTDEF+=-DRES_APP_NAME=simpress + +APP5TARGET=so$/sbase +APP5NOSAL=TRUE +APP5LINKRES=$(MISC)$/$(TARGET)5.res +APP5ICON=$(SOLARRESDIR)$/icons/so9_base_app.ico +APP5OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/sbase.obj +APP5STDLIBS = $(SHELL32LIB) +APP5DEPN=verinfo.rc +APP5VERINFO=verinfo.rc +APP5PRODUCTDEF+=-DRES_APP_NAME=sbase + +APP6TARGET=so$/smath +APP6NOSAL=TRUE +APP6LINKRES=$(MISC)$/$(TARGET)6.res +APP6ICON=$(SOLARRESDIR)$/icons/so9_math_app.ico +APP6OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/smath.obj +APP6STDLIBS = $(SHELL32LIB) +APP6DEPN=verinfo.rc +APP6VERINFO=verinfo.rc +APP6PRODUCTDEF+=-DRES_APP_NAME=smath + +APP7TARGET=so$/sweb +APP7NOSAL=TRUE +APP7LINKRES=$(MISC)$/$(TARGET)7.res +APP7ICON=$(SOLARRESDIR)$/icons/so9_writer_app.ico +APP7OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/sweb.obj +APP7STDLIBS = $(SHELL32LIB) +APP7DEPN=verinfo.rc +APP7VERINFO=verinfo.rc +APP7PRODUCTDEF+=-DRES_APP_NAME=sweb + + +.ENDIF # "$(BUILD_SPECIAL)"!="" + +# --- Targets ------------------------------------------------------ + + +.INCLUDE : target.mk + diff --git a/desktop/win32/source/applauncher/ooo/makefile.mk b/desktop/win32/source/applauncher/ooo/makefile.mk new file mode 100644 index 000000000000..02f240cce9e0 --- /dev/null +++ b/desktop/win32/source/applauncher/ooo/makefile.mk @@ -0,0 +1,130 @@ +#************************************************************************* +# +# 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=applauncher +LIBTARGET=NO +TARGETTYPE=GUI +UWINAPILIB= + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +APP1TARGET=swriter +APP1DEPN=verinfo.rc +APP1VERINFO=verinfo.rc +APP1NOSAL=TRUE +APP1LINKRES=$(MISC)$/$(TARGET)1.res +APP1ICON=$(SOLARRESDIR)$/icons/ooo3_writer_app.ico +APP1OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/swriter.obj +APP1STDLIBS = $(SHELL32LIB) +APP1PRODUCTDEF+=-DRES_APP_NAME=$(APP1TARGET) + +APP2TARGET=scalc +APP2DEPN=verinfo.rc +APP2VERINFO=verinfo.rc +APP2NOSAL=TRUE +APP2LINKRES=$(MISC)$/$(TARGET)2.res +APP2ICON=$(SOLARRESDIR)$/icons/ooo3_calc_app.ico +APP2OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/scalc.obj +APP2STDLIBS = $(SHELL32LIB) +APP2PRODUCTDEF+=-DRES_APP_NAME=$(APP2TARGET) + +APP3TARGET=sdraw +APP3DEPN=verinfo.rc +APP3VERINFO=verinfo.rc +APP3NOSAL=TRUE +APP3LINKRES=$(MISC)$/$(TARGET)3.res +APP3ICON=$(SOLARRESDIR)$/icons/ooo3_draw_app.ico +APP3OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/sdraw.obj +APP3STDLIBS = $(SHELL32LIB) +APP3PRODUCTDEF+=-DRES_APP_NAME=$(APP3TARGET) + +APP4TARGET=simpress +APP4DEPN=verinfo.rc +APP4VERINFO=verinfo.rc +APP4NOSAL=TRUE +APP4LINKRES=$(MISC)$/$(TARGET)4.res +APP4ICON=$(SOLARRESDIR)$/icons/ooo3_impress_app.ico +APP4OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/simpress.obj +APP4STDLIBS = $(SHELL32LIB) +APP4PRODUCTDEF+=-DRES_APP_NAME=$(APP4TARGET) + +APP5TARGET=smath +APP5DEPN=verinfo.rc +APP5VERINFO=verinfo.rc +APP5NOSAL=TRUE +APP5LINKRES=$(MISC)$/$(TARGET)5.res +APP5ICON=$(SOLARRESDIR)$/icons/ooo3_math_app.ico +APP5OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/smath.obj +APP5STDLIBS = $(SHELL32LIB) +APP5PRODUCTDEF+=-DRES_APP_NAME=$(APP5TARGET) + +APP6TARGET=sbase +APP6DEPN=verinfo.rc +APP6VERINFO=verinfo.rc +APP6NOSAL=TRUE +APP6LINKRES=$(MISC)$/$(TARGET)6.res +APP6ICON=$(SOLARRESDIR)$/icons/ooo3_base_app.ico +APP6OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/sbase.obj +APP6STDLIBS = $(SHELL32LIB) +APP6PRODUCTDEF+=-DRES_APP_NAME=$(APP6TARGET) + +APP7TARGET=sweb +APP7DEPN=verinfo.rc +APP7VERINFO=verinfo.rc +APP7NOSAL=TRUE +APP7LINKRES=$(MISC)$/$(TARGET)7.res +APP7ICON=$(SOLARRESDIR)$/icons/ooo3_writer_app.ico +APP7OBJS = \ + $(OBJ)$/launcher.obj\ + $(OBJ)$/sweb.obj +APP7STDLIBS = $(SHELL32LIB) +APP7PRODUCTDEF+=-DRES_APP_NAME=$(APP7TARGET) + +# --- Targets ------------------------------------------------------ + + +.INCLUDE : target.mk + diff --git a/desktop/win32/source/applauncher/ooo/verinfo.rc b/desktop/win32/source/applauncher/ooo/verinfo.rc new file mode 100755 index 000000000000..61e9147a4ab6 --- /dev/null +++ b/desktop/win32/source/applauncher/ooo/verinfo.rc @@ -0,0 +1,71 @@ +/************************************************************************* + * + * 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. + * + *************************************************************************/ + +#define VER_FIRSTYEAR 2009 + +#include <windows.h> +#include "version.hrc" + +// ----------------------------------------------------------------------- +// version information +// ----------------------------------------------------------------------- + +VS_VERSION_INFO versioninfo + fileversion VERSION, SUBVERSION, VERVARIANT, VER_COUNT + productversion VERSION, SUBVERSION, VERVARIANT, VER_COUNT + fileflagsmask 0x3F + fileflags +#if defined(DEBUG) + VS_FF_DEBUG | +#endif +#ifdef VER_PREL + VS_FF_PRERELEASE | +#endif + 0 + fileos VOS_NT_WINDOWS32 + filetype VFT_APP + { + block "StringFileInfo" + { + block "040904E4" + { + // International StringTable + value "CompanyName", "The Document Foundation\0" + value "FileDescription", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\0" + value "FileVersion", PPS(VER_LEVEL) "\0" + value "ProductVersion", PPS(VER_LEVEL) "\0" + value "OriginalFilename", PPS(RES_APP_NAME) ".exe\0" + value "InternalName", PPS(RES_APP_NAME) "\0" + value "LegalCopyright", S_CRIGHT " Oracle and/or its affiliates. All rights reserved.\0" + } + } + + block "VarFileInfo" + { + value "Translation", 0x0409, 1252 + } + } diff --git a/desktop/win32/source/applauncher/sbase.cxx b/desktop/win32/source/applauncher/sbase.cxx new file mode 100644 index 000000000000..df940d0267dd --- /dev/null +++ b/desktop/win32/source/applauncher/sbase.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "launcher.hxx" + +_TCHAR APPLICATION_SWITCH[] = _T( "-base" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/scalc.cxx b/desktop/win32/source/applauncher/scalc.cxx new file mode 100644 index 000000000000..ed741c28e088 --- /dev/null +++ b/desktop/win32/source/applauncher/scalc.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "launcher.hxx" + +_TCHAR APPLICATION_SWITCH[] = _T( "-calc" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/sdraw.cxx b/desktop/win32/source/applauncher/sdraw.cxx new file mode 100644 index 000000000000..c8aa2f62f887 --- /dev/null +++ b/desktop/win32/source/applauncher/sdraw.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "launcher.hxx" + +_TCHAR APPLICATION_SWITCH[] = _T( "-draw" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/simpress.cxx b/desktop/win32/source/applauncher/simpress.cxx new file mode 100644 index 000000000000..616082792216 --- /dev/null +++ b/desktop/win32/source/applauncher/simpress.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "launcher.hxx" + +_TCHAR APPLICATION_SWITCH[] = _T( "-impress" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/smath.cxx b/desktop/win32/source/applauncher/smath.cxx new file mode 100644 index 000000000000..cec6bbdca14d --- /dev/null +++ b/desktop/win32/source/applauncher/smath.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "launcher.hxx" + +_TCHAR APPLICATION_SWITCH[] = _T( "-math" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/sweb.cxx b/desktop/win32/source/applauncher/sweb.cxx new file mode 100644 index 000000000000..578239dd1a9b --- /dev/null +++ b/desktop/win32/source/applauncher/sweb.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "launcher.hxx" + +_TCHAR APPLICATION_SWITCH[] = _T( "-web" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/swriter.cxx b/desktop/win32/source/applauncher/swriter.cxx new file mode 100644 index 000000000000..5235e5b7b246 --- /dev/null +++ b/desktop/win32/source/applauncher/swriter.cxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "launcher.hxx" + +_TCHAR APPLICATION_SWITCH[] = _T( "-writer" ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/verinfo.rc b/desktop/win32/source/applauncher/verinfo.rc new file mode 100644 index 000000000000..afb58f3a377c --- /dev/null +++ b/desktop/win32/source/applauncher/verinfo.rc @@ -0,0 +1,76 @@ +/************************************************************************* + * + * 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. + * + *************************************************************************/ + +#define VER_FIRSTYEAR 2009 + +#include <windows.h> +#include "version_so.hrc" + +// ----------------------------------------------------------------------- +// version information +// ----------------------------------------------------------------------- + +VS_VERSION_INFO versioninfo +#ifndef SUBVERSION + fileversion VERSION, 0, VERVARIANT, VER_COUNT + productversion VERSION, 0, VERVARIANT, VER_COUNT +#else + fileversion VERSION, SUBVERSION, VERVARIANT, VER_COUNT + productversion VERSION, SUBVERSION, VERVARIANT, VER_COUNT +#endif + fileflagsmask 0x3F + fileflags +#if defined(DEBUG) + VS_FF_DEBUG | +#endif +#ifdef VER_PREL + VS_FF_PRERELEASE | +#endif + 0 + fileos VOS_NT_WINDOWS32 + filetype VFT_APP + { + block "StringFileInfo" + { + block "040904E4" + { + // International StringTable + value "CompanyName", "The Document Foundation\0" + value "FileDescription", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\0" + value "FileVersion", PPS(VER_LEVEL) "\0" + value "ProductVersion", PPS(VER_LEVEL) "\0" + value "OriginalFilename", PPS(RES_APP_NAME) ".exe\0" + value "InternalName", PPS(RES_APP_NAME) "\0" + value "LegalCopyright", S_CRIGHT " Oracle and/or its affiliates. All rights reserved.\0" + } + } + + block "VarFileInfo" + { + value "Translation", 0x0409, 1252 + } + } diff --git a/desktop/win32/source/extendloaderenvironment.cxx b/desktop/win32/source/extendloaderenvironment.cxx new file mode 100644 index 000000000000..436003c7703e --- /dev/null +++ b/desktop/win32/source/extendloaderenvironment.cxx @@ -0,0 +1,185 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "precompiled_desktop.hxx" +#include "sal/config.h" + +#include <cstddef> + +#define WIN32_LEAN_AND_MEAN +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#include <shlwapi.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#include "tools/pathutils.hxx" + +#include "extendloaderenvironment.hxx" + +namespace { + +void fail() { + LPWSTR buf = NULL; + FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, + GetLastError(), 0, reinterpret_cast< LPWSTR >(&buf), 0, NULL); + MessageBoxW(NULL, buf, NULL, MB_OK | MB_ICONERROR); + LocalFree(buf); + TerminateProcess(GetCurrentProcess(), 255); +} + +bool contains(WCHAR const * paths, WCHAR const * path, WCHAR const * pathEnd) { + WCHAR const * q = path; + for (WCHAR const * p = paths;; ++p) { + WCHAR c = *p; + switch (c) { + case L'\0': + return q == pathEnd; + case L';': + if (q == pathEnd) { + return true; + } + q = path; + break; + default: + if (q != NULL) { + if (q != pathEnd && *q == c) { + ++q; + } else { + q = NULL; + } + } + break; + } + } +} + +} + +namespace desktop_win32 { + +void extendLoaderEnvironment(WCHAR * binPath, WCHAR * iniDirectory) { + if (!GetModuleFileNameW(NULL, iniDirectory, MAX_PATH)) { + fail(); + } + WCHAR * iniDirEnd = tools::filename(iniDirectory); + WCHAR name[MAX_PATH + MY_LENGTH(L".bin")]; + // hopefully std::size_t is large enough to not overflow + WCHAR * nameEnd = name; + for (WCHAR * p = iniDirEnd; *p != L'\0'; ++p) { + *nameEnd++ = *p; + } + if (!(nameEnd - name >= 4 && nameEnd[-4] == L'.' && + (nameEnd[-3] == L'E' || nameEnd[-3] == L'e') && + (nameEnd[-2] == L'X' || nameEnd[-2] == L'x') && + (nameEnd[-1] == L'E' || nameEnd[-1] == L'e'))) + { + *nameEnd = L'.'; + nameEnd += 4; + } + nameEnd[-3] = 'b'; + nameEnd[-2] = 'i'; + nameEnd[-1] = 'n'; + tools::buildPath(binPath, iniDirectory, iniDirEnd, name, nameEnd - name); + *iniDirEnd = L'\0'; + WCHAR path[MAX_PATH]; + WCHAR * pathEnd = tools::buildPath( + path, iniDirectory, iniDirEnd, MY_STRING(L"..\\basis-link")); + if (pathEnd == NULL) { + fail(); + } + std::size_t const maxEnv = 32767; + WCHAR pad[2 * MAX_PATH + maxEnv]; + // hopefully std::size_t is large enough to not overflow + WCHAR * padEnd = NULL; + WCHAR env[maxEnv]; + DWORD n = GetEnvironmentVariableW(L"PATH", env, maxEnv); + if (n >= maxEnv || n == 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND) { + fail(); + } + env[n] = L'\0'; + bool exclude1; + pathEnd = tools::resolveLink(path); + if (pathEnd == NULL) { + if (GetLastError() != ERROR_FILE_NOT_FOUND) { + fail(); + } + // This path is only taken by testtool.exe in basis program directory; + // its PATH needs to include the brand program directory: + pathEnd = tools::buildPath( + path, iniDirectory, iniDirEnd, MY_STRING(L"..")); + if (pathEnd == NULL) { + fail(); + } + padEnd = tools::buildPath( + pad, path, pathEnd, MY_STRING(L"\\..\\program")); + if (padEnd == NULL) { + fail(); + } + exclude1 = contains(env, pad, padEnd); + } else { + exclude1 = true; + } + WCHAR * pad2 = exclude1 ? pad : padEnd + 1; + pathEnd = tools::buildPath(path, path, pathEnd, MY_STRING(L"\\ure-link")); + if (pathEnd == NULL) { + fail(); + } + pathEnd = tools::resolveLink(path); + if (pathEnd == NULL) { + fail(); + } + padEnd = tools::buildPath(pad2, path, pathEnd, MY_STRING(L"\\bin")); + if (padEnd == NULL) { + fail(); + } + bool exclude2 = contains(env, pad2, padEnd); + if (!(exclude1 && exclude2)) { + if (!(exclude1 || exclude2)) { + pad2[-1] = L';'; + } + WCHAR * p = exclude2 ? pad2 - 1 : padEnd; + if (n != 0) { + *p++ = L';'; + } + for (DWORD i = 0; i <= n; ++i) { + *p++ = env[i]; + } + if (!SetEnvironmentVariableW(L"PATH", pad)) { + fail(); + } + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/extendloaderenvironment.hxx b/desktop/win32/source/extendloaderenvironment.hxx new file mode 100644 index 000000000000..2c1207a0dbac --- /dev/null +++ b/desktop/win32/source/extendloaderenvironment.hxx @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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_WIN32_SOURCE_EXTENDLOADERENVIRONMENT_HXX +#define INCLUDED_DESKTOP_WIN32_SOURCE_EXTENDLOADERENVIRONMENT_HXX + +#include "sal/config.h" + +#include <cstddef> + +#include <tchar.h> + +#define MY_LENGTH(s) (sizeof (s) / sizeof *(s) - 1) +#define MY_STRING(s) (s), MY_LENGTH(s) + +namespace desktop_win32 { + +inline WCHAR * commandLineAppend( + WCHAR * buffer, WCHAR const * text, std::size_t length) +{ + wcsncpy(buffer, text, length + 1); // trailing null + return buffer + length; +} + +inline WCHAR * commandLineAppend(WCHAR * buffer, WCHAR const * text) { + return commandLineAppend(buffer, text, wcslen(text)); +} + +inline WCHAR * commandLineAppendEncoded(WCHAR * buffer, WCHAR const * text) { + std::size_t n = 0; + for (;;) { + WCHAR c = *text++; + if (c == L'\0') { + break; + } else if (c == L'$') { + buffer = commandLineAppend(buffer, MY_STRING(L"\\$")); + n = 0; + } else if (c == L'\\') { + buffer = commandLineAppend(buffer, MY_STRING(L"\\\\")); + n += 2; + } else { + *buffer++ = c; + n = 0; + } + } + // The command line will continue with a double quote, so double any + // preceding backslashes as required by Windows: + for (std::size_t i = 0; i < n; ++i) { + *buffer++ = L'\\'; + } + *buffer = L'\0'; + return buffer; +} + +// Set the PATH environment variable in the current (loader) process, so that a +// following CreateProcess has the necessary environment: +// +// @param binPath +// Must point to an array of size at least MAX_PATH. Is filled with the null +// terminated full path to the "bin" file corresponding to the current +// executable. +// +// @param iniDirectory +// Must point to an array of size at least MAX_PATH. Is filled with the null +// terminated full directory path (ending in "\") to the "ini" file +// corresponding to the current executable. +void extendLoaderEnvironment(WCHAR * binPath, WCHAR * iniDirectory); + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/guiloader/genericloader.cxx b/desktop/win32/source/guiloader/genericloader.cxx new file mode 100644 index 000000000000..ac84ed35103c --- /dev/null +++ b/desktop/win32/source/guiloader/genericloader.cxx @@ -0,0 +1,178 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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" +#define UNICODE +#define _UNICODE + +#define WIN32_LEAN_AND_MEAN +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#include <shellapi.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#include <tchar.h> + +#include <malloc.h> +#include <string.h> +#include <stdlib.h> +#include <systools/win32/uwinapi.h> + +#include "tools/pathutils.hxx" +#include "../extendloaderenvironment.hxx" + +//--------------------------------------------------------------------------- + +static int GenericMain() +{ + TCHAR szTargetFileName[MAX_PATH]; + TCHAR szIniDirectory[MAX_PATH]; + STARTUPINFO aStartupInfo; + + desktop_win32::extendLoaderEnvironment(szTargetFileName, szIniDirectory); + + ZeroMemory( &aStartupInfo, sizeof(aStartupInfo) ); + aStartupInfo.cb = sizeof(aStartupInfo); + + GetStartupInfo( &aStartupInfo ); + + DWORD dwExitCode = (DWORD)-1; + + PROCESS_INFORMATION aProcessInfo; + + size_t iniDirLen = wcslen(szIniDirectory); + WCHAR cwd[MAX_PATH]; + DWORD cwdLen = GetCurrentDirectoryW(MAX_PATH, cwd); + if (cwdLen >= MAX_PATH) { + cwdLen = 0; + } + WCHAR redirect[MAX_PATH]; + DWORD dummy; + bool hasRedirect = + tools::buildPath( + redirect, szIniDirectory, szIniDirectory + iniDirLen, + MY_STRING(L"redirect.ini")) != NULL && + (GetBinaryType(redirect, &dummy) || // cheaper check for file existence? + GetLastError() != ERROR_FILE_NOT_FOUND); + LPTSTR cl1 = GetCommandLine(); + WCHAR * cl2 = new WCHAR[ + wcslen(cl1) + + (hasRedirect + ? (MY_LENGTH(L" \"-env:INIFILENAME=vnd.sun.star.pathname:") + + iniDirLen + MY_LENGTH(L"redirect.ini\"")) + : 0) + + MY_LENGTH(L" \"-env:OOO_CWD=2") + 4 * cwdLen + MY_LENGTH(L"\"") + 1]; + // 4 * cwdLen: each char preceded by backslash, each trailing backslash + // doubled + WCHAR * p = desktop_win32::commandLineAppend(cl2, cl1); + if (hasRedirect) { + p = desktop_win32::commandLineAppend( + p, MY_STRING(L" \"-env:INIFILENAME=vnd.sun.star.pathname:")); + p = desktop_win32::commandLineAppend(p, szIniDirectory); + p = desktop_win32::commandLineAppend(p, MY_STRING(L"redirect.ini\"")); + } + p = desktop_win32::commandLineAppend(p, MY_STRING(L" \"-env:OOO_CWD=")); + if (cwdLen == 0) { + p = desktop_win32::commandLineAppend(p, MY_STRING(L"0")); + } else { + p = desktop_win32::commandLineAppend(p, MY_STRING(L"2")); + p = desktop_win32::commandLineAppendEncoded(p, cwd); + } + desktop_win32::commandLineAppend(p, MY_STRING(L"\"")); + + BOOL fSuccess = CreateProcess( + szTargetFileName, + cl2, + NULL, + NULL, + TRUE, + 0, + NULL, + szIniDirectory, + &aStartupInfo, + &aProcessInfo ); + + delete[] cl2; + + if ( fSuccess ) + { + DWORD dwWaitResult; + + do + { + // On Windows XP it seems as the desktop calls WaitForInputIdle after "OpenWidth" so we have to do so + // as if we where processing any messages + + dwWaitResult = MsgWaitForMultipleObjects( 1, &aProcessInfo.hProcess, FALSE, INFINITE, QS_ALLEVENTS ); + + if ( WAIT_OBJECT_0 + 1 == dwWaitResult ) + { + MSG msg; + + PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ); + } + } while ( WAIT_OBJECT_0 + 1 == dwWaitResult ); + + dwExitCode = 0; + GetExitCodeProcess( aProcessInfo.hProcess, &dwExitCode ); + + CloseHandle( aProcessInfo.hProcess ); + CloseHandle( aProcessInfo.hThread ); + } + + return dwExitCode; +} + +//--------------------------------------------------------------------------- + +#ifdef __MINGW32__ +int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) +#else +int WINAPI _tWinMain( HINSTANCE, HINSTANCE, LPTSTR, int ) +#endif +{ + return GenericMain(); +} + +//--------------------------------------------------------------------------- + +#ifdef __MINGW32__ +int __cdecl main() +#else +int __cdecl _tmain() +#endif +{ + return GenericMain(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/guiloader/makefile.mk b/desktop/win32/source/guiloader/makefile.mk new file mode 100644 index 000000000000..5bb1c523ff19 --- /dev/null +++ b/desktop/win32/source/guiloader/makefile.mk @@ -0,0 +1,64 @@ +#************************************************************************* +# +# 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=guiloader +LIBTARGET=NO +TARGETTYPE=GUI +UWINAPILIB= + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +APP1TARGET=guiloader +APP1NOSAL=TRUE +APP1ICON=$(SOLARRESDIR)$/icons/ooo-main-app.ico +APP1OBJS=\ + $(OBJ)$/extendloaderenvironment.obj \ + $(OBJ)$/genericloader.obj \ + $(SOLARLIBDIR)$/pathutils-obj.obj +STDLIB1=$(SHLWAPILIB) + +APP2TARGET=so$/guiloader +APP2NOSAL=TRUE +APP2ICON=$(SOLARRESDIR)$/icons/so8-main-app.ico +APP2OBJS=\ + $(OBJ)$/extendloaderenvironment.obj \ + $(OBJ)$/genericloader.obj \ + $(SOLARLIBDIR)$/pathutils-obj.obj +STDLIB2=$(SHLWAPILIB) + +# --- Targets ------------------------------------------------------ + + +.INCLUDE : target.mk + diff --git a/desktop/win32/source/guistdio/guistdio.cxx b/desktop/win32/source/guistdio/guistdio.cxx new file mode 100644 index 000000000000..7ebf4cb1204a --- /dev/null +++ b/desktop/win32/source/guistdio/guistdio.cxx @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "precompiled_desktop.hxx" + +#include "guistdio.inc" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/guistdio/guistdio.inc b/desktop/win32/source/guistdio/guistdio.inc new file mode 100644 index 000000000000..05d462d23197 --- /dev/null +++ b/desktop/win32/source/guistdio/guistdio.inc @@ -0,0 +1,454 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#define UNICODE +#define WIN32_LEAN_AND_MEAN +#ifdef _MSC_VER +#pragma warning(push,1) // disable warnings within system headers +#endif +#include <windows.h> +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#define _UNICODE +#include <tchar.h> + +#include <string.h> +#include <stdlib.h> +#include <systools/win32/uwinapi.h> + +#include <stdio.h> +#include <sal/macros.h> + +#ifdef UNOPKG + +DWORD passOutputToConsole(HANDLE readPipe, HANDLE console) +{ + BYTE aBuffer[1024]; + DWORD dwRead = 0; + HANDLE hReadPipe = readPipe; + BOOL fSuccess; + DWORD dwWritten; + + //Indicates that we read an odd number of bytes. That is, we only read half of the last + //wchar_t + bool bIncompleteWchar = false; + //fprintf, fwprintf will both send char data without the terminating zero. + //fwprintf converts the unicode string first. + //We expect here to receive unicode without the terminating zero. + //unopkg and the extension manager code MUST + //use dp_misc::writeConsole instead of using fprintf, etc. + + DWORD dwToRead = sizeof(aBuffer); + BYTE * pBuffer = aBuffer; + while ( ReadFile( hReadPipe, pBuffer, dwToRead, &dwRead, NULL ) ) + { + //If the previous ReadFile call read an odd number of bytes, then the last one was + //put at the front of the buffer. We increase the number of read bytes by one to reflect + //that one byte. + if (bIncompleteWchar) + dwRead++; + //We must make sure that only complete wchar_t|s are written. WriteConsolse takes + //the number of wchar_t|s as argument. ReadFile, however, reads bytes. + bIncompleteWchar = dwRead % 2 ? true : false; + if (bIncompleteWchar) + { + //To test this case, give aBuffer a small odd size, e.g. aBuffer[3] + //The last byte, which is the incomplete wchar_t (half of it), will not be written. + fSuccess = WriteConsoleW( console, aBuffer, + (dwRead - 1) / 2, &dwWritten, NULL ); + + //Move the last byte to the front of the buffer, so that it is the start of the + //next string + aBuffer[0] = aBuffer[dwRead - 1]; + + //Make sure that ReadFile does not overwrite the first byte the next time + dwToRead = sizeof(aBuffer) - 1; + pBuffer = aBuffer + 1; + + } + else + { //We have read an even number of bytes. Therefore, we do not put the last incomplete + //wchar_t at the front of the buffer. We will use the complete buffer the next time + //when ReadFile is called. + dwToRead = sizeof(aBuffer); + pBuffer = aBuffer; + fSuccess = WriteConsoleW( console, + aBuffer, dwRead / 2, &dwWritten, NULL ); + } + } + + return 0; +} + +#endif + +#ifdef UNOPKG +DWORD WINAPI OutputThread( LPVOID pParam ) +{ + return passOutputToConsole((HANDLE)pParam, GetStdHandle( STD_OUTPUT_HANDLE )); +} + +#else +DWORD WINAPI OutputThread( LPVOID pParam ) +{ + BYTE aBuffer[256]; + DWORD dwRead = 0; + HANDLE hReadPipe = (HANDLE)pParam; + while ( ReadFile( hReadPipe, &aBuffer, sizeof(aBuffer), &dwRead, NULL ) ) + { + BOOL fSuccess; + DWORD dwWritten; + + fSuccess = WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ), aBuffer, dwRead, &dwWritten, NULL ); + } + + return 0; +} +#endif +//--------------------------------------------------------------------------- +// Thread that reads from child process standard error pipe +//--------------------------------------------------------------------------- + +#ifdef UNOPKG +DWORD WINAPI ErrorThread( LPVOID pParam ) +{ + return passOutputToConsole((HANDLE)pParam, GetStdHandle( STD_ERROR_HANDLE )); +} + +#else +DWORD WINAPI ErrorThread( LPVOID pParam ) +{ + BYTE aBuffer[256]; + DWORD dwRead = 0; + HANDLE hReadPipe = (HANDLE)pParam; + + while ( ReadFile( hReadPipe, &aBuffer, sizeof(aBuffer), &dwRead, NULL ) ) + { + BOOL fSuccess; + DWORD dwWritten; + + fSuccess = WriteFile( GetStdHandle( STD_ERROR_HANDLE ), aBuffer, dwRead, &dwWritten, NULL ); + } + + return 0; +} +#endif +//--------------------------------------------------------------------------- +// Thread that writes to child process standard input pipe +//--------------------------------------------------------------------------- +#ifdef UNOPKG + +DWORD WINAPI InputThread( LPVOID pParam ) +{ + DWORD dwRead = 0; + HANDLE hWritePipe = (HANDLE)pParam; + + //We need to read in the complete input until we encounter a new line before + //converting to Unicode. This is necessary because the input string can use + //characters of one, two, and more bytes. If the last character is not + //complete, then it will not be converted properly. + + //Find out how a new line (0xd 0xa) looks like with the used code page. + //Characters may have one or multiple bytes and different byte ordering + //can be used (little and big endian); + int cNewLine = WideCharToMultiByte( + GetConsoleCP(), 0, L"\r\n", 2, NULL, 0, NULL, NULL); + char * mbBuff = new char[cNewLine]; + WideCharToMultiByte( + GetConsoleCP(), 0, L"\r\n", 2, mbBuff, cNewLine, NULL, NULL); + + const size_t dwBufferSize = 256; + char* readBuf = (char*) malloc(dwBufferSize); + int readAll = 0; + size_t curBufSize = dwBufferSize; + + while ( ReadFile( GetStdHandle( STD_INPUT_HANDLE ), + readBuf + readAll, + curBufSize - readAll, &dwRead, NULL ) ) + { + readAll += dwRead; + int lastBufSize = curBufSize; + //Grow the buffer if necessary + if (readAll > curBufSize * 0.7) + { + curBufSize *= 2; + readBuf = (char *) realloc(readBuf, curBufSize); + } + + //If the buffer was filled completely then + //there could be more input coming. But if we read from the console + //and the console input fits exactly in the buffer, then the next + //ReadFile would block until the users presses return, etc. + //Therefor we check if last character is a new line. + //To test this, set dwBufferSize to 4 and enter "no". This should produce + //4 bytes with most code pages. + if ( readAll == lastBufSize + && memcmp(readBuf + lastBufSize - cNewLine, mbBuff, cNewLine) != 0) + { + //The buffer was completely filled and the last byte(s) are no + //new line, so there is more to come. + continue; + } + //Obtain the size of the buffer for the converted string. + int sizeWBuf = MultiByteToWideChar( + GetConsoleCP(), MB_PRECOMPOSED, readBuf, readAll, NULL, 0); + + wchar_t * wideBuf = new wchar_t[sizeWBuf]; + + //Do the conversion. + MultiByteToWideChar( + GetConsoleCP(), MB_PRECOMPOSED, readBuf, readAll, wideBuf, sizeWBuf); + + BOOL fSuccess; + DWORD dwWritten; + fSuccess = WriteFile( hWritePipe, wideBuf, sizeWBuf * 2, &dwWritten, NULL ); + delete[] wideBuf; + readAll = 0; + } + delete[] mbBuff; + free(readBuf); + return 0; +} +#else +DWORD WINAPI InputThread( LPVOID pParam ) +{ + BYTE aBuffer[256]; + DWORD dwRead = 0; + HANDLE hWritePipe = (HANDLE)pParam; + + while ( ReadFile( GetStdHandle( STD_INPUT_HANDLE ), &aBuffer, sizeof(aBuffer), &dwRead, NULL ) ) + { + BOOL fSuccess; + DWORD dwWritten; + + fSuccess = WriteFile( hWritePipe, aBuffer, dwRead, &dwWritten, NULL ); + } + + return 0; +} +#endif + +//--------------------------------------------------------------------------- +// Thread that waits until child process reached input idle +//--------------------------------------------------------------------------- + +DWORD WINAPI WaitForUIThread( LPVOID pParam ) +{ + HANDLE hProcess = (HANDLE)pParam; + +#ifndef UNOPKG + if ( !_tgetenv( TEXT("UNOPKG") ) ) + WaitForInputIdle( hProcess, INFINITE ); +#endif + + return 0; +} + + +//--------------------------------------------------------------------------- +// Ctrl-Break handler that terminates the child process if Ctrl-C was pressed +//--------------------------------------------------------------------------- + +HANDLE hTargetProcess = INVALID_HANDLE_VALUE; + +BOOL WINAPI CtrlBreakHandler( + DWORD // control signal type +) +{ + TerminateProcess( hTargetProcess, 255 ); + return TRUE; +} + + +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- + +#ifdef __MINGW32__ +int main( int, char ** ) +#else +int _tmain( int, _TCHAR ** ) +#endif +{ + TCHAR szTargetFileName[MAX_PATH] = TEXT(""); + STARTUPINFO aStartupInfo; + PROCESS_INFORMATION aProcessInfo; + + ZeroMemory( &aStartupInfo, sizeof(aStartupInfo) ); + aStartupInfo.cb = sizeof(aStartupInfo); + aStartupInfo.dwFlags = STARTF_USESTDHANDLES; + + // Create an output pipe where the write end is inheritable + + HANDLE hOutputRead, hOutputWrite; + + if ( CreatePipe( &hOutputRead, &hOutputWrite, NULL, 0 ) ) + { + HANDLE hTemp; + + DuplicateHandle( GetCurrentProcess(), hOutputWrite, GetCurrentProcess(), &hTemp, 0, TRUE, DUPLICATE_SAME_ACCESS ); + CloseHandle( hOutputWrite ); + hOutputWrite = hTemp; + + aStartupInfo.hStdOutput = hOutputWrite; + } + + // Create an error pipe where the write end is inheritable + + HANDLE hErrorRead, hErrorWrite; + + if ( CreatePipe( &hErrorRead, &hErrorWrite, NULL, 0 ) ) + { + HANDLE hTemp; + + DuplicateHandle( GetCurrentProcess(), hErrorWrite, GetCurrentProcess(), &hTemp, 0, TRUE, DUPLICATE_SAME_ACCESS ); + CloseHandle( hErrorWrite ); + hErrorWrite = hTemp; + + aStartupInfo.hStdError = hErrorWrite; + } + + // Create an input pipe where the read end is inheritable + + HANDLE hInputRead, hInputWrite; + + if ( CreatePipe( &hInputRead, &hInputWrite, NULL, 0 ) ) + { + HANDLE hTemp; + + DuplicateHandle( GetCurrentProcess(), hInputRead, GetCurrentProcess(), &hTemp, 0, TRUE, DUPLICATE_SAME_ACCESS ); + CloseHandle( hInputRead ); + hInputRead = hTemp; + + aStartupInfo.hStdInput = hInputRead; + } + + // Get image path with same name but with .exe extension + + TCHAR szModuleFileName[MAX_PATH]; + + GetModuleFileName( NULL, szModuleFileName, MAX_PATH ); + _TCHAR *lpLastDot = _tcsrchr( szModuleFileName, '.' ); + if ( lpLastDot && 0 == _tcsicmp( lpLastDot, _T(".COM") ) ) + { + size_t len = lpLastDot - szModuleFileName; + _tcsncpy( szTargetFileName, szModuleFileName, len ); + _tcsncpy( szTargetFileName + len, _T(".EXE"), SAL_N_ELEMENTS(szTargetFileName) - len ); + } + + // Create process with same command line, environment and stdio handles which + // are directed to the created pipes + + BOOL fSuccess = CreateProcess( + szTargetFileName, + GetCommandLine(), + NULL, + NULL, + TRUE, + 0, + NULL, + NULL, + &aStartupInfo, + &aProcessInfo ); + + if ( fSuccess ) + { + // These pipe ends are inherited by the child process and no longer used + CloseHandle( hOutputWrite ); + CloseHandle( hErrorWrite ); + CloseHandle( hInputRead ); + + // Set the Ctrl-Break handler + hTargetProcess = aProcessInfo.hProcess; + SetConsoleCtrlHandler( CtrlBreakHandler, TRUE ); + + // Create threads that redirect remote pipe io to current process's console stdio + + DWORD dwOutputThreadId, dwErrorThreadId, dwInputThreadId; + + HANDLE hOutputThread = CreateThread( NULL, 0, OutputThread, (LPVOID)hOutputRead, 0, &dwOutputThreadId ); + HANDLE hErrorThread = CreateThread( NULL, 0, OutputThread, (LPVOID)hErrorRead, 0, &dwErrorThreadId ); + HANDLE hInputThread = CreateThread( NULL, 0, InputThread, (LPVOID)hInputWrite, 0, &dwInputThreadId ); + + // Create thread that wait until child process entered input idle + + DWORD dwWaitForUIThreadId; + HANDLE hWaitForUIThread = CreateThread( NULL, 0, WaitForUIThread, (LPVOID)aProcessInfo.hProcess, 0, &dwWaitForUIThreadId ); + + DWORD dwWaitResult; + HANDLE hObjects[] = + { + hTargetProcess, + hWaitForUIThread, + hOutputThread, + hErrorThread + }; + + #ifdef UNOPKG + dwWaitResult = WaitForMultipleObjects( SAL_N_ELEMENTS(hObjects), hObjects, TRUE, INFINITE ); + #else + bool bDetach = false; + int nOpenPipes = 2; + do + { + dwWaitResult = WaitForMultipleObjects( SAL_N_ELEMENTS(hObjects), hObjects, FALSE, INFINITE ); + + switch ( dwWaitResult ) + { + case WAIT_OBJECT_0: // The child process has terminated + case WAIT_OBJECT_0 + 1: // The child process entered input idle + bDetach = true; + break; + case WAIT_OBJECT_0 + 2: // The remote end of stdout pipe was closed + case WAIT_OBJECT_0 + 3: // The remote end of stderr pipe was closed + bDetach = --nOpenPipes <= 0; + break; + default: // Something went wrong + bDetach = true; + break; + } + } while( !bDetach ); + +#endif + + CloseHandle( hOutputThread ); + CloseHandle( hErrorThread ); + CloseHandle( hInputThread ); + CloseHandle( hWaitForUIThread ); + + DWORD dwExitCode = 0; + GetExitCodeProcess( aProcessInfo.hProcess, &dwExitCode ); + CloseHandle( aProcessInfo.hProcess ); + CloseHandle( aProcessInfo.hThread ); + + return dwExitCode; + } + + return -1; +} diff --git a/desktop/win32/source/guistdio/makefile.mk b/desktop/win32/source/guistdio/makefile.mk new file mode 100644 index 000000000000..660a48bcdca9 --- /dev/null +++ b/desktop/win32/source/guistdio/makefile.mk @@ -0,0 +1,58 @@ +#************************************************************************* +# +# 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=guistdio +LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE +TARGETTYPE=CUI +UWINAPILIB= + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +CFLAGS+= $(LFS_CFLAGS) +CXXFLAGS+= $(LFS_CFLAGS) + +# --- Files -------------------------------------------------------- + +OBJFILES=$(APP1OBJS) $(APP2OBJS) + +APP1NOSAL=TRUE +APP1OBJS=$(OBJ)$/guistdio.obj +APP1TARGET=$(TARGET) + +APP2NOSAL=TRUE +APP2OBJS=$(OBJ)$/unopkgio.obj +APP2TARGET=unopkgio + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/desktop/win32/source/guistdio/unopkgio.cxx b/desktop/win32/source/guistdio/unopkgio.cxx new file mode 100644 index 000000000000..af99179c5f61 --- /dev/null +++ b/desktop/win32/source/guistdio/unopkgio.cxx @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "precompiled_desktop.hxx" + +#define UNOPKG +#include "guistdio.inc" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/lwrapa.cxx b/desktop/win32/source/lwrapa.cxx new file mode 100644 index 000000000000..11e4b9e400aa --- /dev/null +++ b/desktop/win32/source/lwrapa.cxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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" +#define LOCAL +#include "wrapper.h" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/lwrapw.cxx b/desktop/win32/source/lwrapw.cxx new file mode 100644 index 000000000000..6a9b72ca3038 --- /dev/null +++ b/desktop/win32/source/lwrapw.cxx @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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" +#define LOCAL +#define UNICODE +#include "wrapper.h" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/main.h b/desktop/win32/source/main.h new file mode 100644 index 000000000000..9e72fb9c3e03 --- /dev/null +++ b/desktop/win32/source/main.h @@ -0,0 +1,15 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +int MainA(); +int MainW(); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/makefile.mk b/desktop/win32/source/makefile.mk new file mode 100644 index 000000000000..564ba319eb56 --- /dev/null +++ b/desktop/win32/source/makefile.mk @@ -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. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=desktop +TARGET=sowrap +LIBTARGET=NO +AUTOSEG=true + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +UWINAPILIB = + +# --- Files -------------------------------------------------------- + +OBJFILES = \ + $(OBJ)$/wrappera.obj \ + $(OBJ)$/wrapperw.obj \ + $(OBJ)$/lwrapa.obj \ + $(OBJ)$/lwrapw.obj \ + $(OBJ)$/rwrapa.obj \ + $(OBJ)$/rwrapw.obj \ + $(OBJ)$/sowrapper.obj \ + $(OBJ)$/extendloaderenvironment.obj \ + $(OBJ)$/unoinfo.obj + +APP1TARGET = unoinfo +APP1OBJS = $(OBJ)$/unoinfo.obj $(SOLARLIBDIR)$/pathutils-obj.obj +APP1STDLIBS = +APP1RPATH = BRAND + +# --- Targets ------------------------------------------------------ + + +.INCLUDE : target.mk + diff --git a/desktop/win32/source/officeloader/makefile.mk b/desktop/win32/source/officeloader/makefile.mk new file mode 100644 index 000000000000..10758727b743 --- /dev/null +++ b/desktop/win32/source/officeloader/makefile.mk @@ -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. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=desktop +TARGET=officeloader +LIBTARGET=NO +#TARGETTYPE=GUI + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +OBJFILES = \ + $(OBJ)$/officeloader.obj + +#APP1TARGET=so$/officeloader +#APP1NOSAL=TRUE +#APP1LINKRES=$(MISC)$/$(TARGET).res +#APP1ICON=$(SOLARRESDIR)$/icons/001_star_main.ico +#APP1OBJS = \ +# $(OBJ)$/officeloader.obj + +#APP2TARGET=officeloader +#APP2NOSAL=TRUE +#APP2LINKRES=$(MISC)$/$(TARGET).res +#APP2ICON=$(SOLARRESDIR)$/icons/ooo_gulls.ico +#APP2OBJS = \ +# $(OBJ)$/officeloader.obj + + +# --- Targets ------------------------------------------------------ + + +.INCLUDE : target.mk + diff --git a/desktop/win32/source/officeloader/officeloader.cxx b/desktop/win32/source/officeloader/officeloader.cxx new file mode 100644 index 000000000000..cce56b05a670 --- /dev/null +++ b/desktop/win32/source/officeloader/officeloader.cxx @@ -0,0 +1,428 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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" +#define UNICODE +#define _UNICODE + +#include <cstddef> + +#define WIN32_LEAN_AND_MEAN +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#include <shellapi.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#include <tchar.h> + +#include <malloc.h> +#include <string.h> +#include <stdlib.h> +#include <systools/win32/uwinapi.h> + +#include "rtl/string.h" +#include <sal/macros.h> + +#include "../../../source/inc/exithelper.hxx" +#include "../extendloaderenvironment.hxx" + +#define PIPE_PREFIX TEXT("\\\\.\\pipe\\OSL_PIPE_") +#define PIPE_POSTFIX TEXT("_SingleOfficeIPC_") +#define PIPE_TERMINATION_SEQUENCE "InternalIPC::ProcessingDone" + +BOOL WINAPI ConvertSidToStringSid( PSID pSid, LPTSTR* StringSid ) +{ + PSID_IDENTIFIER_AUTHORITY psia; + DWORD dwSubAuthorities; + DWORD dwSidRev=SID_REVISION; + DWORD dwCounter; + DWORD dwSidSize; + + // Validate the binary SID. + + if(!IsValidSid(pSid)) return FALSE; + + // Get the identifier authority value from the SID. + + psia = GetSidIdentifierAuthority(pSid); + + // Get the number of subauthorities in the SID. + + dwSubAuthorities = *GetSidSubAuthorityCount(pSid); + + // Compute the buffer length. + // S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL + + dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR); + + *StringSid = (LPTSTR)LocalAlloc( LMEM_FIXED, dwSidSize ); + + // Add 'S' prefix and revision number to the string. + + dwSidSize=wsprintf(*StringSid, TEXT("S-%lu-"), dwSidRev ); + + // Add a SID identifier authority to the string. + + if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) ) + { + dwSidSize+=wsprintf(*StringSid + lstrlen(*StringSid), + TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"), + (USHORT)psia->Value[0], + (USHORT)psia->Value[1], + (USHORT)psia->Value[2], + (USHORT)psia->Value[3], + (USHORT)psia->Value[4], + (USHORT)psia->Value[5]); + } + else + { + dwSidSize+=wsprintf(*StringSid + lstrlen(*StringSid), + TEXT("%lu"), + (ULONG)(psia->Value[5] ) + + (ULONG)(psia->Value[4] << 8) + + (ULONG)(psia->Value[3] << 16) + + (ULONG)(psia->Value[2] << 24) ); + } + + // Add SID subauthorities to the string. + // + for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++) + { + dwSidSize+=wsprintf(*StringSid + dwSidSize, TEXT("-%lu"), + *GetSidSubAuthority(pSid, dwCounter) ); + } + + return TRUE; +} + + +//--------------------------------------------------------------------------- + +static LPTSTR *GetCommandArgs( int *pArgc ) +{ +#ifdef UNICODE + return CommandLineToArgvW( GetCommandLineW(), pArgc ); +#else + *pArgc = __argc; + return __argv; +#endif +} + +//--------------------------------------------------------------------------- + +namespace { + +bool writeArgument(HANDLE pipe, char prefix, WCHAR const * argument) { + CHAR szBuffer[4096]; + int n = WideCharToMultiByte( + CP_UTF8, 0, argument, -1, szBuffer, sizeof (szBuffer), NULL, NULL); + char b[1 + 2 * ((sizeof szBuffer) - 1)]; // hopefully does not overflow + b[0] = prefix; + char * p = b + 1; + for (int i = 0; i < n - 1; ++i) { // cannot underflow (n >= 0) + char c = szBuffer[i]; + switch (c) { + case '\0': + *p++ = '\\'; + *p++ = '0'; + break; + case ',': + *p++ = '\\'; + *p++ = ','; + break; + case '\\': + *p++ = '\\'; + *p++ = '\\'; + break; + default: + *p++ = c; + break; + } + } + DWORD w; + return WriteFile(pipe, b, p - b, &w, NULL); +} + +} + +#ifdef __MINGW32__ +int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int ) +#else +int WINAPI _tWinMain( HINSTANCE, HINSTANCE, LPTSTR, int ) +#endif +{ + TCHAR szTargetFileName[MAX_PATH] = TEXT(""); + TCHAR szIniDirectory[MAX_PATH]; + TCHAR szPerfTuneIniFile[MAX_PATH] = TEXT(""); + STARTUPINFO aStartupInfo; + + desktop_win32::extendLoaderEnvironment(szTargetFileName, szIniDirectory); + + ZeroMemory( &aStartupInfo, sizeof(aStartupInfo) ); + aStartupInfo.cb = sizeof(aStartupInfo); + + GetStartupInfo( &aStartupInfo ); + // Get image path with same name but with .bin extension + + TCHAR szModuleFileName[MAX_PATH]; + + GetModuleFileName( NULL, szModuleFileName, MAX_PATH ); + _TCHAR *lpLastSlash = _tcsrchr( szModuleFileName, '\\' ); + if ( lpLastSlash ) + { + size_t len = lpLastSlash - szModuleFileName + 1; + _tcsncpy( szPerfTuneIniFile, szModuleFileName, len ); + _tcsncpy( szPerfTuneIniFile + len, _T("perftune.ini"), SAL_N_ELEMENTS(szPerfTuneIniFile) - len ); + } + + // Create process with same command line, environment and stdio handles which + // are directed to the created pipes + + DWORD dwExitCode = (DWORD)-1; + + BOOL fSuccess = FALSE; + LPTSTR lpCommandLine = NULL; + int argc = 0; + LPTSTR * argv = NULL; + bool bFirst = true; + WCHAR cwd[MAX_PATH]; + DWORD cwdLen = GetCurrentDirectoryW(MAX_PATH, cwd); + if (cwdLen >= MAX_PATH) { + cwdLen = 0; + } + + do + { + TCHAR szKey[32]; + + GetPrivateProfileString( + TEXT("PerformanceTuning"), + TEXT("FastPipeCommunication"), + TEXT("0"), + szKey, + SAL_N_ELEMENTS(szKey), + szPerfTuneIniFile + ); + + if ( 0 == _tcscmp( szKey, TEXT("1") ) ) + { + HANDLE hProcessToken; + + if ( OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hProcessToken ) ) + { + TCHAR szPipeName[4096]; + + + DWORD dwTokenLength = 0; + + + fSuccess = GetTokenInformation( hProcessToken, TokenUser, NULL, dwTokenLength, &dwTokenLength ); + + PVOID pTokenInfo = _alloca(dwTokenLength); + fSuccess = GetTokenInformation( hProcessToken, TokenUser, pTokenInfo, dwTokenLength, &dwTokenLength ); + CloseHandle( hProcessToken ); + + PSID pSid = ((PTOKEN_USER)pTokenInfo)->User.Sid; + LPTSTR szUserIdent = NULL; + TCHAR szSUPD[11] = TEXT("0"); + + fSuccess = ConvertSidToStringSid( pSid, &szUserIdent ); + + _tcsncpy( szPipeName, PIPE_PREFIX, SAL_N_ELEMENTS(szPipeName) ); + _tcsncat( szPipeName, szUserIdent, SAL_N_ELEMENTS(szPipeName) - _tcslen(szPipeName) - 1 ); + _tcsncat( szPipeName, PIPE_POSTFIX, SAL_N_ELEMENTS(szPipeName) - _tcslen(szPipeName) - 1 ); + _tcsncat( szPipeName, _ultot( SUPD, szSUPD, 10), SAL_N_ELEMENTS(szPipeName) - _tcslen(szPipeName) - 1 ); + + LocalFree( szUserIdent ); + + HANDLE hPipe = CreateFile( + szPipeName, + GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if ( INVALID_HANDLE_VALUE != hPipe ) + { + DWORD dwBytesWritten; + int argc = 0; + LPWSTR *argv = CommandLineToArgvW( GetCommandLine(), &argc ); + + fSuccess = WriteFile( hPipe, RTL_CONSTASCII_STRINGPARAM("InternalIPC::Arguments"), &dwBytesWritten, NULL ); + if (fSuccess) { + if (cwdLen > 0) { + fSuccess = writeArgument(hPipe, '2', cwd); + } else { + fSuccess = WriteFile( + hPipe, RTL_CONSTASCII_STRINGPARAM("0"), + &dwBytesWritten, NULL); + } + } + for ( int argn = 1; fSuccess && argn < argc; argn++ ) + { + fSuccess = writeArgument(hPipe, ',', argv[argn]); + } + + if ( fSuccess ) + { + fSuccess = WriteFile( hPipe, "", 1, &dwBytesWritten, NULL ); + if ( fSuccess ) + { + DWORD dwBytesRead = 0; + char *pBuffer = (char *)_alloca( sizeof(PIPE_TERMINATION_SEQUENCE) ); + fSuccess = ReadFile( hPipe, pBuffer, sizeof(PIPE_TERMINATION_SEQUENCE) - 1, &dwBytesRead, NULL ); + if ( fSuccess ) + { + pBuffer[dwBytesRead] = 0; + if ( 0 != strcmp( PIPE_TERMINATION_SEQUENCE, pBuffer ) ) + fSuccess = FALSE; + } + } + } + + CloseHandle( hPipe ); + + return fSuccess ? 0 : -1; + } + + } + } + + if ( bFirst ) { + argv = GetCommandArgs(&argc); + std::size_t n = wcslen(argv[0]) + 2; + for (int i = 1; i < argc; ++i) { + n += wcslen(argv[i]) + 3; + } + n += MY_LENGTH(L" \"-env:OOO_CWD=2") + 4 * cwdLen + + MY_LENGTH(L"\"") + 1; + // 4 * cwdLen: each char preceded by backslash, each trailing + // backslash doubled + lpCommandLine = new WCHAR[n]; + } + WCHAR * p = desktop_win32::commandLineAppend( + lpCommandLine, MY_STRING(L"\"")); + p = desktop_win32::commandLineAppend(p, argv[0]); + for (int i = 1; i < argc; ++i) { + if (bFirst || ::desktop::ExitHelper::E_NORMAL_RESTART == dwExitCode || wcsncmp(argv[i], MY_STRING(L"-env:")) == 0) { + p = desktop_win32::commandLineAppend(p, MY_STRING(L"\" \"")); + p = desktop_win32::commandLineAppend(p, argv[i]); + } + } + + p = desktop_win32::commandLineAppend( + p, MY_STRING(L"\" \"-env:OOO_CWD=")); + if (cwdLen == 0) { + p = desktop_win32::commandLineAppend(p, MY_STRING(L"0")); + } else { + p = desktop_win32::commandLineAppend(p, MY_STRING(L"2")); + p = desktop_win32::commandLineAppendEncoded(p, cwd); + } + desktop_win32::commandLineAppend(p, MY_STRING(L"\"")); + bFirst = false; + + TCHAR szParentProcessId[64]; // This is more than large enough for a 128 bit decimal value + BOOL bHeadlessMode( FALSE ); + + { + // Check command line arguments for "-headless" parameter. We only + // set the environment variable "ATTACHED_PARENT_PROCESSID" for the headless + // mode as self-destruction of the soffice.bin process can lead to + // certain side-effects (log-off can result in data-loss, ".lock" is not deleted. + // See 138244 for more information. + int argc; + LPTSTR *argv = GetCommandArgs( &argc ); + + if ( argc > 1 ) + { + int n; + + for ( n = 1; n < argc; n++ ) + { + if ( 0 == _tcsnicmp( argv[n], _T("-headless"), 9 ) ) + bHeadlessMode = TRUE; + } + } + } + + if ( _ltot( (long)GetCurrentProcessId(),szParentProcessId, 10 ) && bHeadlessMode ) + SetEnvironmentVariable( TEXT("ATTACHED_PARENT_PROCESSID"), szParentProcessId ); + + PROCESS_INFORMATION aProcessInfo; + + fSuccess = CreateProcess( + szTargetFileName, + lpCommandLine, + NULL, + NULL, + TRUE, + 0, + NULL, + szIniDirectory, + &aStartupInfo, + &aProcessInfo ); + + if ( fSuccess ) + { + DWORD dwWaitResult; + + do + { + // On Windows XP it seems as the desktop calls WaitForInputIdle after "OpenWidth" so we have to do so + // as if we where processing any messages + + dwWaitResult = MsgWaitForMultipleObjects( 1, &aProcessInfo.hProcess, FALSE, INFINITE, QS_ALLEVENTS ); + + if ( WAIT_OBJECT_0 + 1 == dwWaitResult ) + { + MSG msg; + + PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ); + } + } while ( WAIT_OBJECT_0 + 1 == dwWaitResult ); + + dwExitCode = 0; + GetExitCodeProcess( aProcessInfo.hProcess, &dwExitCode ); + + CloseHandle( aProcessInfo.hProcess ); + CloseHandle( aProcessInfo.hThread ); + } + } while ( false ); + delete[] lpCommandLine; + + return fSuccess ? dwExitCode : -1; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/rebase/Resource.h b/desktop/win32/source/rebase/Resource.h new file mode 100644 index 000000000000..8c892111c995 --- /dev/null +++ b/desktop/win32/source/rebase/Resource.h @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 _RESOURCE_H +#define _RESOURCE_H + +#define IDS_APP_TITLE 10 +#define IDS_MSG_OPTIMIZED_FOR_CLIENT 11 +#define IDS_MSG_OPTIMIZED_FOR_SERVER 12 +#define IDS_MSG_NO_INSTALLATION_FOUND 13 + +#define IDI_REBASEGUI 99 + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/rebase/makefile.mk b/desktop/win32/source/rebase/makefile.mk new file mode 100644 index 000000000000..724ea0edf465 --- /dev/null +++ b/desktop/win32/source/rebase/makefile.mk @@ -0,0 +1,89 @@ +#************************************************************************* +# +# 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=rebasegui +LIBTARGET=NO +TARGETTYPE=GUI +UWINAPILIB= + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +OBJFILES = \ + $(OBJ)$/rebase.obj \ + $(OBJ)$/rebasegui.obj + +ULFFILES= rebasegui.ulf + +.IF "$(WITH_LANG)"!="" +ULFDIR:=$(COMMONMISC)$/$(TARGET) +.ELSE # "$(WITH_LANG)"!="" +ULFDIR:=. +.ENDIF # "$(WITH_LANG)"!="" + +RCFILES= $(RES)$/$(TARGET).rc + +# --- Targets ------------------------------------------------------ + +APP1NOSAL= TRUE +APP1TARGET= rebaseoo + +APP1STDLIBS= $(SHELL32LIB) $(SOLARLIBDIR)$/pathutils-obj.obj +.IF "$(COM)"=="GCC" + APP1STDLIBS+=$(PSDK_HOME)$/lib$/imagehlp.lib +.ELSE + APP1STDLIBS+=imagehlp.lib +.ENDIF + +APP1OBJS= $(OBJ)$/rebase.obj + +APP1RPATH= BRAND + +APP2NOSAL= TRUE +APP2TARGET= rebasegui +APP2STDLIBS= $(SHELL32LIB) $(SOLARLIBDIR)$/pathutils-obj.obj + +APP2OBJS= $(OBJ)$/rebasegui.obj + +APP2DEF= $(MISC)$/$(TARGET).def +APP2RPATH= BRAND + +APP2RES= $(RES)$/$(TARGET).res +APP2NOSVRES= $(RES)$/$(TARGET).res + +# --- setup -------------------------------------------------------------- + +.INCLUDE : target.mk + +$(RCFILES) : $(ULFDIR)$/rebasegui.ulf makefile.mk rcfooter.txt rcheader.txt rctmpl.txt + $(LNGCONVEX) -ulf $(ULFDIR)$/rebasegui.ulf -rc $(RCFILES) -rct rctmpl.txt -rch rcheader.txt -rcf rcfooter.txt diff --git a/desktop/win32/source/rebase/rcfooter.txt b/desktop/win32/source/rebase/rcfooter.txt new file mode 100644 index 000000000000..3237729437f5 --- /dev/null +++ b/desktop/win32/source/rebase/rcfooter.txt @@ -0,0 +1,2 @@ + +// The end diff --git a/desktop/win32/source/rebase/rcheader.txt b/desktop/win32/source/rebase/rcheader.txt new file mode 100644 index 000000000000..56afc5377920 --- /dev/null +++ b/desktop/win32/source/rebase/rcheader.txt @@ -0,0 +1,39 @@ +#if defined(_MSC_VER) && (_MSC_VER < 1500) +#include <winres.h> +#else +#define WINVER 0x0500 +#include <winresrc.h> +#define IDC_STATIC (-1) +#endif +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,1,1,0 + PRODUCTVERSION 1,1,1,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x9L +#else + FILEFLAGS 0x8L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + diff --git a/desktop/win32/source/rebase/rctmpl.txt b/desktop/win32/source/rebase/rctmpl.txt new file mode 100644 index 000000000000..97a2775e9b02 --- /dev/null +++ b/desktop/win32/source/rebase/rctmpl.txt @@ -0,0 +1,9 @@ +// String Table + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APP_TITLE %APP_TITLE% + IDS_MSG_OPTIMIZED_FOR_CLIENT %MSG_OPTIMIZED_FOR_CLIENT% + IDS_MSG_OPTIMIZED_FOR_SERVER %MSG_OPTIMIZED_FOR_SERVER% + IDS_MSG_NO_INSTALLATION_FOUND %MSG_NO_INSTALLATION_FOUND% +END diff --git a/desktop/win32/source/rebase/rebase.cxx b/desktop/win32/source/rebase/rebase.cxx new file mode 100644 index 000000000000..e712c8d548e5 --- /dev/null +++ b/desktop/win32/source/rebase/rebase.cxx @@ -0,0 +1,191 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "precompiled_desktop.hxx" +#define UNICODE +#define _UNICODE + +#define WIN32_LEAN_AND_MEAN +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#include <shellapi.h> +#include <imagehlp.h> +#include <wchar.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#include <time.h> +#include "sal/config.h" +#include <sal/macros.h> +#include "tools/pathutils.hxx" + +#define MY_LENGTH(s) (sizeof (s) / sizeof *(s) - 1) +#define MY_STRING(s) (s), MY_LENGTH(s) + +const int FORMAT_MESSAGE_SIZE = 4096; +const DWORD PE_Signature = 0x00004550; +const DWORD BASEVIRTUALADDRESS = 0x10000000; + +namespace +{ + +bool IsValidHandle( HANDLE handle ) +{ + return ((NULL != handle) && (INVALID_HANDLE_VALUE != handle)); +} + +void fail() +{ + LPWSTR buf = NULL; + FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, + GetLastError(), 0, reinterpret_cast< LPWSTR >(&buf), 0, NULL); + MessageBoxW(NULL, buf, NULL, MB_OK | MB_ICONERROR); + LocalFree(buf); + TerminateProcess(GetCurrentProcess(), 255); +} + +bool rebaseImage( wchar_t* pszFilePath, ULONG nNewImageBase) +{ + ULONG ulOldImageSize; + ULONG_PTR lpOldImageBase; + ULONG ulNewImageSize; + ULONG_PTR lpNewImageBase = nNewImageBase; + ULONG ulDateTimeStamp = 0; + bool bResult(false); + + char cszFilePath[_MAX_PATH+1] = {0}; + int nResult = WideCharToMultiByte(CP_ACP, 0, pszFilePath, -1, cszFilePath, _MAX_PATH, NULL, NULL); + + if (nResult != 0) + { + BOOL bResult = ReBaseImage( + cszFilePath, + "", + TRUE, + FALSE, + FALSE, + 0, + &ulOldImageSize, + &lpOldImageBase, + &ulNewImageSize, + &lpNewImageBase, + ulDateTimeStamp ); + } + + return bResult; +} + +wchar_t* getBrandPath(wchar_t * path) +{ + DWORD n = GetModuleFileNameW(NULL, path, MAX_PATH); + if (n == 0 || n >= MAX_PATH) { + exit(EXIT_FAILURE); + } + return tools::filename(path); +} + +void rebaseImagesInFolder( wchar_t* pszFolder, DWORD nNewImageBase ) +{ + wchar_t szPattern[MAX_PATH]; + wchar_t *lpLastSlash = wcsrchr( pszFolder, '\\' ); + if ( lpLastSlash ) + { + size_t len = lpLastSlash - pszFolder + 1; + wcsncpy( szPattern, pszFolder, len ); + wcsncpy( szPattern + len, TEXT("*.dll"), SAL_N_ELEMENTS(szPattern) - len ); + } + + WIN32_FIND_DATA aFindFileData; + HANDLE hFind = FindFirstFile( szPattern, &aFindFileData ); + + if ( IsValidHandle(hFind) ) + { + BOOL fSuccess = false; + + do + { + wchar_t szLibFilePath[MAX_PATH]; + wchar_t *lpLastSlash = wcsrchr( pszFolder, '\\' ); + if ( lpLastSlash ) + { + size_t len = lpLastSlash - pszFolder + 1; + wcsncpy( szLibFilePath, pszFolder, len ); + wcsncpy( szLibFilePath + len, aFindFileData.cFileName, SAL_N_ELEMENTS(szLibFilePath) - len ); + } + + rebaseImage( szLibFilePath, nNewImageBase ); + fSuccess = FindNextFile( hFind, &aFindFileData ); + } + while ( fSuccess ); + + FindClose( hFind ); + } +} + +} + +extern "C" int APIENTRY WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) +{ + wchar_t path[MAX_PATH]; + + wchar_t * pathEnd = getBrandPath(path); + + if (tools::buildPath(path, path, pathEnd, MY_STRING(L"")) == NULL) + fail(); + rebaseImagesInFolder(path, BASEVIRTUALADDRESS); + + if (tools::buildPath(path, path, pathEnd, MY_STRING(L"..\\basis-link")) == NULL) + fail(); + pathEnd = tools::resolveLink(path); + + if ( pathEnd == NULL ) + return 0; + + if (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\program\\")) == NULL) + fail(); + rebaseImagesInFolder(path, BASEVIRTUALADDRESS); + + if (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\ure-link")) == NULL) + fail(); + pathEnd = tools::resolveLink(path); + + if ( pathEnd == NULL ) + return 0; + + if (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\bin\\")) == NULL) + fail(); + rebaseImagesInFolder(path, BASEVIRTUALADDRESS); + + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/rebase/rebasegui.cxx b/desktop/win32/source/rebase/rebasegui.cxx new file mode 100644 index 000000000000..e1bb148c2b56 --- /dev/null +++ b/desktop/win32/source/rebase/rebasegui.cxx @@ -0,0 +1,200 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "precompiled_desktop.hxx" + +#define UNICODE 1 +#define _UNICODE 1 + +#ifndef _WINDOWS_ +# define WIN32_LEAN_AND_MEAN +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +# include <windows.h> +# include <shellapi.h> +# include <wchar.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#endif + +#include "Resource.h" +#include <time.h> +#include "sal/config.h" +#include "tools/pathutils.hxx" + +const DWORD PE_Signature = 0x00004550; + +#define MY_LENGTH(s) (sizeof (s) / sizeof *(s) - 1) +#define MY_STRING(s) (s), MY_LENGTH(s) +#define MAX_STR_CAPTION 256 +#define MAX_TEXT_LENGTH 1024 + +static void failPath(wchar_t* pszAppTitle, wchar_t* pszMsg) +{ + MessageBoxW(NULL, pszMsg, pszAppTitle, MB_OK | MB_ICONERROR); + TerminateProcess(GetCurrentProcess(), 255); +} + +static void fail() +{ + LPWSTR buf = NULL; + FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, + GetLastError(), 0, reinterpret_cast< LPWSTR >(&buf), 0, NULL); + MessageBoxW(NULL, buf, NULL, MB_OK | MB_ICONERROR); + LocalFree(buf); + TerminateProcess(GetCurrentProcess(), 255); +} + +static LPVOID getVirtualBaseAddress( wchar_t* pszFilePath ) +{ + HANDLE hFile; + HANDLE hFileMapping; + LPVOID lpFileBase = 0; + PIMAGE_DOS_HEADER lpDosHeader; + PIMAGE_NT_HEADERS lpNTHeader; + + hFile = CreateFile(pszFilePath, + GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, + 0); + + if ( hFile == INVALID_HANDLE_VALUE ) + { + return NULL; + } + + hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + if ( hFileMapping == 0 ) + { + CloseHandle(hFile); + return NULL; + } + + lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0); + if ( lpFileBase == 0 ) + { + CloseHandle(hFileMapping); + CloseHandle(hFile); + return NULL; + } + + lpDosHeader = (PIMAGE_DOS_HEADER)lpFileBase; + if ( lpDosHeader->e_magic == IMAGE_DOS_SIGNATURE ) + { + lpNTHeader = (PIMAGE_NT_HEADERS)((char*)lpDosHeader + lpDosHeader->e_lfanew); + if (lpNTHeader->Signature == PE_Signature ) + lpFileBase = reinterpret_cast<LPVOID>( lpNTHeader->OptionalHeader.ImageBase ); + } + + UnmapViewOfFile(lpFileBase); + CloseHandle(hFileMapping); + CloseHandle(hFile); + + return lpFileBase; +} + +static bool checkImageVirtualBaseAddress(wchar_t* pszFilePath, LPVOID lpVBA) +{ + LPVOID lpImageVBA = getVirtualBaseAddress(pszFilePath); + if ( lpImageVBA == lpVBA ) + return true; + else + return false; +} + +static wchar_t* getBrandPath(wchar_t * pszPath) +{ + DWORD n = GetModuleFileNameW(NULL, pszPath, MAX_PATH); + if (n == 0 || n >= MAX_PATH) { + exit(EXIT_FAILURE); + } + return tools::filename(pszPath); +} + +extern "C" int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int ) +{ + wchar_t* pAppTitle = new wchar_t[ MAX_STR_CAPTION ]; + pAppTitle[0] = '\0'; + LoadString( hInst, IDS_APP_TITLE, pAppTitle, MAX_STR_CAPTION ); + + wchar_t* pTextServer = new wchar_t[ MAX_TEXT_LENGTH ]; + pTextServer[0] = '\0'; + LoadString( hInst, IDS_MSG_OPTIMIZED_FOR_SERVER, pTextServer, MAX_TEXT_LENGTH ); + + wchar_t* pTextClient = new wchar_t[ MAX_TEXT_LENGTH ]; + pTextClient[0] = '\0'; + LoadString( hInst, IDS_MSG_OPTIMIZED_FOR_CLIENT, pTextClient, MAX_TEXT_LENGTH ); + + wchar_t* pTextNoInstallation = new wchar_t[ MAX_TEXT_LENGTH ]; + pTextNoInstallation[0] = '\0'; + LoadString( hInst, IDS_MSG_NO_INSTALLATION_FOUND, pTextNoInstallation, MAX_TEXT_LENGTH ); + + LPVOID VBA = (void*)0x10000000; + wchar_t path[MAX_PATH]; + + wchar_t * pathEnd = getBrandPath(path); + + if (tools::buildPath(path, path, pathEnd, MY_STRING(L"libxml2.dll")) == NULL) + fail(); + bool bFast = checkImageVirtualBaseAddress(path, VBA); + + if (tools::buildPath(path, path, pathEnd, MY_STRING(L"..\\basis-link")) == NULL) + fail(); + pathEnd = tools::resolveLink(path); + + if (pathEnd == NULL) + failPath(pAppTitle, pTextNoInstallation); + + if (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\program\\vclmi.dll")) == NULL) + fail(); + bFast &= checkImageVirtualBaseAddress(path, VBA); + + if (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\ure-link")) == NULL) + fail(); + pathEnd = tools::resolveLink(path); + + if (pathEnd == NULL) + failPath(pAppTitle, pTextNoInstallation); + + if (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\bin\\sal3.dll")) == NULL) + fail(); + bFast &= checkImageVirtualBaseAddress(path, VBA); + + const wchar_t* pOutput = pTextClient; + if (!bFast) + pOutput = pTextServer; + + MessageBoxW( NULL, pOutput, pAppTitle, MB_OK ); + + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/rebase/rebasegui.ulf b/desktop/win32/source/rebase/rebasegui.ulf new file mode 100644 index 000000000000..ee6b6e828ac1 --- /dev/null +++ b/desktop/win32/source/rebase/rebasegui.ulf @@ -0,0 +1,11 @@ +[%APP_TITLE%] +en-US = "Installation Status" + +[%MSG_OPTIMIZED_FOR_CLIENT%] +en-US = "Installation is optimized for clients." + +[%MSG_OPTIMIZED_FOR_SERVER%] +en-US = "Installation is optimized for servers." + +[%MSG_NO_INSTALLATION_FOUND%] +en-US = "Cannot find Office installation." diff --git a/desktop/win32/source/rwrapa.cxx b/desktop/win32/source/rwrapa.cxx new file mode 100644 index 000000000000..4d1f599f016b --- /dev/null +++ b/desktop/win32/source/rwrapa.cxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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" +#define REMOTE +#include "wrapper.h" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/rwrapw.cxx b/desktop/win32/source/rwrapw.cxx new file mode 100644 index 000000000000..d4912990e440 --- /dev/null +++ b/desktop/win32/source/rwrapw.cxx @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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" +#define REMOTE +#define UNICODE +#include "wrapper.h" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/setup/Resource.h b/desktop/win32/source/setup/Resource.h new file mode 100644 index 000000000000..2f075004d68c --- /dev/null +++ b/desktop/win32/source/setup/Resource.h @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 _RESOURCE_H +#define _RESOURCE_H + +#define IDS_APP_TITLE 10 +#define IDS_APP_PROD_TITLE 11 +#define IDS_OUTOFMEM 12 +#define IDS_NOMSI 13 +#define IDS_USER_CANCELLED 14 +#define IDS_REQUIRES_ADMIN_PRIV 15 +#define IDS_FILE_NOT_FOUND 16 +#define IDS_INVALID_PARAM 17 +#define IDS_ALLOW_MSI_UPDATE 18 +#define IDS_USAGE 19 +#define IDS_ALREADY_RUNNING 20 +#define IDS_UNKNOWN_ERROR 21 +#define IDS_INVALID_PROFILE 22 +#define IDS_UNKNOWN_LANG 23 +#define IDS_SETUP_TO_OLD 24 +#define IDS_SETUP_NOT_FOUND 25 +#define IDS_LANGUAGE_ENGLISH 50 +#define IDS_LANGUAGE_SPAIN 51 +#define IDS_LANGUAGE_GERMAN 52 +#define IDS_LANGUAGE_ZH_TW 53 +#define IDS_LANGUAGE_CS 54 +#define IDS_LANGUAGE_DA 55 +#define IDS_LANGUAGE_DE_DE 56 +#define IDS_LANGUAGE_EL 57 +#define IDS_LANGUAGE_EN_US 58 +#define IDS_LANGUAGE_ES 59 +#define IDS_LANGUAGE_FI 60 +#define IDS_LANGUAGE_FR_FR 61 +#define IDS_LANGUAGE_HE 62 +#define IDS_LANGUAGE_HU 63 +#define IDS_LANGUAGE_IT_IT 64 +#define IDS_LANGUAGE_JA 65 +#define IDS_LANGUAGE_KO 66 +#define IDS_LANGUAGE_NL_NL 67 +#define IDS_LANGUAGE_NO_NO 68 +#define IDS_LANGUAGE_PL 69 +#define IDS_LANGUAGE_PT_BR 70 +#define IDS_LANGUAGE_RU 71 +#define IDS_LANGUAGE_SK 72 +#define IDS_LANGUAGE_SV_SE 73 +#define IDS_LANGUAGE_TH 74 +#define IDS_LANGUAGE_TR 75 +#define IDS_LANGUAGE_ET 76 +#define IDS_LANGUAGE_ZH_CN 77 +#define IDS_LANGUAGE_PT_PT 78 + +#define IDI_INSTALLER 99 + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/setup/makefile.mk b/desktop/win32/source/setup/makefile.mk new file mode 100644 index 000000000000..15b7b1937e78 --- /dev/null +++ b/desktop/win32/source/setup/makefile.mk @@ -0,0 +1,90 @@ +#************************************************************************* +# +# 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 = loader2 +LIBTARGET = NO +DYNAMIC_CRT = +TARGETTYPE = GUI + +ENABLE_EXCEPTIONS = TRUE + +# --- Settings ------------------------------------------------------------ + +.INCLUDE : settings.mk + +# --- Allgemein ----------------------------------------------------------- + +INCPRE+=$(MFC_INCLUDE) + +.IF "$(USE_STLP_DEBUG)"!="" +CDEFS+=-D_DEBUG +.ENDIF # "$(USE_STLP_DEBUG)"!="" + +RCFILES= $(RES)$/$(TARGET).rc + +ULFFILES= setup.ulf + +.IF "$(WITH_LANG)"!="" +ULFDIR:=$(COMMONMISC)$/$(TARGET) +.ELSE # "$(WITH_LANG)"!="" +ULFDIR:=. +.ENDIF # "$(WITH_LANG)"!="" + +OBJFILES= $(OBJ)$/setup_main.obj \ + $(OBJ)$/setup_w.obj + +# --- Targets ------------------------------------------------------ +# Generate the native Windows resource file +# using lngconvex.exe + +UWINAPILIB= $(0) +LIBSALCPPRT= $(0) + +APP1NOSAL= TRUE +APP1TARGET= loader2 + +APP1STDLIBS= $(GDI32LIB) $(ADVAPI32LIB) $(SHELL32LIB) $(MSILIB) +.IF "$(COM)"!="GCC" +APP1STDLIBS+= libcmt.lib +.ENDIF +APP1OBJS= $(OBJFILES) + +APP1DEF= $(MISC)$/$(TARGET).def + +APP1RES= $(RES)$/$(TARGET).res +APP1NOSVRES= $(RES)$/$(TARGET).res + +# --- setup -------------------------------------------------------------- + +.INCLUDE : target.mk + +$(RCFILES) : $(ULFDIR)$/setup.ulf makefile.mk rcfooter.txt rcheader.txt rctmpl.txt + $(LNGCONVEX) -ulf $(ULFDIR)$/setup.ulf -rc $(RCFILES) -rct rctmpl.txt -rch rcheader.txt -rcf rcfooter.txt + diff --git a/desktop/win32/source/setup/rcfooter.txt b/desktop/win32/source/setup/rcfooter.txt new file mode 100644 index 000000000000..3237729437f5 --- /dev/null +++ b/desktop/win32/source/setup/rcfooter.txt @@ -0,0 +1,2 @@ + +// The end diff --git a/desktop/win32/source/setup/rcheader.txt b/desktop/win32/source/setup/rcheader.txt new file mode 100644 index 000000000000..9a59ad7f6477 --- /dev/null +++ b/desktop/win32/source/setup/rcheader.txt @@ -0,0 +1,43 @@ +#if defined(_MSC_VER) && (_MSC_VER < 1500) +#include <winres.h> +#else +#define WINVER 0x0500 +#include <winresrc.h> +#define LB_ADDSTRING (WM_USER+1) +#define CB_ADDSTRING (WM_USER+3) +#define IDC_STATIC (-1) +#endif +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,1,1,0 + PRODUCTVERSION 1,1,1,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x9L +#else + FILEFLAGS 0x8L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +IDI_INSTALLER ICON "setup.ico" + diff --git a/desktop/win32/source/setup/rctmpl.txt b/desktop/win32/source/setup/rctmpl.txt new file mode 100644 index 000000000000..59f454f70c16 --- /dev/null +++ b/desktop/win32/source/setup/rctmpl.txt @@ -0,0 +1,49 @@ +// String Table + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APP_TITLE %APP_TITLE% + IDS_APP_PROD_TITLE %APP_PROD_TITLE% + IDS_OUTOFMEM %OUTOFMEM% + IDS_NOMSI %NOMSI% + IDS_USER_CANCELLED %USER_CANCELLED% + IDS_REQUIRES_ADMIN_PRIV %REQUIRES_ADMIN_PRIV% + IDS_FILE_NOT_FOUND %FILE_NOT_FOUND% + IDS_INVALID_PARAM %INVALID_PARAM% + IDS_SETUP_TO_OLD %SETUP_TO_OLD% + IDS_SETUP_NOT_FOUND %SETUP_NOT_FOUND% + IDS_USAGE %USAGE% + IDS_ALREADY_RUNNING %ALREADY_RUNNING% + IDS_UNKNOWN_ERROR %UNKNOWN_ERROR% + IDS_INVALID_PROFILE %INVALID_PROFILE% + IDS_UNKNOWN_LANG %UNKNOWN_LANG% + IDS_LANGUAGE_ENGLISH %LANGUAGE_ENGLISH% + IDS_LANGUAGE_SPAIN %LANGUAGE_SPAIN% + IDS_LANGUAGE_GERMAN %LANGUAGE_GERMAN% + IDS_LANGUAGE_ZH_TW %LANGUAGE_ZH_TW% + IDS_LANGUAGE_CS %LANGUAGE_CS% + IDS_LANGUAGE_DA %LANGUAGE_DA% + IDS_LANGUAGE_DE_DE %LANGUAGE_DE_DE% + IDS_LANGUAGE_EL %LANGUAGE_EL% + IDS_LANGUAGE_EN_US %LANGUAGE_EN_US% + IDS_LANGUAGE_ES %LANGUAGE_ES% + IDS_LANGUAGE_FI %LANGUAGE_FI% + IDS_LANGUAGE_FR_FR %LANGUAGE_FR_FR% + IDS_LANGUAGE_HE %LANGUAGE_HE% + IDS_LANGUAGE_HU %LANGUAGE_HU% + IDS_LANGUAGE_IT_IT %LANGUAGE_IT_IT% + IDS_LANGUAGE_JA %LANGUAGE_JA% + IDS_LANGUAGE_KO %LANGUAGE_KO% + IDS_LANGUAGE_NL_NL %LANGUAGE_NL_NL% + IDS_LANGUAGE_NO_NO %LANGUAGE_NO_NO% + IDS_LANGUAGE_PL %LANGUAGE_PL% + IDS_LANGUAGE_PT_BR %LANGUAGE_PT_BR% + IDS_LANGUAGE_RU %LANGUAGE_RU% + IDS_LANGUAGE_SK %LANGUAGE_SK% + IDS_LANGUAGE_SV_SE %LANGUAGE_SV_SE% + IDS_LANGUAGE_TH %LANGUAGE_TH% + IDS_LANGUAGE_TR %LANGUAGE_TR% + IDS_LANGUAGE_ET %LANGUAGE_ET% + IDS_LANGUAGE_ZH_CN %LANGUAGE_ZH_CN% + IDS_LANGUAGE_PT_PT %LANGUAGE_PT_PT% +END diff --git a/desktop/win32/source/setup/setup.cpp b/desktop/win32/source/setup/setup.cpp new file mode 100644 index 000000000000..69d09a47f647 --- /dev/null +++ b/desktop/win32/source/setup/setup.cpp @@ -0,0 +1,2063 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +#define WIN // scope W32 API +#define _WIN32_WINNT 0x0501 + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#include <tchar.h> +#include <assert.h> +#include <shlwapi.h> +#include <new> +#include <time.h> +#include <mbctype.h> +#include <locale.h> +#include <Msiquery.h> +#include <MsiDefs.h> +#include "strsafe.h" + +#include "setup.hxx" + +#include "resource.h" + +//-------------------------------------------------------------------------- + +#define MAX_STR_LENGTH 32000 +#define MAX_TEXT_LENGTH 1024 +#define MAX_LANGUAGE_LEN 80 +#define MAX_STR_CAPTION 256 +#define VERSION_SIZE 80 +#define SECTION_SETUP TEXT( "Setup" ) +#define SECTION_LANGUAGE TEXT( "Languages" ) +#define PRODUCT_NAME_VAR TEXT( "%PRODUCTNAME" ) +#define PRODUCT_VERSION TEXT( "ProductVersion" ) +#define ERROR_SHOW_USAGE -2 +#define ERROR_SETUP_TO_OLD -3 +#define ERROR_SETUP_NOT_FOUND -4 + +#define PARAM_SETUP_USED TEXT( " SETUP_USED=1 " ) +#define PARAM_PACKAGE TEXT( "/I " ) +#define PARAM_MINOR_UPGRADE TEXT( "/FVOMUS " ) +#define PARAM_ADMIN TEXT( "/A " ) +#define PARAM_TRANSFORM TEXT( " TRANSFORMS=" ) +#define PARAM_REBOOT TEXT( " REBOOT=Force" ) +#define PARAM_PATCH TEXT( " /update " ) +#define PARAM_REG_ALL_MSO_TYPES TEXT( "REGISTER_ALL_MSO_TYPES=1 " ) +#define PARAM_REG_NO_MSO_TYPES TEXT( "REGISTER_NO_MSO_TYPES=1 " ) +#define PARAM_SILENTINSTALL TEXT( " /QB" ) + +#define PARAM_RUNNING TEXT( "ignore_running" ) +#define CMDLN_REG_ALL_MSO_TYPES TEXT( "msoreg=1" ) +#define CMDLN_REG_NO_MSO_TYPES TEXT( "msoreg=0" ) + +#define MSI_DLL TEXT( "msi.dll" ) +#define ADVAPI32_DLL TEXT( "advapi32.dll" ) +#define PROFILE_NAME TEXT( "setup.ini" ) + +#define RUNTIME_X64_NAME TEXT( "redist\\vcredist_x64.exe" ) +#define RUNTIME_X86_NAME TEXT( "redist\\vcredist_x86.exe" ) +#define PRODUCTCODE_X86 TEXT( "{E503B4BF-F7BB-3D5F-8BC8-F694B1CFF942}" ) +#define PRODUCTCODE_X64 TEXT( "{350AA351-21FA-3270-8B7A-835434E766AD}" ) + +#define MSIAPI_DllGetVersion "DllGetVersion" +#define ADVAPI32API_CheckTokenMembership "CheckTokenMembership" + +typedef HRESULT (CALLBACK* PFnDllGetVersion)( DLLVERSIONINFO *pdvi); +typedef BOOL (WINAPI* PFnCheckTokenMembership)(HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember); + +#ifdef DEBUG +inline void OutputDebugStringFormat( LPCTSTR pFormat, ... ) +{ + TCHAR buffer[1024]; + va_list args; + + va_start( args, pFormat ); + StringCchVPrintf( buffer, sizeof(buffer), pFormat, args ); + OutputDebugString( buffer ); +} +#else +static inline void OutputDebugStringFormat( LPCTSTR, ... ) +{ +} +#endif + +//-------------------------------------------------------------------------- + +const TCHAR sInstKey[] = TEXT( "Software\\Microsoft\\Windows\\CurrentVersion\\Installer" ); +const TCHAR sInstLocValue[] = TEXT( "InstallerLocation" ); +const TCHAR sMsiDll[] = TEXT( "\\msi.dll" ); +const TCHAR sMsiExe[] = TEXT( "\\msiexec.exe" ); +const TCHAR sDelayReboot[] = TEXT( " /c:\"msiinst /delayreboot\"" ); +const TCHAR sMsiQuiet[] = TEXT( " /q" ); +const TCHAR sMemMapName[] = TEXT( "Global\\MsiErrorObject" ); + +//-------------------------------------------------------------------------- +SetupAppX::SetupAppX() +{ + m_hInst = NULL; + m_hMapFile = NULL; + m_pAppTitle = NULL; + m_pCmdLine = NULL; + + m_pDatabase = NULL; + m_pReqVersion = NULL; + m_pProductName = NULL; + m_pAdvertise = NULL; + m_pTmpName = NULL; + m_pLogFile = NULL; + m_pModuleFile = NULL; + m_pPatchFiles = NULL; + m_pMSIErrorCode = NULL; + m_pUpgradeKey = NULL; + m_pProductVersion = NULL; + + m_pErrorText = new TCHAR[ MAX_TEXT_LENGTH ]; + m_pErrorText[0] = '\0'; + + m_nLanguageID = 0; + m_nLanguageCount = 0; + m_ppLanguageList = NULL; + + m_bQuiet = false; + m_bRegNoMsoTypes = false; + m_bRegAllMsoTypes = false; + m_bIsMinorUpgrade = false; + m_bSupportsPatch = false; + + m_bIgnoreAlreadyRunning = false; +} + +//-------------------------------------------------------------------------- +SetupAppX::~SetupAppX() +{ + if ( m_ppLanguageList ) + { + for ( int i = 0; i < m_nLanguageCount; i++ ) + if ( m_ppLanguageList[i] ) + delete m_ppLanguageList[ i ]; + delete [] m_ppLanguageList; + } + + time_t aTime; + time( &aTime ); + tm *pTime = localtime( &aTime ); // Convert time to struct tm form + + Log( TEXT( "End: %s\n\r\n\r\n" ), _tasctime( pTime ) ); + + if ( m_pLogFile ) fclose( m_pLogFile ); + + if ( m_pTmpName ) + { + _tremove( m_pTmpName ); + free( m_pTmpName ); + } + + if ( m_pMSIErrorCode ) UnmapViewOfFile( m_pMSIErrorCode ); + if ( m_hMapFile ) CloseHandle( m_hMapFile ); + + if ( m_pAppTitle ) delete [] m_pAppTitle; + if ( m_pDatabase ) delete [] m_pDatabase; + if ( m_pReqVersion ) delete [] m_pReqVersion; + if ( m_pProductName ) delete [] m_pProductName; + if ( m_pAdvertise ) delete [] m_pAdvertise; + if ( m_pLogFile ) delete [] m_pLogFile; + if ( m_pErrorText ) delete [] m_pErrorText; + if ( m_pModuleFile ) delete [] m_pModuleFile; + if ( m_pPatchFiles ) delete [] m_pPatchFiles; + if ( m_pUpgradeKey ) delete [] m_pUpgradeKey; + if ( m_pProductVersion ) delete [] m_pProductVersion; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::Initialize( HINSTANCE hInst ) +{ + m_pCmdLine = WIN::GetCommandLine(); + m_hInst = hInst; + + // Load our AppTitle (caption) + m_pAppTitle = new TCHAR[ MAX_STR_CAPTION ]; + m_pAppTitle[0] = '\0'; + WIN::LoadString( hInst, IDS_APP_TITLE, m_pAppTitle, MAX_STR_CAPTION ); + + // Obtain path we are running from + m_pModuleFile = new TCHAR[ MAX_PATH ]; + m_pModuleFile[ 0 ] = '\0'; + + if ( 0 == WIN::GetModuleFileName( hInst, m_pModuleFile, MAX_PATH ) ) + { + SetError( WIN::GetLastError() ); + return false; + } + + if ( ! GetCmdLineParameters( &m_pCmdLine ) ) + return false; + + m_hMapFile = CreateFileMapping( + INVALID_HANDLE_VALUE, // use paging file + NULL, // default security + PAGE_READWRITE, // read/write access + 0, // max. object size + sizeof( int ), // buffer size + sMemMapName ); + if ( m_hMapFile ) + { + m_pMSIErrorCode = (int*) MapViewOfFile( m_hMapFile, // handle to map object + FILE_MAP_ALL_ACCESS, // read/write permission + 0, + 0, + sizeof( int ) ); + if ( m_pMSIErrorCode ) + *m_pMSIErrorCode = 0; + else + OutputDebugStringFormat( TEXT("Could not map view of file (%d).\n"), GetLastError() ); + } + else + OutputDebugStringFormat( TEXT("Could not create file mapping object (%d).\n"), GetLastError() ); + + Log( TEXT("Starting: %s\r\n"), m_pModuleFile ); + Log( TEXT(" CommandLine=<%s>\r\n"), m_pCmdLine ); + + if ( m_bQuiet ) + Log( TEXT(" Using quiet install mode\r\n") ); + + time_t aTime; + time( &aTime ); + tm* pTime = localtime( &aTime ); + Log( TEXT(" Begin: %s\n"), _tasctime( pTime ) ); + + return true; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::GetProfileSection( LPCTSTR pFileName, LPCTSTR pSection, + DWORD& rSize, LPTSTR *pRetBuf ) +{ + if ( !rSize || !*pRetBuf ) + { + rSize = 10000; + *pRetBuf = new TCHAR[ rSize ]; + } + + DWORD nRet = GetPrivateProfileSection( pSection, *pRetBuf, rSize, pFileName ); + + while ( nRet && ( nRet + 2 >= rSize ) ) // buffer was too small, retry until big enough + { + if (rSize > 1000000) + break; + delete [] (*pRetBuf); + rSize = rSize * 2; + *pRetBuf = new TCHAR[ rSize ]; + + nRet = GetPrivateProfileSection( pSection, *pRetBuf, rSize, pFileName ); + } + + if ( !nRet ) + { + SetError( WIN::GetLastError() ); + + TCHAR sBuf[80]; + StringCchPrintf( sBuf, 80, TEXT("ERROR: GetPrivateProfileSection(): GetLastError returned %u\r\n"), GetError() ); + Log( sBuf ); + return false; + } + else if ( nRet + 2 >= rSize ) + { + SetError( ERROR_OUTOFMEMORY ); + Log( TEXT( "ERROR: GetPrivateProfileSection() out of memory\r\n" ) ); + return false; + } + + Log( TEXT( " GetProfileSection read %s\r\n" ), pSection ); + + return true; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::ReadProfile() +{ + boolean bRet = false; + TCHAR *sProfilePath = 0; + + if ( GetPathToFile( PROFILE_NAME, &sProfilePath ) ) + { + DWORD nSize = 0; + LPTSTR pRetBuf = NULL; + + Log( TEXT( " Open ini file: <%s>\r\n" ), sProfilePath ); + + bRet = GetProfileSection( sProfilePath, SECTION_SETUP, nSize, &pRetBuf ); + + if ( !bRet ) + { + LPTSTR pTmpFile = CopyIniFile( sProfilePath ); + delete [] sProfilePath; + sProfilePath = pTmpFile; + + if ( sProfilePath ) + { + SetError( ERROR_SUCCESS ); + + Log( TEXT( " Could not open inifile, copied ini file to: <%s>\r\n" ), sProfilePath ); + bRet = GetProfileSection( sProfilePath, SECTION_SETUP, nSize, &pRetBuf ); + } + } + + if ( bRet ) + { + LPTSTR pCurLine = pRetBuf; + while ( *pCurLine ) + { + LPTSTR pName = 0; + LPTSTR pValue = 0; + + pCurLine += GetNameValue( pCurLine, &pName, &pValue ); + + if ( lstrcmpi( TEXT( "database" ), pName ) == 0 ) + { + m_pDatabase = pValue; + Log( TEXT( " Database = %s\r\n" ), pValue ); + } + else if ( lstrcmpi( TEXT( "msiversion" ), pName ) == 0 ) + { + m_pReqVersion = pValue; + Log( TEXT( " msiversion = %s\r\n" ), pValue ); + } + else if ( lstrcmpi( TEXT( "productname" ), pName ) == 0 ) + { + m_pProductName = pValue; + Log( TEXT( " productname = %s\r\n" ), pValue ); + m_pAppTitle = SetProdToAppTitle( m_pProductName ); + } + else if ( lstrcmpi( TEXT( "upgradekey" ), pName ) == 0 ) + { + m_pUpgradeKey = pValue; + Log( TEXT( " upgradekey = %s\r\n" ), pValue ); + } + else if ( lstrcmpi( TEXT( "productversion" ), pName ) == 0 ) + { + m_pProductVersion = pValue; + Log( TEXT( " productversion = %s\r\n" ), pValue ); + } + else if ( lstrcmpi( TEXT( "productcode" ), pName ) == 0 ) + { + delete [] pValue; + } + else + { + Log( TEXT( "Warning: unknown entry in profile <%s>\r\n" ), pName ); + delete [] pValue; + } + } + } + + if ( bRet && ( !m_pDatabase || !m_pReqVersion || !m_pProductName ) ) + { + Log( TEXT( "ERROR: incomplete 'Setup' section in profile\r\n" ) ); + SetError( ERROR_INVALID_DATA ); + bRet = false; + } + + if ( bRet ) + bRet = GetProfileSection( sProfilePath, SECTION_LANGUAGE, nSize, &pRetBuf ); + + if ( bRet ) + { + LPTSTR pName = 0; + LPTSTR pValue = 0; + LPTSTR pCurLine = pRetBuf; + LPTSTR pLastChar; + int nNext = 0; + + // first line in this section should be the language count + nNext = GetNameValue( pCurLine, &pName, &pValue ); + if ( lstrcmpi( TEXT( "count" ), pName ) == 0 ) + { + Log( TEXT( " Languages = %s\r\n" ), pValue ); + m_nLanguageCount = _tcstol( pValue, &pLastChar, 10 ); + pCurLine += nNext; + delete [] pValue; + } + + m_ppLanguageList = new LanguageDataX*[ m_nLanguageCount ]; + + for ( int i=0; i < m_nLanguageCount; i++ ) + { + if ( !*pCurLine ) + { + m_nLanguageCount = i; + break; + } + + pCurLine += GetNameValue( pCurLine, &pName, &pValue ); + m_ppLanguageList[ i ] = new LanguageDataX( pValue ); + Log( TEXT( " Language = %s\r\n" ), pValue ); + + if ( m_ppLanguageList[ i ]->m_pTransform ) + Log( TEXT( " Transform = %s\r\n" ), m_ppLanguageList[ i ]->m_pTransform ); + + delete [] pValue; + } + } + + if ( pRetBuf ) + delete [] pRetBuf; + } + + if ( sProfilePath && ! m_pTmpName ) + delete [] sProfilePath; + + return bRet; +} + +//-------------------------------------------------------------------------- +void SetupAppX::AddFileToPatchList( TCHAR* pPath, TCHAR* pFile ) +{ + if ( m_pPatchFiles == NULL ) + { + m_pPatchFiles = new TCHAR[ MAX_STR_LENGTH ]; + StringCchCopy( m_pPatchFiles, MAX_STR_LENGTH, TEXT("\"") ); + } + else + StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, TEXT(";") ); + + StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, pPath ); + StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, pFile ); +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::GetPatches() +{ + boolean bRet = true; + + int nPatternLen = lstrlen( m_pModuleFile ) + 7; // 1 for null terminator, 1 for back slash, 5 for extensions + TCHAR* pPattern = new TCHAR[ nPatternLen ]; + TCHAR* pBaseDir = new TCHAR[ nPatternLen ]; + + // find 'setup.exe' in the path so we can remove it + TCHAR *pFilePart = 0; + if ( 0 == GetFullPathName( m_pModuleFile, nPatternLen, pPattern, &pFilePart ) ) + { + SetError( WIN::GetLastError() ); + bRet = false; + } + else + { + if ( pFilePart ) + *pFilePart = '\0'; + StringCchCopy( pBaseDir, nPatternLen, pPattern ); + StringCchCat( pPattern, nPatternLen, TEXT("*.msp") ); + + WIN32_FIND_DATA aFindFileData; + + HANDLE hFindPatches = FindFirstFile( pPattern, &aFindFileData ); + + if ( hFindPatches != INVALID_HANDLE_VALUE ) + { + if ( ! IsPatchInstalled( pBaseDir, aFindFileData.cFileName ) ) + AddFileToPatchList( pBaseDir, aFindFileData.cFileName ); + + while ( FindNextFile( hFindPatches, &aFindFileData ) ) + { + if ( ! IsPatchInstalled( pBaseDir, aFindFileData.cFileName ) ) + AddFileToPatchList( pBaseDir, aFindFileData.cFileName ); + } + + if ( m_pPatchFiles != NULL ) + StringCchCat( m_pPatchFiles, MAX_STR_LENGTH, TEXT("\"") ); + + FindClose( hFindPatches ); + } + } + + delete [] pPattern; + delete [] pBaseDir; + + return bRet; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::GetPathToFile( TCHAR* pFileName, TCHAR** pPath ) +{ + // generate the path to the file = szModuleFile + FileName + // note: FileName is a relative path + + boolean bRet = true; + + int nTempPath = lstrlen( m_pModuleFile ) + lstrlen( pFileName ) + 2; // 1 for null terminator, 1 for back slash + TCHAR* pTempPath = new TCHAR[ nTempPath ]; + + // find 'setup.exe' in the path so we can remove it + TCHAR *pFilePart = 0; + if ( 0 == GetFullPathName( m_pModuleFile, nTempPath, pTempPath, &pFilePart ) ) + { + SetError( WIN::GetLastError() ); + bRet = false; + } + else + { + if ( pFilePart ) + *pFilePart = '\0'; + + StringCchCat( pTempPath, nTempPath, pFileName ); + + int nPath = 2 * nTempPath; + *pPath = new TCHAR[ nPath ]; + + // normalize the path + int nReturn = GetFullPathName( pTempPath, nPath, *pPath, &pFilePart ); + + if ( nReturn > nPath ) + { + // try again, with larger buffer + delete [] (*pPath); + nPath = nReturn; + *pPath = new TCHAR[ nPath ]; + + nReturn = GetFullPathName( pTempPath, nPath, *pPath, &pFilePart ); + } + + if ( 0 == nReturn ) + { + // error -- invalid path + SetError( WIN::GetLastError() ); + bRet = false; + } + } + + if ( bRet ) // check for the file's existence + { + DWORD dwFileAttrib = GetFileAttributes( *pPath ); + + if (0xFFFFFFFF == dwFileAttrib) + { + StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pFileName ); + SetError( ERROR_FILE_NOT_FOUND ); + bRet = false; + } + } + + delete [] pTempPath; + return bRet; +} + +//-------------------------------------------------------------------------- +int SetupAppX::GetNameValue( TCHAR* pLine, TCHAR** pName, TCHAR** pValue ) +{ + int nRet = lstrlen( pLine ) + 1; + *pValue = 0; + + if ( nRet == 1 ) + return nRet; + + LPTSTR pChar = pLine; + LPTSTR pLast = NULL; + + // Skip leading spaces. + while (' ' == *pChar || '\t' == *pChar) + pChar = CharNext( pChar ); + + *pName = pChar; + + // look for the end of the name + while( *pChar && (' ' != *pChar) && + ( '\t' != *pChar ) && ( '=' != *pChar ) ) + pChar = CharNext( pChar ); + + if ( ! *pChar ) + return nRet; + + pLast = pChar; + pChar = CharNext( pChar ); + *pLast = '\0'; + + // look for the start of the value + while( ( ' ' == *pChar ) || ( '\t' == *pChar ) || + ( '=' == *pChar ) ) + pChar = CharNext( pChar ); + + int nValueLen = lstrlen( pChar ) + 1; + *pValue = new TCHAR[ nValueLen ]; + + if ( *pValue ) + StringCchCopy( *pValue, nValueLen, pChar ); + + return nRet; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::ChooseLanguage( long& rLanguage ) +{ + rLanguage = 0; + + if ( m_bQuiet ) + return true; + + // When there are none or only one language, there is nothing + // to do here + if ( m_nLanguageCount > 1 ) + { + TCHAR *sString = new TCHAR[ MAX_LANGUAGE_LEN ]; + + LANGID nUserDefLang = GetUserDefaultLangID(); + LANGID nSysDefLang = GetSystemDefaultLangID(); + + int nUserPrimary = PRIMARYLANGID( nUserDefLang ); + int nSysPrimary = PRIMARYLANGID( nSysDefLang ); + + long nUserIndex = -1; + long nUserPrimIndex = -1; + long nSystemIndex = -1; + long nSystemPrimIndex = -1; + long nParamIndex = -1; + + for ( long i=0; i<GetLanguageCount(); i++ ) + { + long nLanguage = GetLanguageID( i ); + int nPrimary = PRIMARYLANGID( nLanguage ); + GetLanguageName( nLanguage, sString ); + Log( TEXT( " Info: found Language: %s\r\n" ), sString ); + + if ( nLanguage == nUserDefLang ) + nUserIndex = i; + if ( nPrimary == nUserPrimary ) + nUserPrimIndex = i; + if ( nLanguage == nSysDefLang ) + nSystemIndex = i; + if ( nPrimary == nSysPrimary ) + nSystemPrimIndex = i; + if ( m_nLanguageID && ( nLanguage == m_nLanguageID ) ) + nParamIndex = i; + } + + if ( m_nLanguageID && ( nParamIndex == -1 ) ) + { + Log( TEXT( "Warning: Language chosen with parameter -lang not found.\r\n" ) ); + } + + if ( nParamIndex != -1 ) + { + Log( TEXT( "Info: Found language chosen with parameter -lang.\r\n" ) ); + rLanguage = GetLanguageID( nParamIndex ); + } + else if ( nUserIndex != -1 ) + { + Log( TEXT( "Info: Found user default language.\r\n" ) ); + rLanguage = GetLanguageID( nUserIndex ); + } + else if ( nUserPrimIndex != -1 ) + { + Log( TEXT( "Info: Found user default primary language.\r\n" ) ); + rLanguage = GetLanguageID( nUserPrimIndex ); + } + else if ( nSystemIndex != -1 ) + { + Log( TEXT( "Info: Found system default language.\r\n" ) ); + rLanguage = GetLanguageID( nSystemIndex ); + } + else if ( nSystemPrimIndex != -1 ) + { + Log( TEXT( "Info: Found system default primary language.\r\n" ) ); + rLanguage = GetLanguageID( nSystemPrimIndex ); + } + else + { + Log( TEXT( "Info: Use default language from ini file.\r\n" ) ); + rLanguage = GetLanguageID( 0 ); + } + delete [] sString; + } + + return true; +} + +//-------------------------------------------------------------------------- +HMODULE SetupAppX::LoadMsiLibrary() +{ + HMODULE hMsi = NULL; + HKEY hInstKey = NULL; + + // find registered location of Msi.dll + if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, sInstKey, 0, KEY_READ, &hInstKey ) ) + { + long nRet = ERROR_SUCCESS; + TCHAR *sMsiFolder = new TCHAR[ MAX_PATH + 1 ]; + DWORD dwMsiFolderSize = MAX_PATH + 1; + DWORD dwType = 0; + + if ( ERROR_MORE_DATA == ( nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, + &dwType, (BYTE*)sMsiFolder, &dwMsiFolderSize ) ) ) + { + // try again with larger buffer + delete [] sMsiFolder; + sMsiFolder = new TCHAR[ dwMsiFolderSize ]; + + nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, &dwType, + (BYTE*)sMsiFolder, &dwMsiFolderSize ); + } + + if ( ERROR_SUCCESS == nRet && dwType == REG_SZ && dwMsiFolderSize > 0 ) + { + // load Msi.dll from registered location + int nLength = lstrlen( sMsiDll ) + dwMsiFolderSize + 1; // use StringCchLength ? + TCHAR *pMsiLocation = new TCHAR[ nLength ]; + + if ( SUCCEEDED( StringCchCopy( pMsiLocation, nLength, sMsiFolder ) ) && + SUCCEEDED( StringCchCat( pMsiLocation, nLength, sMsiDll ) ) ) + { + hMsi = LoadLibrary( pMsiLocation ); + } + } + } + + if ( !hMsi ) // use the default location + { + hMsi = LoadLibrary( sMsiDll ); + } + + return hMsi; +} + +//-------------------------------------------------------------------------- +LPCTSTR SetupAppX::GetPathToMSI() +{ + LPTSTR sMsiPath = NULL; + HKEY hInstKey = NULL; + TCHAR *sMsiFolder = new TCHAR[ MAX_PATH + 1 ]; + DWORD nMsiFolderSize = MAX_PATH + 1; + + sMsiFolder[0] = '\0'; + + // find registered location of Msi.dll + if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, sInstKey, 0, KEY_READ, &hInstKey ) ) + { + LONG nRet = ERROR_SUCCESS; + DWORD dwType = 0; + + if ( ERROR_MORE_DATA == ( nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, + &dwType, (BYTE*)sMsiFolder, &nMsiFolderSize ) ) ) + { + // try again with larger buffer + delete [] sMsiFolder; + sMsiFolder = new TCHAR[ nMsiFolderSize ]; + + nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, &dwType, + (BYTE*)sMsiFolder, &nMsiFolderSize ); + } + + if ( ERROR_SUCCESS != nRet || dwType != REG_SZ || nMsiFolderSize == 0 ) + sMsiFolder[0] = '\0'; + } + + if ( sMsiFolder[0] == '\0' ) // use the default location + { + Log( TEXT( " Could not find path to msiexec.exe in registry" ) ); + + DWORD nRet = WIN::GetSystemDirectory( sMsiFolder, nMsiFolderSize ); + if ( nRet > nMsiFolderSize ) + { + delete [] sMsiFolder; + sMsiFolder = new TCHAR[ nRet ]; + nMsiFolderSize = nRet; + + nRet = WIN::GetSystemDirectory( sMsiFolder, nMsiFolderSize ); + } + if ( 0 == nRet ) + { + sMsiFolder[0] = '\0'; + SetError( WIN::GetLastError() ); + } + nMsiFolderSize = nRet; + } + + if ( sMsiFolder[0] != '\0' ) + { + int nLength = lstrlen( sMsiExe ) + lstrlen( sMsiFolder ) + 1; + sMsiPath = new TCHAR[ nLength ]; + + if ( FAILED( StringCchCopy( sMsiPath, nLength, sMsiFolder ) ) || + FAILED( StringCchCat( sMsiPath, nLength, sMsiExe ) ) ) + { + delete [] sMsiPath; + sMsiPath = NULL; + } + } + + if ( ! sMsiPath ) + Log( TEXT( "ERROR: Can't build path to msiexec.exe!" ) ); + + return sMsiPath; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::LaunchInstaller( LPCTSTR pParam ) +{ + LPCTSTR sMsiPath = GetPathToMSI(); + + if ( !sMsiPath ) + { + Log( TEXT( "ERROR: msiexec not found!" ) ); + SetError( ERROR_FILE_NOT_FOUND ); + return false; + } + + STARTUPINFO aSUI; + PROCESS_INFORMATION aPI; + + Log( TEXT( " Will install using <%s>\r\n" ), sMsiPath ); + Log( TEXT( " Prameters are: %s\r\n" ), pParam ); + + OutputDebugStringFormat( TEXT( " Will install using <%s>\r\n" ), sMsiPath ); + OutputDebugStringFormat( TEXT( " Prameters are: %s\r\n" ), pParam ); + + ZeroMemory( (void*)&aPI, sizeof( PROCESS_INFORMATION ) ); + ZeroMemory( (void*)&aSUI, sizeof( STARTUPINFO ) ); + + aSUI.cb = sizeof(STARTUPINFO); + aSUI.dwFlags = STARTF_USESHOWWINDOW; + aSUI.wShowWindow = SW_SHOW; + + DWORD nCmdLineLength = lstrlen( sMsiPath ) + lstrlen( pParam ) + 2; + TCHAR *sCmdLine = new TCHAR[ nCmdLineLength ]; + + if ( FAILED( StringCchCopy( sCmdLine, nCmdLineLength, sMsiPath ) ) || + FAILED( StringCchCat( sCmdLine, nCmdLineLength, TEXT( " " ) ) ) || + FAILED( StringCchCat( sCmdLine, nCmdLineLength, pParam ) ) ) + { + delete [] sCmdLine; + SetError( ERROR_INSTALL_FAILURE ); + return false; + } + + if ( !WIN::CreateProcess( NULL, sCmdLine, NULL, NULL, FALSE, + CREATE_DEFAULT_ERROR_MODE, NULL, NULL, + &aSUI, &aPI ) ) + { + Log( TEXT( "ERROR: Could not create process %s.\r\n" ), sCmdLine ); + SetError( WIN::GetLastError() ); + delete [] sCmdLine; + return false; + } + + DWORD nResult = WaitForProcess( aPI.hProcess ); + bool bRet = true; + + if( ERROR_SUCCESS != nResult ) + { + Log( TEXT( "ERROR: While waiting for %s.\r\n" ), sCmdLine ); + SetError( nResult ); + bRet = false; + } + else + { + GetExitCodeProcess( aPI.hProcess, &nResult ); + SetError( nResult ); + + if ( nResult != ERROR_SUCCESS ) + { + TCHAR sBuf[80]; + StringCchPrintf( sBuf, 80, TEXT("Warning: msiexec returned %u.\r\n"), nResult ); + Log( sBuf ); + } + else + Log( TEXT( " Installation completed successfully.\r\n" ) ); + } + + CloseHandle( aPI.hProcess ); + + delete [] sCmdLine; + + return bRet; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::Install( long nLanguage ) +{ + LPTSTR pTransform = NULL; + + if ( nLanguage ) // look for transformation + { + for ( int i = 0; i < m_nLanguageCount; i++ ) + { + if ( m_ppLanguageList[i]->m_nLanguageID == nLanguage ) + { + if ( m_ppLanguageList[i]->m_pTransform ) + { + if ( !GetPathToFile( m_ppLanguageList[i]->m_pTransform, + &pTransform ) ) + { + Log( TEXT( "ERROR: Could not find transform <%s\r\n" ), m_ppLanguageList[i]->m_pTransform ); + return false; + } + } + break; + } + } + } + + TCHAR *pDataBasePath = NULL; + + if ( ! GetPathToFile( m_pDatabase, &pDataBasePath ) ) + { + Log( TEXT( "ERROR: Could not find database <%s\r\n" ), m_pDatabase ); + SetError( ERROR_INSTALL_SOURCE_ABSENT ); + return false; + } + + // we will always use the parameter setup used + int nParLen = lstrlen( PARAM_SETUP_USED ); + + if ( m_bRegNoMsoTypes ) + nParLen += lstrlen( PARAM_REG_NO_MSO_TYPES ); + else if ( m_bRegAllMsoTypes ) + nParLen += lstrlen( PARAM_REG_ALL_MSO_TYPES ); + + if ( m_pAdvertise ) + nParLen += lstrlen( m_pAdvertise ) + 1; // one for the space + else if ( m_bIsMinorUpgrade ) + nParLen += lstrlen( PARAM_MINOR_UPGRADE ); + else + nParLen += lstrlen( PARAM_PACKAGE ); + + nParLen += lstrlen( pDataBasePath ) + 3; // two quotes, one null + + if ( NeedReboot() ) + nParLen += lstrlen( PARAM_REBOOT ); + + if ( m_pPatchFiles ) + { + nParLen += lstrlen( PARAM_PATCH ); + nParLen += lstrlen( m_pPatchFiles ); + } + + if ( pTransform ) + { + nParLen += lstrlen( PARAM_TRANSFORM ); + nParLen += lstrlen( pTransform ) + 2; // two quotes + } + + if ( m_pCmdLine ) + nParLen += lstrlen( m_pCmdLine ) + 1; // one for the space; + + TCHAR *pParams = new TCHAR[ nParLen ]; + + StringCchCopy( pParams, nParLen, PARAM_SETUP_USED ); + + if ( m_bRegNoMsoTypes ) + StringCchCat( pParams, nParLen, PARAM_REG_NO_MSO_TYPES ); + else if ( m_bRegAllMsoTypes ) + StringCchCat( pParams, nParLen, PARAM_REG_ALL_MSO_TYPES ); + + if ( m_pAdvertise ) + StringCchCat( pParams, nParLen, m_pAdvertise ); + else if ( IsAdminInstall() ) + StringCchCat( pParams, nParLen, PARAM_ADMIN ); + else if ( m_bIsMinorUpgrade ) + StringCchCat( pParams, nParLen, PARAM_MINOR_UPGRADE ); + else + StringCchCat( pParams, nParLen, PARAM_PACKAGE ); + + StringCchCat( pParams, nParLen, TEXT( "\"" ) ); + StringCchCat( pParams, nParLen, pDataBasePath ); + StringCchCat( pParams, nParLen, TEXT( "\"" ) ); + + if ( NeedReboot() ) + StringCchCat( pParams, nParLen, PARAM_REBOOT ); + + if ( m_pPatchFiles ) + { + StringCchCat( pParams, nParLen, PARAM_PATCH ); + StringCchCat( pParams, nParLen, m_pPatchFiles ); + } + + if ( pTransform ) + { + StringCchCat( pParams, nParLen, PARAM_TRANSFORM ); + StringCchCat( pParams, nParLen, TEXT( "\"" ) ); + StringCchCat( pParams, nParLen, pTransform ); + StringCchCat( pParams, nParLen, TEXT( "\"" ) ); + } + + if ( m_pCmdLine ) + { + StringCchCat( pParams, nParLen, TEXT( " " ) ); + StringCchCat( pParams, nParLen, m_pCmdLine ); + } + + return LaunchInstaller( pParams ); +} + +//-------------------------------------------------------------------------- +UINT SetupAppX::GetError() const +{ + UINT nErr = 0; + + if ( m_pMSIErrorCode ) + nErr = (UINT) *m_pMSIErrorCode; + + if ( nErr == 0 ) + nErr = m_uiRet; + + if ( nErr != 0 ) + OutputDebugStringFormat( TEXT("Setup will return error (%d).\n"), nErr ); + return nErr; +} + +//-------------------------------------------------------------------------- +void SetupAppX::DisplayError( UINT nErr ) const +{ + TCHAR sError[ MAX_TEXT_LENGTH ] = {0}; + TCHAR sTmp[ MAX_TEXT_LENGTH ] = {0}; + + UINT nMsgType = MB_OK | MB_ICONERROR; + + switch ( nErr ) + { + case ERROR_SUCCESS: break; // 0 + + case ERROR_FILE_NOT_FOUND: // 2 + WIN::LoadString( m_hInst, IDS_FILE_NOT_FOUND, sTmp, MAX_TEXT_LENGTH ); + StringCchPrintf( sError, MAX_TEXT_LENGTH, sTmp, m_pErrorText ); + break; + case ERROR_INVALID_DATA: // 13 + WIN::LoadString( m_hInst, IDS_INVALID_PROFILE, sError, MAX_TEXT_LENGTH ); + break; + case ERROR_OUTOFMEMORY: WIN::LoadString( m_hInst, IDS_OUTOFMEM, sError, MAX_TEXT_LENGTH ); + break; + case ERROR_INSTALL_USEREXIT: + WIN::LoadString( m_hInst, IDS_USER_CANCELLED, sError, MAX_TEXT_LENGTH ); + break; + case ERROR_INSTALL_ALREADY_RUNNING: // 1618 + WIN::LoadString( m_hInst, IDS_ALREADY_RUNNING, sError, MAX_TEXT_LENGTH ); + break; + case ERROR_INSTALL_SOURCE_ABSENT: + WIN::LoadString( m_hInst, IDS_NOMSI, sError, MAX_TEXT_LENGTH ); + break; + case ERROR_DS_INSUFF_ACCESS_RIGHTS: // 8344 + WIN::LoadString( m_hInst, IDS_REQUIRES_ADMIN_PRIV, sError, MAX_TEXT_LENGTH ); + break; + case E_ABORT: WIN::LoadString( m_hInst, IDS_UNKNOWN_ERROR, sError, MAX_TEXT_LENGTH ); + break; + case ERROR_INVALID_PARAMETER: // 87 + WIN::LoadString( m_hInst, IDS_INVALID_PARAM, sTmp, MAX_TEXT_LENGTH ); + StringCchPrintf( sError, MAX_TEXT_LENGTH, sTmp, m_pErrorText ); + break; + + case ERROR_SETUP_TO_OLD: // - 3 + WIN::LoadString( m_hInst, IDS_SETUP_TO_OLD, sTmp, MAX_TEXT_LENGTH ); + StringCchPrintf( sError, MAX_TEXT_LENGTH, sTmp, m_pReqVersion, m_pErrorText ); + break; + case ERROR_SETUP_NOT_FOUND: // - 4 + WIN::LoadString( m_hInst, IDS_SETUP_NOT_FOUND, sTmp, MAX_TEXT_LENGTH ); + StringCchPrintf( sError, MAX_TEXT_LENGTH, sTmp, m_pReqVersion ); + break; + case ERROR_SHOW_USAGE: // - 2 + nMsgType = MB_OK | MB_ICONINFORMATION; + WIN::LoadString( m_hInst, IDS_USAGE, sError, MAX_TEXT_LENGTH ); + break; + + default: WIN::LoadString( m_hInst, IDS_UNKNOWN_ERROR, sError, MAX_TEXT_LENGTH ); + break; + } + + if ( sError[0] ) + { + if ( !m_bQuiet ) + { + ConvertNewline( sError ); + WIN::MessageBox( NULL, sError, m_pAppTitle, nMsgType ); + } + + Log( TEXT( "ERROR: %s\r\n" ), sError ); + } +} + +//-------------------------------------------------------------------------- +long SetupAppX::GetLanguageID( long nIndex ) const +{ + if ( nIndex >=0 && nIndex < m_nLanguageCount ) + return m_ppLanguageList[ nIndex ]->m_nLanguageID; + else + return 0; +} + +//-------------------------------------------------------------------------- +void SetupAppX::GetLanguageName( long nLanguage, LPTSTR sName ) const +{ + switch ( nLanguage ) + { + case 1028: WIN::LoadString( m_hInst, IDS_LANGUAGE_ZH_TW, sName, MAX_LANGUAGE_LEN ); break; + case 1029: WIN::LoadString( m_hInst, IDS_LANGUAGE_CS, sName, MAX_LANGUAGE_LEN ); break; + case 1030: WIN::LoadString( m_hInst, IDS_LANGUAGE_DA, sName, MAX_LANGUAGE_LEN ); break; + case 1031: WIN::LoadString( m_hInst, IDS_LANGUAGE_DE_DE, sName, MAX_LANGUAGE_LEN ); break; + case 1032: WIN::LoadString( m_hInst, IDS_LANGUAGE_EL, sName, MAX_LANGUAGE_LEN ); break; + case 1033: WIN::LoadString( m_hInst, IDS_LANGUAGE_EN_US, sName, MAX_LANGUAGE_LEN ); break; + case 1034: WIN::LoadString( m_hInst, IDS_LANGUAGE_ES, sName, MAX_LANGUAGE_LEN ); break; + case 1035: WIN::LoadString( m_hInst, IDS_LANGUAGE_FI, sName, MAX_LANGUAGE_LEN ); break; + case 1036: WIN::LoadString( m_hInst, IDS_LANGUAGE_FR_FR, sName, MAX_LANGUAGE_LEN ); break; + case 1037: WIN::LoadString( m_hInst, IDS_LANGUAGE_HE, sName, MAX_LANGUAGE_LEN ); break; + case 1038: WIN::LoadString( m_hInst, IDS_LANGUAGE_HU, sName, MAX_LANGUAGE_LEN ); break; + case 1040: WIN::LoadString( m_hInst, IDS_LANGUAGE_IT_IT, sName, MAX_LANGUAGE_LEN ); break; + case 1041: WIN::LoadString( m_hInst, IDS_LANGUAGE_JA, sName, MAX_LANGUAGE_LEN ); break; + case 1042: WIN::LoadString( m_hInst, IDS_LANGUAGE_KO, sName, MAX_LANGUAGE_LEN ); break; + case 1043: WIN::LoadString( m_hInst, IDS_LANGUAGE_NL_NL, sName, MAX_LANGUAGE_LEN ); break; + case 1044: WIN::LoadString( m_hInst, IDS_LANGUAGE_NO_NO, sName, MAX_LANGUAGE_LEN ); break; + case 1045: WIN::LoadString( m_hInst, IDS_LANGUAGE_PL, sName, MAX_LANGUAGE_LEN ); break; + case 1046: WIN::LoadString( m_hInst, IDS_LANGUAGE_PT_BR, sName, MAX_LANGUAGE_LEN ); break; + case 1049: WIN::LoadString( m_hInst, IDS_LANGUAGE_RU, sName, MAX_LANGUAGE_LEN ); break; + case 1051: WIN::LoadString( m_hInst, IDS_LANGUAGE_SK, sName, MAX_LANGUAGE_LEN ); break; + case 1053: WIN::LoadString( m_hInst, IDS_LANGUAGE_SV_SE, sName, MAX_LANGUAGE_LEN ); break; + case 1054: WIN::LoadString( m_hInst, IDS_LANGUAGE_TH, sName, MAX_LANGUAGE_LEN ); break; + case 1055: WIN::LoadString( m_hInst, IDS_LANGUAGE_TR, sName, MAX_LANGUAGE_LEN ); break; + case 1061: WIN::LoadString( m_hInst, IDS_LANGUAGE_ET, sName, MAX_LANGUAGE_LEN ); break; + case 2052: WIN::LoadString( m_hInst, IDS_LANGUAGE_ZH_CN, sName, MAX_LANGUAGE_LEN ); break; + case 2070: WIN::LoadString( m_hInst, IDS_LANGUAGE_PT_PT, sName, MAX_LANGUAGE_LEN ); break; + + default: + { + TCHAR sTmp[ MAX_LANGUAGE_LEN ] = {0}; + + WIN::LoadString( m_hInst, IDS_UNKNOWN_LANG, sTmp, MAX_LANGUAGE_LEN ); + StringCchPrintf( sName, MAX_LANGUAGE_LEN, sTmp, nLanguage ); + } + } +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::CheckVersion() +{ + boolean bRet = false; + HMODULE hMsi = LoadMsiLibrary(); + + Log( TEXT( " Looking for installed MSI with version >= %s\r\n" ), m_pReqVersion ); + + if ( !hMsi ) + { + Log( TEXT( "Error: No MSI found!\r\n" ) ); + SetError( (UINT) ERROR_SETUP_NOT_FOUND ); + } + else + { + PFnDllGetVersion pDllGetVersion = (PFnDllGetVersion) GetProcAddress( hMsi, MSIAPI_DllGetVersion ); + + if ( pDllGetVersion ) + { + DLLVERSIONINFO aInfo; + + aInfo.cbSize = sizeof( DLLVERSIONINFO ); + if ( NOERROR == pDllGetVersion( &aInfo ) ) + { + TCHAR pMsiVersion[ VERSION_SIZE ]; + StringCchPrintf( pMsiVersion, VERSION_SIZE, TEXT("%d.%d.%4d"), + aInfo.dwMajorVersion, + aInfo.dwMinorVersion, + aInfo.dwBuildNumber ); + if ( _tcsncmp( pMsiVersion, m_pReqVersion, _tcslen( pMsiVersion ) ) < 0 ) + { + StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pMsiVersion ); + SetError( (UINT) ERROR_SETUP_TO_OLD ); + Log( TEXT( "Warning: Old MSI version found <%s>, update needed!\r\n" ), pMsiVersion ); + } + else + { + Log( TEXT( " Found MSI version <%s>, no update needed\r\n" ), pMsiVersion ); + bRet = true; + } + if ( aInfo.dwMajorVersion >= 3 ) + m_bSupportsPatch = true; + else + Log( TEXT("Warning: Patching not supported! MSI-Version <%s>\r\n"), pMsiVersion ); + } + } + + FreeLibrary( hMsi ); + } + + return bRet; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::CheckForUpgrade() +{ + // When we have patch files we will never try an Minor upgrade + if ( m_pPatchFiles ) return true; + + if ( !m_pUpgradeKey || ( _tcslen( m_pUpgradeKey ) == 0 ) ) + { + Log( TEXT( " No Upgrade Key Found -> continue with standard installation!\r\n" ) ); + return true; + } + + HKEY hInstKey = NULL; + + if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, m_pUpgradeKey, 0, KEY_READ, &hInstKey ) ) + { + Log( TEXT( " Found Upgrade Key in Registry (HKLM) -> will try minor upgrade!\r\n" ) ); + m_bIsMinorUpgrade = true; + } + else if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_CURRENT_USER, m_pUpgradeKey, 0, KEY_READ, &hInstKey ) ) + { + Log( TEXT( " Found Upgrade Key in Registry (HKCU) -> will try minor upgrade!\r\n" ) ); + m_bIsMinorUpgrade = true; + } + else + { + Log( TEXT( " Didn't Find Upgrade Key in Registry -> continue with standard installation!\r\n" ) ); + return true; + } + + if ( m_pProductVersion && ( _tcslen( m_pProductVersion ) > 0 ) ) + { + TCHAR *sProductVersion = new TCHAR[ MAX_PATH + 1 ]; + DWORD nSize = MAX_PATH + 1; + + sProductVersion[0] = '\0'; + + // get product version + if ( ERROR_SUCCESS == RegQueryValueEx( hInstKey, PRODUCT_VERSION, NULL, NULL, (LPBYTE)sProductVersion, &nSize ) ) + { + if ( lstrcmpi( sProductVersion, m_pProductVersion ) == 0 ) + { + Log( TEXT( " Same Product Version already installed, no minor upgrade!\r\n" ) ); + m_bIsMinorUpgrade = false; + } + } + + delete [] sProductVersion; + } + + return true; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::IsTerminalServerInstalled() const +{ + boolean bIsTerminalServer = false; + + const TCHAR sSearchStr[] = TEXT("Terminal Server"); + const TCHAR sKey[] = TEXT("System\\CurrentControlSet\\Control\\ProductOptions"); + const TCHAR sValue[] = TEXT("ProductSuite"); + + DWORD dwSize = 0; + HKEY hKey = 0; + DWORD dwType = 0; + + if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, sKey, 0, KEY_READ, &hKey ) && + ERROR_SUCCESS == RegQueryValueEx( hKey, sValue, NULL, &dwType, NULL, &dwSize ) && + dwSize > 0 && + REG_MULTI_SZ == dwType ) + { + TCHAR* sSuiteList = new TCHAR[ (dwSize*sizeof(byte)/sizeof(TCHAR)) + 1 ]; + + ZeroMemory(sSuiteList, dwSize); + + if ( ERROR_SUCCESS == RegQueryValueEx( hKey, sValue, NULL, &dwType, (LPBYTE)sSuiteList, &dwSize) ) + { + DWORD nMulti = 0; + DWORD nSrch = lstrlen( sSearchStr ); + const TCHAR *sSubString = sSuiteList; + + while (*sSubString) + { + nMulti = lstrlen( sSubString ); + if ( nMulti == nSrch && 0 == lstrcmp( sSearchStr, sSubString ) ) + { + bIsTerminalServer = true; + break; + } + + sSubString += (nMulti + 1); + } + } + delete [] sSuiteList; + } + + if ( hKey ) + RegCloseKey( hKey ); + + return bIsTerminalServer; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::AlreadyRunning() const +{ + if ( m_bIgnoreAlreadyRunning ) + { + Log( TEXT("Ignoring already running MSI instance!\r\n") ); + return false; + } + + const TCHAR *sMutexName = NULL; + const TCHAR sGUniqueName[] = TEXT( "Global\\_MSISETUP_{EA8130C1-8D3D-4338-9309-1A52D530D846}" ); + const TCHAR sUniqueName[] = TEXT( "_MSISETUP_{EA8130C1-8D3D-4338-9309-1A52D530D846}" ); + + if ( ( GetOSVersion() < 5 ) && ! IsTerminalServerInstalled() ) + sMutexName = sUniqueName; + else + sMutexName = sGUniqueName; + + HANDLE hMutex = 0; + + hMutex = WIN::CreateMutex( NULL, FALSE, sMutexName ); + + if ( !hMutex || ERROR_ALREADY_EXISTS == WIN::GetLastError() ) + { + if ( !hMutex ) + Log( TEXT( "ERROR: AlreadyRunning() could not create mutex!\r\n" ) ); + else + Log( TEXT( "ERROR: There's already a setup running!\r\n" ) ); + + return true; + } + Log( TEXT( " No running Setup found\r\n" ) ); + + return false; +} + +//-------------------------------------------------------------------------- +DWORD SetupAppX::WaitForProcess( HANDLE hHandle ) +{ + DWORD nResult = NOERROR; + boolean bLoop = true; + + MSG aMsg; + ZeroMemory( (void*) &aMsg, sizeof(MSG) ); + + while ( bLoop ) + { + switch ( WIN::MsgWaitForMultipleObjects( 1, &hHandle, false, + INFINITE, QS_ALLINPUT ) ) + { + case WAIT_OBJECT_0: bLoop = false; + break; + + case (WAIT_OBJECT_0 + 1): + { + if ( WIN::PeekMessage( &aMsg, NULL, NULL, NULL, PM_REMOVE ) ) + { + WIN::TranslateMessage( &aMsg ); + WIN::DispatchMessage( &aMsg ); + } + break; + } + + default: + { + nResult = WIN::GetLastError(); + bLoop = false; + } + } + } + + return nResult; +} + +//-------------------------------------------------------------------------- +void SetupAppX::Log( LPCTSTR pMessage, LPCTSTR pText ) const +{ + if ( m_pLogFile ) + { + static boolean bInit = false; + + if ( !bInit ) + { + bInit = true; + _ftprintf( m_pLogFile, TEXT("%c"), 0xfeff ); + + _tsetlocale( LC_ALL, TEXT("") ); + _ftprintf( m_pLogFile, TEXT("\nCodepage=%s\nMultiByte Codepage=[%d]\n"), + _tsetlocale( LC_ALL, NULL ), _getmbcp() ); + } + if ( pText ) + { + _ftprintf( m_pLogFile, pMessage, pText ); + OutputDebugStringFormat( pMessage, pText ); + } + else + { + _ftprintf( m_pLogFile, pMessage ); + OutputDebugStringFormat( pMessage ); + } + + fflush( m_pLogFile ); + } +} + +//-------------------------------------------------------------------------- +DWORD SetupAppX::GetNextArgument( LPCTSTR pStr, LPTSTR *pArg, LPTSTR *pNext, + boolean bStripQuotes ) +{ + boolean bInQuotes = false; + boolean bFoundArgEnd = false; + LPCTSTR pChar = pStr; + LPCTSTR pFirst = NULL; + + if ( NULL == pChar ) + return ERROR_NO_MORE_ITEMS; + + while ( ' ' == (*pChar) || '\t' == (*pChar) ) + pChar = CharNext( pChar ); + + if ( '\0' == (*pChar) ) + return ERROR_NO_MORE_ITEMS; + + int nCount = 1; + pFirst = pChar; + + while ( ! bFoundArgEnd ) + { + if ( '\0' == (*pChar) ) + bFoundArgEnd = true; + else if ( !bInQuotes && ' ' == (*pChar) ) + bFoundArgEnd = true; + else if ( !bInQuotes && '\t' == (*pChar) ) + bFoundArgEnd = true; + else + { + if ( '\"' == (*pChar) ) + { + bInQuotes = !bInQuotes; + if ( bStripQuotes ) + { + if ( pChar == pFirst ) + pFirst = CharNext( pFirst ); + nCount -= 1; + } + } + + pChar = CharNext( pChar ); + nCount += 1; + } + } + + if ( pArg ) + { + *pArg = new TCHAR[ nCount ]; + StringCchCopyN ( *pArg, nCount, pFirst, nCount-1 ); + } + + if ( pNext ) + *pNext = CharNext( pChar ); + + return ERROR_SUCCESS; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::GetCmdLineParameters( LPTSTR *pCmdLine ) +{ + int nRet = ERROR_SUCCESS; + LPTSTR pStart = NULL; + LPTSTR pNext = NULL; + + if ( GetNextArgument( *pCmdLine, NULL, &pNext ) != ERROR_SUCCESS ) + { + SetError( ERROR_NO_MORE_ITEMS ); + return false; + } + + int nSize = lstrlen( *pCmdLine ) + 2; + TCHAR *pNewCmdLine = new TCHAR[ nSize ]; + pNewCmdLine[0] = '\0'; + + while ( GetNextArgument( pNext, &pStart, &pNext ) == ERROR_SUCCESS ) + { + boolean bDeleteStart = true; + + if ( (*pStart) == '/' || (*pStart) == '-' ) + { + LPTSTR pSub = CharNext( pStart ); + if ( (*pSub) == 'l' || (*pSub) == 'L' ) + { + pSub = CharNext( pSub ); + if ( (*pSub) == 'a' || (*pSub) == 'A' ) + { // --- handle the lang parameter --- + LPTSTR pLanguage = NULL; + LPTSTR pLastChar; + if ( GetNextArgument( pNext, &pLanguage, &pNext, true ) != ERROR_SUCCESS ) + { + StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pStart ); + nRet = ERROR_INVALID_PARAMETER; + break; + } + + m_nLanguageID = _tcstol( pLanguage, &pLastChar, 10 ); + delete [] pLanguage; + } + else + { // --- handle the l(og) parameter --- + boolean bAppend = false; + LPTSTR pFileName = NULL; + + while ( *pSub ) + { + if ( *pSub == '+' ) + { + bAppend = true; + break; + } + pSub = CharNext( pSub ); + } + + if ( GetNextArgument( pNext, &pFileName, &pNext, true ) != ERROR_SUCCESS ) + { + StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pStart ); + nRet = ERROR_INVALID_PARAMETER; + break; + } + + if ( FAILED( StringCchCat( pNewCmdLine, nSize, pStart ) ) ) + { + nRet = ERROR_OUTOFMEMORY; + break; + } + // we need to append a '+' otherwise msiexec would overwrite our log file + if ( !bAppend && FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( "+" ) ) ) ) + { + nRet = ERROR_OUTOFMEMORY; + break; + } + if ( FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( " \"" ) ) ) || + FAILED( StringCchCat( pNewCmdLine, nSize, pFileName ) ) || + FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( "\" " ) ) ) ) + { + nRet = ERROR_OUTOFMEMORY; + break; + } + + if ( bAppend ) + m_pLogFile = _tfopen( pFileName, TEXT( "ab" ) ); + else + m_pLogFile = _tfopen( pFileName, TEXT( "wb" ) ); + + delete [] pFileName; + } + } + else if ( (*pSub) == 'q' || (*pSub) == 'Q' ) + { // --- Handle quiet file parameter --- + pSub = CharNext( pSub ); + if ( ! (*pSub) || (*pSub) == 'n' || (*pSub) == 'N' ) + m_bQuiet = true; + + if ( FAILED( StringCchCat( pNewCmdLine, nSize, pStart ) ) || + FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( " " ) ) ) ) + { + nRet = ERROR_OUTOFMEMORY; + break; + } + } + else if ( _tcsnicmp( pSub, PARAM_RUNNING, _tcslen( PARAM_RUNNING ) ) == 0 ) + { + m_bIgnoreAlreadyRunning = true; + } + else if ( _tcsnicmp( pSub, CMDLN_REG_ALL_MSO_TYPES, _tcslen( CMDLN_REG_ALL_MSO_TYPES ) ) == 0 ) + { + m_bRegAllMsoTypes = true; + } + else if ( _tcsnicmp( pSub, CMDLN_REG_NO_MSO_TYPES, _tcslen( CMDLN_REG_NO_MSO_TYPES ) ) == 0 ) + { + m_bRegNoMsoTypes = true; + } + else if ( (*pSub) == 'i' || (*pSub) == 'I' || (*pSub) == 'f' || (*pSub) == 'F' || + (*pSub) == 'p' || (*pSub) == 'P' || (*pSub) == 'x' || (*pSub) == 'X' || + (*pSub) == 'y' || (*pSub) == 'Y' || (*pSub) == 'z' || (*pSub) == 'Z' ) + { + StringCchCopy( m_pErrorText, MAX_TEXT_LENGTH, pStart ); + nRet = ERROR_INVALID_PARAMETER; + break; + } + else if ( (*pSub) == 'a' || (*pSub) == 'A' ) + { // --- Handle Adminstrative Installation --- + SetAdminInstall( true ); + } + else if ( (*pSub) == 'j' || (*pSub) == 'J' ) + { // --- Handle Adminstrative Installation --- + m_pAdvertise = pStart; + m_bQuiet = true; + bDeleteStart = false; + } + else if ( (*pSub) == '?' || (*pSub) == 'h' || (*pSub) == 'H' ) + { // --- Handle Show Usage --- + nRet = ERROR_SHOW_USAGE; + break; + } + else + { + if ( FAILED( StringCchCat( pNewCmdLine, nSize, pStart ) ) || + FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( " " ) ) ) ) + { + nRet = ERROR_OUTOFMEMORY; + break; + } + } + } + else + { + if ( FAILED( StringCchCat( pNewCmdLine, nSize, pStart ) ) || + FAILED( StringCchCat( pNewCmdLine, nSize, TEXT( " " ) ) ) ) + { + nRet = ERROR_OUTOFMEMORY; + break; + } + } + + if ( bDeleteStart ) delete [] pStart; + pStart = NULL; + } + + if ( pStart ) delete [] pStart; + + *pCmdLine = pNewCmdLine; + + if ( nRet != ERROR_SUCCESS ) + { + SetError( nRet ); + return false; + } + else + return true;; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::IsAdmin() +{ + PSID aPsidAdmin; + SID_IDENTIFIER_AUTHORITY aAuthority = SECURITY_NT_AUTHORITY; + + if ( !AllocateAndInitializeSid( &aAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, + &aPsidAdmin ) ) + return false; + + BOOL bIsAdmin = FALSE; + + if ( GetOSVersion() >= 5 ) + { + HMODULE hAdvapi32 = LoadLibrary( ADVAPI32_DLL ); + + if ( !hAdvapi32 ) + bIsAdmin = FALSE; + else + { + PFnCheckTokenMembership pfnCheckTokenMembership = (PFnCheckTokenMembership) GetProcAddress( hAdvapi32, ADVAPI32API_CheckTokenMembership); + if ( !pfnCheckTokenMembership || !pfnCheckTokenMembership( NULL, aPsidAdmin, &bIsAdmin ) ) + bIsAdmin = FALSE; + } + FreeLibrary( hAdvapi32 ); + } + else + { + // NT4, check groups of user + HANDLE hAccessToken = 0; + UCHAR *szInfoBuffer = new UCHAR[ 1024 ]; // may need to resize if TokenInfo too big + DWORD dwInfoBufferSize = 1024; + DWORD dwRetInfoBufferSize = 0; + UINT i=0; + + if ( WIN::OpenProcessToken( WIN::GetCurrentProcess(), TOKEN_READ, &hAccessToken ) ) + { + bool bSuccess = false; + bSuccess = WIN::GetTokenInformation( hAccessToken, TokenGroups, + szInfoBuffer, dwInfoBufferSize, + &dwRetInfoBufferSize ) == TRUE; + + if( dwRetInfoBufferSize > dwInfoBufferSize ) + { + delete [] szInfoBuffer; + szInfoBuffer = new UCHAR[ dwRetInfoBufferSize ]; + dwInfoBufferSize = dwRetInfoBufferSize; + bSuccess = WIN::GetTokenInformation( hAccessToken, TokenGroups, + szInfoBuffer, dwInfoBufferSize, + &dwRetInfoBufferSize ) == TRUE; + } + + WIN::CloseHandle( hAccessToken ); + + if ( bSuccess ) + { + PTOKEN_GROUPS pGroups = (PTOKEN_GROUPS)(UCHAR*) szInfoBuffer; + for( i=0; i<pGroups->GroupCount; i++ ) + { + if( WIN::EqualSid( aPsidAdmin, pGroups->Groups[i].Sid ) ) + { + bIsAdmin = TRUE; + break; + } + } + } + + delete [] szInfoBuffer; + } + } + + WIN::FreeSid( aPsidAdmin ); + + return bIsAdmin ? true : false; +} + +//-------------------------------------------------------------------------- +LPTSTR SetupAppX::CopyIniFile( LPCTSTR pIniFile ) +{ + m_pTmpName = _ttempnam( TEXT( "C:\\" ), TEXT( "Setup" ) ); + + if ( !m_pTmpName ) + { + Log( TEXT( "ERROR: Could not create temp file\n" ) ); + return NULL; + } + + FILE *pOut = _tfopen( m_pTmpName, TEXT( "wb" ) ); + FILE *pIn = _tfopen( pIniFile, TEXT( "rb" ) ); + + if ( pOut && pIn ) + { + size_t nRead, nWritten; + BYTE pBuf[1024]; + + nRead = fread( pBuf, sizeof( BYTE ), 1024, pIn ); + while ( nRead && !ferror( pIn ) ) + { + nWritten = fwrite( pBuf, sizeof( BYTE ), nRead, pOut ); + if ( nWritten != nRead ) + { + Log( TEXT( "ERROR: Could not write all bytes to temp file\n" ) ); + break; + } + nRead = fread( pBuf, sizeof( BYTE ), 1024, pIn ); + } + } + + if ( pOut ) fclose( pOut ); + if ( pIn ) fclose( pIn ); + + return m_pTmpName; +} + +//-------------------------------------------------------------------------- +void SetupAppX::ConvertNewline( LPTSTR pText ) const +{ + int i=0; + + while ( pText[i] != 0 ) + { + if ( ( pText[i] == '\\' ) && ( pText[i+1] == 'n' ) ) + { + pText[i] = 0x0d; + pText[i+1] = 0x0a; + i+=2; + } + else + i+=1; + } +} + +//-------------------------------------------------------------------------- +LPTSTR SetupAppX::SetProdToAppTitle( LPCTSTR pProdName ) +{ + if ( !pProdName ) return m_pAppTitle; + + LPTSTR pAppProdTitle = new TCHAR[ MAX_STR_CAPTION ]; + pAppProdTitle[0] = '\0'; + + WIN::LoadString( m_hInst, IDS_APP_PROD_TITLE, pAppProdTitle, MAX_STR_CAPTION ); + + int nAppLen = lstrlen( pAppProdTitle ); + int nProdLen = lstrlen( pProdName ); + + if ( ( nAppLen == 0 ) || ( nProdLen == 0 ) ) + { + delete [] pAppProdTitle; + return m_pAppTitle; + } + + int nLen = nAppLen + nProdLen + 3; + + if ( nLen > STRSAFE_MAX_CCH ) return m_pAppTitle; + + LPTSTR pIndex = _tcsstr( pAppProdTitle, PRODUCT_NAME_VAR ); + + if ( pIndex ) + { + int nOffset = pIndex - pAppProdTitle; + int nVarLen = lstrlen( PRODUCT_NAME_VAR ); + + LPTSTR pNewTitle = new TCHAR[ nLen ]; + pNewTitle[0] = '\0'; + + if ( nOffset > 0 ) + { + StringCchCopyN( pNewTitle, nLen, pAppProdTitle, nOffset ); + } + + StringCchCat( pNewTitle, nLen, pProdName ); + + if ( nOffset + nVarLen < nAppLen ) + { + StringCchCat( pNewTitle, nLen, pIndex + nVarLen ); + } + + delete [] m_pAppTitle; + m_pAppTitle = pNewTitle; + } + + delete [] pAppProdTitle; + + return m_pAppTitle; +} + + +//-------------------------------------------------------------------------- +boolean SetupAppX::IsPatchInstalled( TCHAR* pBaseDir, TCHAR* pFileName ) +{ + if ( !m_bSupportsPatch ) + return false; + + PMSIHANDLE hSummaryInfo; + int nLen = lstrlen( pBaseDir ) + lstrlen( pFileName ) + 1; + TCHAR *szDatabasePath = new TCHAR [ nLen ]; + TCHAR sBuf[80]; + + StringCchCopy( szDatabasePath, nLen, pBaseDir ); + StringCchCat( szDatabasePath, nLen, pFileName ); + + UINT nRet = MsiGetSummaryInformation( NULL, szDatabasePath, 0, &hSummaryInfo ); + + if ( nRet != ERROR_SUCCESS ) + { + StringCchPrintf( sBuf, 80, TEXT("ERROR: IsPatchInstalled: MsiGetSummaryInformation returned %u.\r\n"), nRet ); + Log( sBuf ); + return false; + } + + UINT uiDataType; + LPTSTR szPatchID = new TCHAR[ 64 ]; + DWORD cchValueBuf = 64; + nRet = MsiSummaryInfoGetProperty( hSummaryInfo, PID_REVNUMBER, &uiDataType, NULL, NULL, szPatchID, &cchValueBuf ); + + if ( nRet != ERROR_SUCCESS ) + { + StringCchPrintf( sBuf, 80, TEXT("ERROR: IsPatchInstalled: MsiSummaryInfoGetProperty returned %u.\r\n"), nRet ); + Log( sBuf ); + return false; + } + + nRet = MsiGetPatchInfo( szPatchID, INSTALLPROPERTY_LOCALPACKAGE, NULL, NULL ); + + StringCchPrintf( sBuf, 80, TEXT(" GetPatchInfo for (%s) returned (%u)\r\n"), szPatchID, nRet ); + Log( sBuf ); + + delete []szPatchID; + + if ( nRet == ERROR_BAD_CONFIGURATION ) + return false; + else if ( nRet == ERROR_INVALID_PARAMETER ) + return false; + else if ( nRet == ERROR_MORE_DATA ) + return true; + else if ( nRet == ERROR_SUCCESS ) + return true; + else if ( nRet == ERROR_UNKNOWN_PRODUCT ) + return false; + else if ( nRet == ERROR_UNKNOWN_PROPERTY ) + return false; + else return false; + + return false; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::InstallRuntimes( TCHAR *sProductCode, TCHAR *sRuntimePath ) +{ + INSTALLSTATE nRet = MsiQueryProductState( sProductCode ); + OutputDebugStringFormat( TEXT( "MsiQueryProductState returned <%d>\r\n" ), nRet ); + if ( nRet == INSTALLSTATE_DEFAULT ) + return true; + + Log( TEXT( " Will install runtime <%s>\r\n" ), sRuntimePath ); + OutputDebugStringFormat( TEXT( " Will install runtime <%s>\r\n" ), sRuntimePath ); + + STARTUPINFO aSUI; + PROCESS_INFORMATION aPI; + + ZeroMemory( (void*)&aPI, sizeof( PROCESS_INFORMATION ) ); + ZeroMemory( (void*)&aSUI, sizeof( STARTUPINFO ) ); + + aSUI.cb = sizeof(STARTUPINFO); + aSUI.dwFlags = STARTF_USESHOWWINDOW; + aSUI.wShowWindow = SW_SHOW; + + DWORD nCmdLineLength = lstrlen( sRuntimePath ) + lstrlen( PARAM_SILENTINSTALL ) + 2; + TCHAR *sCmdLine = new TCHAR[ nCmdLineLength ]; + + if ( FAILED( StringCchCopy( sCmdLine, nCmdLineLength, sRuntimePath ) ) || + FAILED( StringCchCat( sCmdLine, nCmdLineLength, PARAM_SILENTINSTALL ) ) ) + { + delete [] sCmdLine; + SetError( ERROR_INSTALL_FAILURE ); + return false; + } + + if ( !WIN::CreateProcess( NULL, sCmdLine, NULL, NULL, FALSE, + CREATE_DEFAULT_ERROR_MODE, NULL, NULL, + &aSUI, &aPI ) ) + { + Log( TEXT( "ERROR: Could not create process %s.\r\n" ), sCmdLine ); + SetError( WIN::GetLastError() ); + delete [] sCmdLine; + return false; + } + + DWORD nResult = WaitForProcess( aPI.hProcess ); + bool bRet = true; + + if( ERROR_SUCCESS != nResult ) + { + Log( TEXT( "ERROR: While waiting for %s.\r\n" ), sCmdLine ); + SetError( nResult ); + bRet = false; + } + else + { + GetExitCodeProcess( aPI.hProcess, &nResult ); + SetError( nResult ); + + if ( nResult != ERROR_SUCCESS ) + { + TCHAR sBuf[80]; + StringCchPrintf( sBuf, 80, TEXT("Warning: install runtime returned %u.\r\n"), nResult ); + Log( sBuf ); + } + else + Log( TEXT( " Installation of runtime completed successfully.\r\n" ) ); + } + + CloseHandle( aPI.hProcess ); + + delete [] sCmdLine; + + return bRet; +} + +//-------------------------------------------------------------------------- +boolean SetupAppX::InstallRuntimes() +{ + TCHAR *sRuntimePath = 0; + SYSTEM_INFO siSysInfo; + + HMODULE hKernel32 = ::LoadLibrary(_T("Kernel32.dll")); + if ( hKernel32 != NULL ) + { + typedef void (CALLBACK* pfnGetNativeSystemInfo_t)(LPSYSTEM_INFO); + pfnGetNativeSystemInfo_t pfnGetNativeSystemInfo; + pfnGetNativeSystemInfo = (pfnGetNativeSystemInfo_t)::GetProcAddress(hKernel32, "GetNativeSystemInfo"); + if ( pfnGetNativeSystemInfo != NULL ) + { + pfnGetNativeSystemInfo(&siSysInfo); + } + else + { + // GetNativeSystemInfo does not exist. Maybe the code is running under Windows 2000. + // Use GetSystemInfo instead. + GetSystemInfo(&siSysInfo); + } + FreeLibrary(hKernel32); + } + else + { + // Failed to check Kernel32.dll. There may be something wrong. + // Use GetSystemInfo instead anyway. + GetSystemInfo(&siSysInfo); + } + + OutputDebugStringFormat( TEXT( "found architecture<%d>\r\n" ), siSysInfo.wProcessorArchitecture ); + + if ( siSysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ) + { + if ( GetPathToFile( RUNTIME_X64_NAME, &sRuntimePath ) ) + InstallRuntimes( PRODUCTCODE_X64, sRuntimePath ); + else + Log( TEXT( "ERROR: no installer for x64 runtime libraries found!" ) ); + + if ( sRuntimePath ) + { + delete [] sRuntimePath; + sRuntimePath = 0; + } + } + + if ( GetPathToFile( RUNTIME_X86_NAME, &sRuntimePath ) ) + InstallRuntimes( PRODUCTCODE_X86, sRuntimePath ); + else + Log( TEXT( "ERROR: no installer for x86 runtime libraries found!" ) ); + + if ( sRuntimePath ) + delete [] sRuntimePath; + + return true; +} + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +LanguageDataX::LanguageDataX( LPTSTR pData ) +{ + m_nLanguageID = 0; + m_pTransform = NULL; + + LPTSTR pLastChar; + + m_nLanguageID = _tcstol( pData, &pLastChar, 10 ); + + if ( *pLastChar == ',' ) + { + pLastChar += 1; + int nLen = lstrlen( pLastChar ) + 1; + m_pTransform = new TCHAR [ nLen ]; + StringCchCopy( m_pTransform, nLen, pLastChar ); + } +} + +//-------------------------------------------------------------------------- +LanguageDataX::~LanguageDataX() +{ + if ( m_pTransform ) delete [] m_pTransform; +} + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +SetupApp* Create_SetupAppX() +{ + return new SetupAppX; +} + +//-------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/setup/setup.hxx b/desktop/win32/source/setup/setup.hxx new file mode 100644 index 000000000000..c3bb71cb3fc6 --- /dev/null +++ b/desktop/win32/source/setup/setup.hxx @@ -0,0 +1,157 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "setup_main.hxx" + +//-------------------------------------------------------------------------- + +#ifdef SetupAppX + #undef SetupAppX +#endif + +#ifdef Create_SetupAppX + #undef Create_SetupAppX +#endif + +#ifdef LanguageDataX + #undef LanguageDataX +#endif + + +#ifdef UNICODE + #define SetupAppX SetupAppW + #define Create_SetupAppX Create_SetupAppW + #define LanguageDataX LanguageDataW +#else + #define SetupAppX SetupAppA + #define Create_SetupAppX Create_SetupAppA + #define LanguageDataX LanguageDataA +#endif + +//-------------------------------------------------------------------------- + +struct LanguageDataX +{ + long m_nLanguageID; + LPTSTR m_pTransform; + + LanguageDataX( LPTSTR pData ); + ~LanguageDataX(); +}; + +//-------------------------------------------------------------------------- + +class SetupAppX : public SetupApp +{ + HINSTANCE m_hInst; + HANDLE m_hMapFile; + LPTSTR m_pAppTitle; + LPTSTR m_pCmdLine; + LPTSTR m_pDatabase; + LPTSTR m_pReqVersion; + LPTSTR m_pProductName; + LPTSTR m_pAdvertise; + LPTSTR m_pTmpName; + LPTSTR m_pErrorText; + LPTSTR m_pModuleFile; + LPTSTR m_pPatchFiles; + LPCTSTR m_pUpgradeKey; + LPCTSTR m_pProductVersion; + int *m_pMSIErrorCode; + + boolean m_bQuiet : 1; + boolean m_bIgnoreAlreadyRunning : 1; + boolean m_bRegNoMsoTypes :1; + boolean m_bRegAllMsoTypes :1; + boolean m_bIsMinorUpgrade :1; + boolean m_bSupportsPatch :1; + + FILE *m_pLogFile; + + long m_nLanguageID; + long m_nLanguageCount; + LanguageDataX** m_ppLanguageList; + +private: + + boolean GetPathToFile( TCHAR* pFileName, TCHAR **pPath ); + LPCTSTR GetPathToMSI(); + + int GetNameValue( TCHAR* pLine, TCHAR **pName, TCHAR **pValue ); + boolean GetProfileSection( LPCTSTR pFileName, LPCTSTR pSection, + DWORD& rSize, LPTSTR *pRetBuf ); + LPTSTR CopyIniFile( LPCTSTR pIniFile ); + void ConvertNewline( LPTSTR pText ) const; + + boolean LaunchInstaller( LPCTSTR pParam ); + HMODULE LoadMsiLibrary(); + DWORD WaitForProcess( HANDLE hHandle ); + + boolean GetCmdLineParameters( LPTSTR *pCmdLine ); + DWORD GetNextArgument( LPCTSTR pStr, LPTSTR *pArg, + LPTSTR *pNext, boolean bStripQuotes = false ); + boolean IsAdmin(); + + boolean GetCommandLine(); + + boolean IsTerminalServerInstalled() const; + void AddFileToPatchList( TCHAR* pPath, TCHAR* pFile ); + boolean IsPatchInstalled( TCHAR* pBaseDir, TCHAR* pFileName ); + boolean InstallRuntimes( TCHAR* pProductCode, TCHAR* pFileName ); + +public: + SetupAppX(); + ~SetupAppX(); + + virtual boolean Initialize( HINSTANCE hInst ); + virtual boolean AlreadyRunning() const; + virtual boolean ReadProfile(); + virtual boolean GetPatches(); + virtual boolean ChooseLanguage( long& rLanguage ); + virtual boolean CheckVersion(); + virtual boolean CheckForUpgrade(); + virtual boolean InstallRuntimes(); + virtual boolean Install( long nLanguage ); + + virtual UINT GetError() const; + virtual void DisplayError( UINT nErr ) const; + + void Log( LPCTSTR pMessage, LPCTSTR pText = NULL ) const; + + long GetLanguageCount() const { return m_nLanguageCount; } + long GetLanguageID( long nIndex ) const; + void GetLanguageName( long nLanguage, LPTSTR sName ) const; + + LPCTSTR GetAppTitle() const { return m_pAppTitle; } + LPTSTR SetProdToAppTitle( LPCTSTR pProdName ); + HINSTANCE GetHInst() const { return m_hInst; } +}; + +//-------------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/setup/setup.ico b/desktop/win32/source/setup/setup.ico Binary files differnew file mode 100644 index 000000000000..2a7ebda53a25 --- /dev/null +++ b/desktop/win32/source/setup/setup.ico diff --git a/desktop/win32/source/setup/setup.ulf b/desktop/win32/source/setup/setup.ulf new file mode 100644 index 000000000000..d0e867d49f3f --- /dev/null +++ b/desktop/win32/source/setup/setup.ulf @@ -0,0 +1,162 @@ +[%APP_TITLE%] +en-US = "Setup" + + +[%APP_PROD_TITLE%] +en-US = "The %PRODUCTNAME Setup" + + +[%OUTOFMEM%] +en-US = "Out of Memory" + + +[%NOMSI%] +en-US = "Setup was unable to find the msi package." + + +[%USER_CANCELLED%] +en-US = "Setup was cancelled" + + +[%REQUIRES_ADMIN_PRIV%] +en-US = "Administrator privileges are required for upgrading the Windows Installer." + + +[%FILE_NOT_FOUND%] +en-US = "Setup was unable to find the file '%s'." + + +[%INVALID_PARAM%] +en-US = "Invalid command line option '%s'. Please use '/?' for help." + + +[%SETUP_TO_OLD%] +en-US = "This package requires at least the version '%s' of the Windows Installer. \nYou have Windows Installer '%s' on your system!" + +[%SETUP_NOT_FOUND%] +en-US = "This package requires the Windows Installer. \nYou need at least Windows Installer '%s' on your system!" + + +[%USAGE%] +en-US = "Usage:\n /? : Shows this dialog.\n /a : Performs an administrative installation.\n /j[u|m] : Performs an advertising installation.\n /q[n] : Do not show any user interface (silent mode).\n" + + +[%ALREADY_RUNNING%] +en-US = "There is already a setup process running." + + +[%UNKNOWN_ERROR%] +en-US = "An Unknown Error occured!" + + +[%INVALID_PROFILE%] +en-US = "Invalid or incomplete profile." + + +[%UNKNOWN_LANG%] +en-US = "Unknown Language: %d" + + +[%LANGUAGE_ZH_TW%] +en-US = "Chinese (traditional)" + + +[%LANGUAGE_CS%] +en-US = "Czech" + + +[%LANGUAGE_DA%] +en-US = "Danish" + + +[%LANGUAGE_DE_DE%] +en-US = "German (Germany)" + + +[%LANGUAGE_EL%] +en-US = "Greek" + + +[%LANGUAGE_EN_US%] +en-US = "English (USA)" + + +[%LANGUAGE_ES%] +en-US = "Spanish (Spain)" + + +[%LANGUAGE_FI%] +en-US = "Finnish" + + +[%LANGUAGE_FR_FR%] +en-US = "French (France)" + + +[%LANGUAGE_HE%] +en-US = "Hebrew" + + +[%LANGUAGE_HU%] +en-US = "Hungarian" + + +[%LANGUAGE_IT_IT%] +en-US = "Italian (Italy)" + + +[%LANGUAGE_JA%] +en-US = "Japanese" + + +[%LANGUAGE_KO%] +en-US = "Korean" + + +[%LANGUAGE_NL_NL%] +en-US = "Dutch (Netherlands)" + + +[%LANGUAGE_NO_NO%] +en-US = "Norwegian (Bokmål)" + + +[%LANGUAGE_PL%] +en-US = "Polish" + + +[%LANGUAGE_PT_BR%] +en-US = "Portuguese (Brazil)" + + +[%LANGUAGE_RU%] +en-US = "Russian" + + +[%LANGUAGE_SK%] +en-US = "Slovakian" + + +[%LANGUAGE_SV_SE%] +en-US = "Swedish (Sweden)" + + +[%LANGUAGE_TH%] +en-US = "Thai" + + +[%LANGUAGE_TR%] +en-US = "Turkish" + + +[%LANGUAGE_ET%] +en-US = "Estonian" + + +[%LANGUAGE_ZH_CN%] +en-US = "Chinese (Simplified)" + + +[%LANGUAGE_PT_PT%] +en-US = "Portuguese (Portugal)" + diff --git a/desktop/win32/source/setup/setup_a.cxx b/desktop/win32/source/setup/setup_a.cxx new file mode 100644 index 000000000000..b3cb31bea40a --- /dev/null +++ b/desktop/win32/source/setup/setup_a.cxx @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "setup.cpp" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/setup/setup_help.hxx b/desktop/win32/source/setup/setup_help.hxx new file mode 100644 index 000000000000..f37daa5be37e --- /dev/null +++ b/desktop/win32/source/setup/setup_help.hxx @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 SETUP_HELP_HXX +#define SETUP_HELP_HXX + +//-------------------------------------------------------------------------- + + +#ifdef UNICODE +#else + #define LanguageDataX LanguageDataA +#endif + +//-------------------------------------------------------------------------- + +class SetupHelperX +{ +}; + +//-------------------------------------------------------------------------- + +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/setup/setup_main.cxx b/desktop/win32/source/setup/setup_main.cxx new file mode 100644 index 000000000000..effd3de52ed8 --- /dev/null +++ b/desktop/win32/source/setup/setup_main.cxx @@ -0,0 +1,144 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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" + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#include <new> + +#include "setup_main.hxx" + +//-------------------------------------------------------------------------- + +void __cdecl newhandler() +{ + throw std::bad_alloc(); + return; +} + +//-------------------------------------------------------------------------- + +SetupApp::SetupApp() +{ + m_uiRet = ERROR_SUCCESS; + + // Get OS version + OSVERSIONINFO sInfoOS; + + ZeroMemory( &sInfoOS, sizeof(OSVERSIONINFO) ); + sInfoOS.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); + + GetVersionEx( &sInfoOS ); + + m_nOSVersion = sInfoOS.dwMajorVersion; + m_nMinorVersion = sInfoOS.dwMinorVersion; + m_bNeedReboot = false; + m_bAdministrative = false; +} + +//-------------------------------------------------------------------------- + +SetupApp::~SetupApp() +{ +} + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- + +extern "C" int __stdcall WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int ) +{ + // Get OS version + OSVERSIONINFO sInfoOS; + + ZeroMemory( &sInfoOS, sizeof(OSVERSIONINFO) ); + sInfoOS.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); + + GetVersionEx( &sInfoOS ); + + SetupApp *pSetup; + + pSetup = Create_SetupAppW(); + + try + { + if ( ! pSetup->Initialize( hInst ) ) + throw pSetup->GetError(); + + if ( pSetup->AlreadyRunning() ) + throw (UINT) ERROR_INSTALL_ALREADY_RUNNING; + + if ( ! pSetup->ReadProfile() ) + throw pSetup->GetError(); + + if ( ! pSetup->CheckVersion() ) + throw pSetup->GetError(); + + if ( ! pSetup->IsAdminInstall() ) + if ( ! pSetup->GetPatches() ) + throw pSetup->GetError(); + + // CheckForUpgrade() has to be called after calling GetPatches()! + if ( ! pSetup->CheckForUpgrade() ) + throw pSetup->GetError(); + + long nLanguage; + + if ( ! pSetup->ChooseLanguage( nLanguage ) ) + throw pSetup->GetError(); + + if ( ! pSetup->InstallRuntimes() ) + throw pSetup->GetError(); + + if ( ! pSetup->Install( nLanguage ) ) + throw pSetup->GetError(); + } + catch ( std::bad_alloc ) + { + pSetup->DisplayError( ERROR_OUTOFMEMORY ); + } + catch ( UINT nErr ) + { + pSetup->DisplayError( nErr ); + } + + int nRet = pSetup->GetError(); + + delete pSetup; + + return nRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/setup/setup_main.hxx b/desktop/win32/source/setup/setup_main.hxx new file mode 100644 index 000000000000..f966e6ae0348 --- /dev/null +++ b/desktop/win32/source/setup/setup_main.hxx @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 SETUP_MAIN_HXX +#define SETUP_MAIN_HXX + +class SetupApp +{ + DWORD m_nOSVersion; + DWORD m_nMinorVersion; + boolean m_bNeedReboot : 1; + boolean m_bAdministrative : 1; + +public: + UINT m_uiRet; + + SetupApp(); + virtual ~SetupApp(); + + virtual boolean Initialize( HINSTANCE hInst ) = 0; + virtual boolean AlreadyRunning() const = 0; + virtual boolean ReadProfile() = 0; + virtual boolean GetPatches() = 0; + virtual boolean ChooseLanguage( long& rLanguage ) = 0; + virtual boolean CheckVersion() = 0; + virtual boolean CheckForUpgrade() = 0; + virtual boolean InstallRuntimes() = 0; + virtual boolean Install( long nLanguage ) = 0; + + virtual UINT GetError() const = 0; + virtual void DisplayError( UINT nErr ) const = 0; + + void SetError( UINT nErr ) { m_uiRet = nErr; } + DWORD GetOSVersion() const { return m_nOSVersion; } + DWORD GetMinorVersion() const { return m_nMinorVersion; } + + boolean IsAdminInstall() { return m_bAdministrative; } + void SetAdminInstall( boolean bValue ) { m_bAdministrative = bValue; } + + void SetRebootNeeded( boolean bNeedReboot ) { m_bNeedReboot = bNeedReboot; } + boolean NeedReboot() const { return m_bNeedReboot; } +}; + +SetupApp* Create_SetupAppW(); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/setup/setup_w.cxx b/desktop/win32/source/setup/setup_w.cxx new file mode 100644 index 000000000000..d123eeb350e6 --- /dev/null +++ b/desktop/win32/source/setup/setup_w.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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" + +#define UNICODE 1 +#define _UNICODE 1 + +#include "setup.cpp" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/sowrapper.cxx b/desktop/win32/source/sowrapper.cxx new file mode 100644 index 000000000000..b7020f09c595 --- /dev/null +++ b/desktop/win32/source/sowrapper.cxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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" + +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#include "main.h" + +int APIENTRY WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) +{ + if ( (LONG)GetVersion() < 0 ) + return MainA(); + else + return MainW(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/unoinfo.cxx b/desktop/win32/source/unoinfo.cxx new file mode 100644 index 000000000000..6ec5727a3603 --- /dev/null +++ b/desktop/win32/source/unoinfo.cxx @@ -0,0 +1,151 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 <cstddef> +#include <stdio.h> +#include <stdlib.h> +#include <wchar.h> + +#define WIN32_LEAN_AND_MEAN +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +#include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#include "tools/pathutils.hxx" + +#define MY_LENGTH(s) (sizeof (s) / sizeof *(s) - 1) +#define MY_STRING(s) (s), MY_LENGTH(s) + +namespace { + +wchar_t * getBrandPath(wchar_t * path) { + DWORD n = GetModuleFileNameW(NULL, path, MAX_PATH); + if (n == 0 || n >= MAX_PATH) { + exit(EXIT_FAILURE); + } + return tools::filename(path); +} + +void writeNull() { + if (fwrite("\0\0", 1, 2, stdout) != 2) { + exit(EXIT_FAILURE); + } +} + +void writePath( + wchar_t const * frontBegin, wchar_t const * frontEnd, + wchar_t const * backBegin, std::size_t backLength) +{ + wchar_t path[MAX_PATH]; + wchar_t * end = tools::buildPath( + path, frontBegin, frontEnd, backBegin, backLength); + if (end == NULL) { + exit(EXIT_FAILURE); + } + std::size_t n = (end - path) * sizeof (wchar_t); + if (fwrite(path, 1, n, stdout) != n) { + exit(EXIT_FAILURE); + } +} + +} + +#ifdef __MINGW32__ +int main(int argc, char ** argv, char **) { + if (argc == 2 && strcmp(argv[1], "c++") == 0) { +#else +int wmain(int argc, wchar_t ** argv, wchar_t **) { + if (argc == 2 && wcscmp(argv[1], L"c++") == 0) { +#endif + wchar_t path[MAX_PATH]; + wchar_t * pathEnd = getBrandPath(path); + if (tools::buildPath(path, path, pathEnd, MY_STRING(L"..\\basis-link")) + == NULL) + { + exit(EXIT_FAILURE); + } + pathEnd = tools::resolveLink(path); + if (pathEnd == NULL || + (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\ure-link")) == + NULL)) + { + exit(EXIT_FAILURE); + } + pathEnd = tools::resolveLink(path); + if (pathEnd == NULL) { + exit(EXIT_FAILURE); + } + writePath(path, pathEnd, MY_STRING(L"\\bin")); +#ifdef __MINGW32__ + } else if (argc == 2 && strcmp(argv[1], "java") == 0) { +#else + } else if (argc == 2 && wcscmp(argv[1], L"java") == 0) { +#endif + if (fwrite("1", 1, 1, stdout) != 1) { + exit(EXIT_FAILURE); + } + wchar_t path[MAX_PATH]; + wchar_t * pathEnd = getBrandPath(path); + writePath(path, pathEnd, MY_STRING(L"")); + if (tools::buildPath(path, path, pathEnd, MY_STRING(L"..\\basis-link")) + == NULL) + { + exit(EXIT_FAILURE); + } + pathEnd = tools::resolveLink(path); + if (pathEnd == NULL) { + exit(EXIT_FAILURE); + } + writeNull(); + writePath(path, pathEnd, MY_STRING(L"\\program\\classes\\unoil.jar")); + if (tools::buildPath(path, path, pathEnd, MY_STRING(L"\\ure-link")) == + NULL) + { + exit(EXIT_FAILURE); + } + pathEnd = tools::resolveLink(path); + if (pathEnd == NULL) { + exit(EXIT_FAILURE); + } + writeNull(); + writePath(path, pathEnd, MY_STRING(L"\\java\\ridl.jar")); + writeNull(); + writePath(path, pathEnd, MY_STRING(L"\\java\\jurt.jar")); + writeNull(); + writePath(path, pathEnd, MY_STRING(L"\\java\\juh.jar")); + } else { + exit(EXIT_FAILURE); + } + exit(EXIT_SUCCESS); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/wrapper.h b/desktop/win32/source/wrapper.h new file mode 100644 index 000000000000..6ccf063b36a5 --- /dev/null +++ b/desktop/win32/source/wrapper.h @@ -0,0 +1,175 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#pragma once +#ifndef __cplusplus +#error Need C++ to compile +#endif + +#include "main.h" + +#ifndef _WINDOWS_ +#if defined _MSC_VER +#pragma warning(push, 1) +#endif +# include <windows.h> +#if defined _MSC_VER +#pragma warning(pop) +#endif +#endif + + +#ifndef _INC_TCHAR +# ifdef UNICODE +# define _UNICODE +# endif +# include <tchar.h> +#endif + +#ifdef UNICODE +# define Main MainW +# define GetArgv( pArgc ) CommandLineToArgvW( GetCommandLine(), pArgc ) +# define PROCESS_CREATIONFLAGS CREATE_UNICODE_ENVIRONMENT +#else +# define GetArgv( pArgc ) (*pArgc = __argc, __argv) +# define PROCESS_CREATIONFLAGS 0 +# define Main MainA +#endif + +#define BIN_EXT_STR TEXT(".bin") +#define PARAM_LIBPATH_STR TEXT("-libpath=") +#define PARAM_LOCAL_STR TEXT("-local") +#define PARAM_REMOTE_STR TEXT("-remote") + +#if defined( REMOTE ) +#define DEFAULT_LIBPATH TEXT("remote;") +#elif defined( LOCAL ) +#define DEFAULT_LIBPATH TEXT("local;") +#endif + +extern "C" int Main() +{ + // Retreive startup info + + STARTUPINFO aStartupInfo; + + ZeroMemory( &aStartupInfo, sizeof(aStartupInfo) ); + aStartupInfo.cb = sizeof( aStartupInfo ); + GetStartupInfo( &aStartupInfo ); + + // Retrieve command line + + LPTSTR lpCommandLine = GetCommandLine(); + + LPTSTR *ppArguments = NULL; + int nArguments = 0; + + ppArguments = GetArgv( &nArguments ); + + // Calculate application name + + + TCHAR szApplicationName[MAX_PATH]; + TCHAR szDrive[MAX_PATH]; + TCHAR szDir[MAX_PATH]; + TCHAR szFileName[MAX_PATH]; + TCHAR szExt[MAX_PATH]; + + GetModuleFileName( NULL, szApplicationName, MAX_PATH ); + _tsplitpath( szApplicationName, szDrive, szDir, szFileName, szExt ); + _tmakepath( szApplicationName, szDrive, szDir, szFileName, BIN_EXT_STR ); + + // Retreive actual environment + + TCHAR szBuffer[1024]; + TCHAR szPathValue[1024] = TEXT(""); + +#ifdef DEFAULT_LIBPATH + _tmakepath( szPathValue, szDrive, szDir, DEFAULT_LIBPATH, TEXT("") ); +#endif + + for ( int argn = 1; argn < nArguments; argn++ ) + { + if ( 0 == _tcscmp( ppArguments[argn], PARAM_REMOTE_STR ) ) + { + _tmakepath( szPathValue, szDrive, szDir, TEXT("remote;"), TEXT("") ); + break; + } + else if ( 0 == _tcscmp( ppArguments[argn], PARAM_LOCAL_STR ) ) + { + _tmakepath( szPathValue, szDrive, szDir, TEXT("local;"), TEXT("") ); + break; + } + else if ( 0 == _tcsncmp( ppArguments[argn], PARAM_LIBPATH_STR, _tcslen(PARAM_LIBPATH_STR) ) ) + { + LPTSTR pFileSpec = NULL; + + GetFullPathName( ppArguments[argn] + _tcslen(PARAM_LIBPATH_STR), sizeof(szPathValue) / sizeof(TCHAR), szPathValue, &pFileSpec ); + _tcscat( szPathValue, TEXT(";") ); + break; + } + } + + GetEnvironmentVariable( TEXT("PATH"), szBuffer, sizeof(szBuffer) ); + _tcscat( szPathValue, szBuffer ); + SetEnvironmentVariable( TEXT("PATH"), szPathValue); + + LPVOID lpEnvironment = GetEnvironmentStrings(); + + + // Retrieve current directory + + TCHAR szCurrentDirectory[MAX_PATH]; + GetCurrentDirectory( MAX_PATH, szCurrentDirectory ); + + // Set the Flags + + DWORD dwCreationFlags = PROCESS_CREATIONFLAGS; + + PROCESS_INFORMATION aProcessInfo; + + BOOL fSuccess = CreateProcess( + szApplicationName, + lpCommandLine, + NULL, + NULL, + TRUE, + dwCreationFlags, + lpEnvironment, + szCurrentDirectory, + &aStartupInfo, + &aProcessInfo ); + + if ( fSuccess ) + { + DWORD dwExitCode; + + WaitForSingleObject( aProcessInfo.hProcess, INFINITE ); + fSuccess = GetExitCodeProcess( aProcessInfo.hProcess, &dwExitCode ); + + return dwExitCode; + } + + DWORD dwError = GetLastError(); + + LPVOID lpMsgBuf; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dwError, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR)&lpMsgBuf, + 0, + NULL + ); + + // Display the string. + MessageBox( NULL, (LPCTSTR)lpMsgBuf, NULL, MB_OK | MB_ICONERROR ); + + // Free the buffer. + LocalFree( lpMsgBuf ); + + return GetLastError(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/wrappera.cxx b/desktop/win32/source/wrappera.cxx new file mode 100644 index 000000000000..c9a21299229d --- /dev/null +++ b/desktop/win32/source/wrappera.cxx @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "wrapper.h" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/wrapperw.cxx b/desktop/win32/source/wrapperw.cxx new file mode 100644 index 000000000000..e6927ab82074 --- /dev/null +++ b/desktop/win32/source/wrapperw.cxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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" +#define UNICODE +#include "wrapper.h" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/zipintro/delzip b/desktop/zipintro/delzip new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/desktop/zipintro/delzip @@ -0,0 +1 @@ + diff --git a/desktop/zipintro/makefile.mk b/desktop/zipintro/makefile.mk new file mode 100644 index 000000000000..cdc547fcc5c7 --- /dev/null +++ b/desktop/zipintro/makefile.mk @@ -0,0 +1,104 @@ +#************************************************************************* +# +# 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=zipintro + +.INCLUDE : settings.mk + +ZIP1LIST= \ + $(MISC)$/$(RSCDEFIMG)$/brand$/intro.png \ + $(MISC)$/$(RSCDEFIMG)$/brand$/about.png +ZIP2LIST= \ + $(MISC)$/$(RSCDEFIMG)$/brand_dev$/intro.png \ + $(MISC)$/$(RSCDEFIMG)$/brand_dev$/about.png +ZIP3LIST= \ + $(MISC)$/$(RSCDEFIMG)$/brand$/shell$/backing_left.png \ + $(MISC)$/$(RSCDEFIMG)$/brand$/shell$/backing_right.png \ + $(MISC)$/$(RSCDEFIMG)$/brand$/shell$/backing_space.png \ + $(MISC)$/$(RSCDEFIMG)$/brand$/shell$/backing_rtl_left.png \ + $(MISC)$/$(RSCDEFIMG)$/brand$/shell$/backing_rtl_right.png + +.IF "$(ENABLE_BROFFICE)"=="TRUE" +ZIP1LIST+= \ + $(MISC)$/$(RSCDEFIMG)$/brand$/intro-pt_BR.png \ + $(MISC)$/$(RSCDEFIMG)$/brand$/about-pt_BR.png +ZIP2LIST+= \ + $(MISC)$/$(RSCDEFIMG)$/brand_dev$/intro-pt_BR.png \ + $(MISC)$/$(RSCDEFIMG)$/brand_dev$/about-pt_BR.png +ZIP3LIST+= \ + $(MISC)$/$(RSCDEFIMG)$/brand$/shell$/backing_left-pt_BR.png \ + $(MISC)$/$(RSCDEFIMG)$/brand$/shell$/backing_right-pt_BR.png +.ENDIF # ENABLE_BROFFICE + +ZIP1TARGET=brand +ZIP1DEPS=$(ZIP1LIST) +ZIP2TARGET=brand_dev +ZIP2DEPS=$(ZIP2LIST) +ZIP3TARGET=shell +ZIP3DEPS=$(ZIP3LIST) + +.INCLUDE : target.mk + +ALLTAR : \ + $(COMMONBIN)$/brand$/intro.zip \ + $(COMMONBIN)$/brand_dev$/intro.zip \ + $(COMMONBIN)$/shell/shell.zip + +$(COMMONBIN)$/brand_dev$/intro.zip : $(COMMONBIN)$/brand_dev.zip + @@-$(MKDIR) $(@:d) + @$(COPY) $< $@ + +$(COMMONBIN)$/brand$/intro.zip : $(COMMONBIN)$/brand.zip + @@-$(MKDIR) $(@:d) + @$(COPY) $< $@ + +$(COMMONBIN)$/shell$/shell.zip : $(COMMONBIN)$/shell.zip + @@-$(MKDIR) $(@:d) + @$(COPY) $< $@ + +$(MISC)$/%.bmp : $(SOLARSRC)$/%.bmp + @@-$(MKDIRHIER) $(@:d) + $(COPY) $< $@ + +$(MISC)$/%.png : $(SOLARSRC)$/%.png + @@-$(MKDIRHIER) $(@:d) + $(COPY) $< $@ + +.IF "$(INTRO_BITMAP)" != "" +$(MISC)$/$(RSCDEFIMG)$/brand$/intro.png : $(INTRO_BITMAP) + @@-$(MKDIRHIER) $(@:d) + $(COPY) $< $@ +.ENDIF + +.IF "$(ABOUT_BITMAP)" != "" +$(MISC)$/$(RSCDEFIMG)$/brand$/about.png : $(ABOUT_BITMAP) + @@-$(MKDIRHIER) $(@:d) + $(COPY) $< $@ +.ENDIF |