diff options
author | Jens-Heiner Rechtien <hr@openoffice.org> | 2004-05-10 12:06:44 +0000 |
---|---|---|
committer | Jens-Heiner Rechtien <hr@openoffice.org> | 2004-05-10 12:06:44 +0000 |
commit | 4c8f30ec2c3341874255420b1ccc2dc92b690616 (patch) | |
tree | 5f8e93280cc119344f4a232029e78533d9f87d61 /shell/source/unix/exec | |
parent | b39107a0d72918aba7dadc9f46fd07253599b927 (diff) |
INTEGRATION: CWS defaultbrowser (1.8.102); FILE MERGED
2004/05/03 10:18:57 obr 1.8.102.6: #i27120# check for !=0 instead of -1 for errors
2004/04/29 11:31:03 obr 1.8.102.5: #i27120# CDE needs special file url treatment
2004/04/29 08:00:51 obr 1.8.102.4: #i27120# removed compiler warning
2004/04/28 14:02:34 obr 1.8.102.3: #i27120# extract desltop setting from current context (not component context) and removed debug output
2004/04/28 06:18:35 obr 1.8.102.2: #i27120# mailto uris now handled correctly
2004/04/27 08:03:16 obr 1.8.102.1: #i27120# new unix shell execute service implementation
Diffstat (limited to 'shell/source/unix/exec')
-rw-r--r-- | shell/source/unix/exec/shellexec.cxx | 327 |
1 files changed, 114 insertions, 213 deletions
diff --git a/shell/source/unix/exec/shellexec.cxx b/shell/source/unix/exec/shellexec.cxx index caebb917673d..adb027d6e257 100644 --- a/shell/source/unix/exec/shellexec.cxx +++ b/shell/source/unix/exec/shellexec.cxx @@ -2,9 +2,9 @@ * * $RCSfile: shellexec.cxx,v $ * - * $Revision: 1.8 $ + * $Revision: 1.9 $ * - * last change: $Author: hr $ $Date: 2003-03-27 11:16:07 $ + * last change: $Author: hr $ $Date: 2004-05-10 13:06:44 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -67,6 +67,10 @@ #include <osl/thread.h> #endif +#ifndef _OSL_PROCESS_H_ +#include <osl/process.h> +#endif + #ifndef _OSL_FILE_HXX_ #include <osl/file.hxx> #endif @@ -79,6 +83,10 @@ #include <rtl/ustrbuf.hxx> #endif +#ifndef _RTL_URI_H_ +#include <rtl/uri.hxx> +#endif + #ifndef _SHELLEXEC_HXX_ #include "shellexec.hxx" #endif @@ -87,14 +95,9 @@ #include <com/sun/star/system/SystemShellExecuteFlags.hpp> #endif -#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_ -#include <com/sun/star/container/XNameAccess.hpp> -#endif - -#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_ -#include <com/sun/star/beans/PropertyValue.hpp> -#endif +#include "uno/current_context.hxx" +#include <string.h> #include <errno.h> #include <unistd.h> @@ -104,17 +107,12 @@ using com::sun::star::system::XSystemShellExecute; using com::sun::star::system::SystemShellExecuteException; -using com::sun::star::beans::PropertyValue; -using com::sun::star::container::NoSuchElementException; -using com::sun::star::container::XNameAccess; using rtl::OString; using rtl::OUString; using rtl::OStringBuffer; using rtl::OUStringBuffer; using osl::FileBase; -using osl::MutexGuard; -using osl::Mutex; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; @@ -125,7 +123,7 @@ using namespace cppu; // defines //------------------------------------------------------------------------ -#define SHELLEXEC_IMPL_NAME "com.sun.star.comp.system.SystemShellExecute" +#define SHELLEXEC_IMPL_NAME "com.sun.star.comp.system.SystemShellExecute2" //------------------------------------------------------------------------ // helper functions @@ -139,27 +137,57 @@ namespace // private aRet[0] = OUString::createFromAscii("com.sun.star.sys.shell.SystemShellExecute"); return aRet; } + + //------------------------------------- + + /* a slightly modified version of Pchar in rtl/source/uri.c */ + const sal_Bool uriCharClass[128] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Pchar but without encoding slashes */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* !"#$%&'()*+,-./ */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, /* 0123456789:;<=>? */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ABCDEFGHIJKLMNO */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* PQRSTUVWXYZ[\]^_ */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* `abcdefghijklmno */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /* pqrstuvwxyz{|}~ */ + }; + + //------------------------------------- + + rtl::OUString reencode_file_url(const rtl::OUString& file_url, + rtl_TextEncoding from_textenc, rtl_TextEncoding to_textenc) + { + rtl::OUString tmp = rtl::Uri::decode( + file_url, rtl_UriDecodeWithCharset, from_textenc); + + return rtl::Uri::encode( + tmp, uriCharClass, rtl_UriEncodeIgnoreEscapes, to_textenc); + } } //----------------------------------------------------------------------------------------- // //----------------------------------------------------------------------------------------- -ShellExec::ShellExec( const Reference< XMultiServiceFactory >& xServiceManager ) : - WeakComponentImplHelper3< XSystemShellExecute, XEventListener, XServiceInfo >( m_aMutex ), - m_xServiceManager( xServiceManager ) +ShellExec::ShellExec( const Reference< XComponentContext >& xContext ) : + WeakImplHelper2< XSystemShellExecute, XServiceInfo >() { try { - Reference< XComponent > xComponent = Reference< XComponent >( xServiceManager, UNO_QUERY ); + Reference< XCurrentContext > xCurrentContext(getCurrentContext()); - if( xComponent.is() ) - xComponent->addEventListener( static_cast < XEventListener * > (this) ); - } + if (xCurrentContext.is()) + { + Any aValue = xCurrentContext->getValueByName( + OUString( RTL_CONSTASCII_USTRINGPARAM( "system.desktop-environment" ) ) ); - catch( ... ) - { - m_xServiceManager.clear(); - OSL_TRACE( "ShellExec: corrupted service manager given." ); + OUString aDesktopEnvironment; + if (aValue >>= aDesktopEnvironment) + { + m_aDesktopEnvironment = OUStringToOString(aDesktopEnvironment, RTL_TEXTENCODING_ASCII_US); + } + } + } catch (RuntimeException e) { } } @@ -168,221 +196,94 @@ ShellExec::ShellExec( const Reference< XMultiServiceFactory >& xServiceManager ) //------------------------------------------------- void SAL_CALL ShellExec::execute( const OUString& aCommand, const OUString& aParameter, sal_Int32 nFlags ) - throw (IllegalArgumentException, SystemShellExecuteException, RuntimeException) + throw (IllegalArgumentException, SystemShellExecuteException, RuntimeException) { - OString aCommandLine = OUStringToOString( aCommand, osl_getThreadTextEncoding() ); + OStringBuffer aBuffer; - // check if file exists and is executable - - // if not, it is either an url or a document -// if( 0 != access( aCommandLine.getStr(), X_OK ) ) + // Check wether aCommand contains a document url or not + sal_Int32 nIndex = aCommand.indexOf( OUString( RTL_CONSTASCII_USTRINGPARAM(":/") ) ); - // for now, only execute urls - if( 1 ) + if( nIndex > 0 || 0 == aCommand.compareToAscii("mailto:", 7) ) { - OUString aURL( aCommand ); - OUString aProtocol, aHandler; - - // save this value here -// int nerr = errno; - // default error value here - int nerr = ENOEXEC; - - // find protocol specifier - sal_Int32 nIndex = aCommand.indexOf( (sal_Unicode) ':' ); - - if( nIndex > 0 ) + // It seems to be a url .. + OUString aURL(aCommand); + + // We need to re-encode file urls because osl_getFileURLFromSystemPath converts + // to UTF-8 before encoding non ascii characters, which is not what other apps + // expect. + if ( 0 == aURL.compareToAscii("file://", 7) ) + aURL = reencode_file_url(aURL, RTL_TEXTENCODING_UTF8, osl_getThreadTextEncoding()); + +#ifdef MACOSX + aBuffer.append("open"); +#else + OUString aProgramURL; + if ( osl_Process_E_None != osl_getExecutableFile(&aProgramURL.pData) ) { - // FIXME: check for valid protocols here - proposed API for rtl - - // protocol keys are stored in lower case - aProtocol = aCommand.copy( 0, nIndex ).toAsciiLowerCase(); + throw SystemShellExecuteException( + OUString(RTL_CONSTASCII_USTRINGPARAM("Cound not determine executable path")), + static_cast < XSystemShellExecute * > (this), ENOENT ); } - if( ( 0 == aProtocol.getLength() ) && - ( osl_File_E_None == FileBase::getFileURLFromSystemPath( aCommand, aURL ) ) ) + OUString aProgram; + if ( FileBase::E_None != FileBase::getSystemPathFromFileURL(aProgramURL, aProgram)) { - // seems to be a document - aProtocol = OUString::createFromAscii( "file" ); + throw SystemShellExecuteException( + OUString(RTL_CONSTASCII_USTRINGPARAM("Cound not convert executable path")), + static_cast < XSystemShellExecute * > (this), ENOENT ); } - // if aCommand contains a url with a known protocol, - // retrieve the registered handler from configuration - if( aProtocol.getLength() ) + // The url launchers are expected to be in the same directory as the main executable, + // so prefixing the launchers with the path of the executable including the last slash + OString aTmp = OUStringToOString(aProgram, osl_getThreadTextEncoding()); + nIndex = aTmp.lastIndexOf('/'); + if (nIndex > 0) + aBuffer.append(aTmp.copy(0, nIndex+1)); + + // Respect the desktop environment - if there is an executable named + // <desktop-environement-is>-open-url, pass the url to this one instead + // of the default "open-url" script. + if ( m_aDesktopEnvironment.getLength() > 0 ) { - MutexGuard aGuard( m_aMutex ); + OString aDesktopEnvironment(m_aDesktopEnvironment.toAsciiLowerCase()); + OStringBuffer aCopy(aBuffer); - // create config manager if not already done so - if( m_xServiceManager.is() && !m_xConfigurationProvider.is() ) - { - try - { - m_xConfigurationProvider = Reference< XMultiServiceFactory > ( - m_xServiceManager->createInstance( - OUString::createFromAscii( "com.sun.star.configuration.ConfigurationProvider" ) ), - UNO_QUERY ); + aCopy.append(aDesktopEnvironment); + aCopy.append("-open-url"); - Reference< XComponent > xComponent = - Reference< XComponent >( m_xConfigurationProvider, UNO_QUERY ); - - if( xComponent.is() ) - xComponent->addEventListener( static_cast < XEventListener * > (this) ); - } - - // release service manager instance on runtime exceptions - catch ( RuntimeException e ) - { - m_xServiceManager.clear(); - OSL_TRACE( "ShellExec: can not instanciate configuration provider." ); - throw e; - } - } - - if( m_xConfigurationProvider.is() ) + if ( 0 == access( aCopy.getStr(), X_OK) ) { - try - { - Sequence< Any > aArgumentList( 1 ); - - PropertyValue aProperty; - aProperty.Name = OUString::createFromAscii( "nodepath" ); - aProperty.Value = makeAny( OUString::createFromAscii( "org.openoffice.Office.Common/ExternalApps" ) ); - - aArgumentList[0] = makeAny( aProperty ); - - // query the configured handle for this protocol - Reference< XNameAccess > xNameAccess = - Reference< XNameAccess > ( - m_xConfigurationProvider->createInstanceWithArguments( - OUString::createFromAscii( "com.sun.star.configuration.ConfigurationAccess" ), - aArgumentList ), - UNO_QUERY ); - - if( xNameAccess.is() ) - { - // save the registered handler - xNameAccess->getByName( aProtocol ) >>= aHandler; - } - } - - catch( NoSuchElementException e ) - { - OSL_TRACE( "ShellExec: unknown protocol.\n" ); - OSL_TRACE( OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); - } - - catch( WrappedTargetException e ) - { - OSL_TRACE( "ShellExec: unexspected exception.\n" ); - OSL_TRACE( OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); - } - - catch( RuntimeException e ) - { - m_xConfigurationProvider.clear(); - OSL_TRACE( "ShellExec: configuration provider." ); - OSL_TRACE( OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); - throw e; - } + aBuffer.append(aDesktopEnvironment); + aBuffer.append("-"); - catch( Exception e ) + /* CDE requires file urls to be decoded */ + if ( m_aDesktopEnvironment.equals("CDE") && 0 == aURL.compareToAscii("file://", 7) ) { - OSL_TRACE( "ShellExec: unexspected exception.\n" ); - OSL_TRACE( OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); + aURL = rtl::Uri::decode(aURL, rtl_UriDecodeWithCharset, osl_getThreadTextEncoding()); } } } - if( aHandler.getLength() ) - { - // search handler in system path if no absolute path given - FileBase::searchFileURL( aHandler, OUString(), aHandler ); - - // handler may be stored as file URL - FileBase::getSystemPathFromFileURL( aHandler, aHandler ); - - // due to a possible convertion to file url, - // rebuild command line from scratch - OUStringBuffer aBuffer( aHandler.getLength() + aURL.getLength() + 5 ); - - aBuffer.append( (sal_Unicode) '\"' ); - aBuffer.append( aHandler ); - aBuffer.append( (sal_Unicode) '\"' ); - aBuffer.append( (sal_Unicode) ' ' ); - aBuffer.append( (sal_Unicode) '\'' ); - aBuffer.append( aURL ); - aBuffer.append( (sal_Unicode) '\'' ); - - aCommandLine = OUStringToOString( aBuffer.makeStringAndClear(), osl_getThreadTextEncoding() ); - } - else - { - // no handler installed - throw SystemShellExecuteException( - OUString::createFromAscii( strerror( nerr ) ), - static_cast < XSystemShellExecute * > (this), - nerr ); - } - } - - // append parameter if any - if( aParameter.getLength() ) - { - OString aTmp = OUStringToOString( aParameter, osl_getThreadTextEncoding() ); - - OStringBuffer aBuffer( aCommandLine.getLength() + aTmp.getLength() + 1 ); - - aBuffer.append( aCommandLine ); - aBuffer.append( ' ' ); - aBuffer.append( aTmp ); - - aCommandLine = aBuffer.makeStringAndClear(); - } - - // check if the handler really exists and is executable - OString aHandler = aCommandLine.copy( 1, aCommandLine.indexOf( '\"', 1 ) - 1 ); - if( 0 != access( aHandler.getStr(), X_OK ) ) - { - int nerr = errno; + aBuffer.append("open-url"); +#endif + aBuffer.append(" "); + aBuffer.append(OUStringToOString(aURL, osl_getThreadTextEncoding())); - throw SystemShellExecuteException( - OUString::createFromAscii( strerror( nerr ) ), - static_cast < XSystemShellExecute * > (this), - nerr ); + } else { + aBuffer.append(OUStringToOString(aCommand, osl_getThreadTextEncoding())); + aBuffer.append(" "); + aBuffer.append(OUStringToOString(aParameter, osl_getThreadTextEncoding())); } - // do not wait for completion - aCommandLine += " &"; - - if( 0 != system( aCommandLine.getStr() ) ) + OString cmd = aBuffer.makeStringAndClear(); + if ( 0 != pclose(popen(cmd.getStr(), "w")) ) { int nerr = errno; - - throw SystemShellExecuteException( - OUString::createFromAscii( strerror( nerr ) ), - static_cast < XSystemShellExecute * > (this), - nerr ); + throw SystemShellExecuteException(OUString::createFromAscii( strerror( nerr ) ), + static_cast < XSystemShellExecute * > (this), nerr ); } } -//------------------------------------------------ -// XEventListener -//------------------------------------------------ - -void SAL_CALL ShellExec::disposing( const ::com::sun::star::lang::EventObject& aEvent ) - throw(::com::sun::star::uno::RuntimeException) -{ - MutexGuard aGuard( m_aMutex ); - - if( m_xServiceManager == aEvent.Source ) - { - m_xServiceManager.clear(); - } - - else if( m_xConfigurationProvider == aEvent.Source ) - { - m_xConfigurationProvider.clear(); - } -} // ------------------------------------------------- // XServiceInfo |