LCOV - code coverage report
Current view: top level - libreoffice/shell/source/unix/exec - shellexec.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 97 0.0 %
Date: 2012-12-27 Functions: 0 7 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <osl/diagnose.h>
      21             : #include <osl/thread.h>
      22             : #include <osl/process.h>
      23             : #include <osl/file.hxx>
      24             : #include <rtl/ustrbuf.hxx>
      25             : 
      26             : #include <rtl/uri.hxx>
      27             : #include "shellexec.hxx"
      28             : #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
      29             : 
      30             : #include <com/sun/star/util/XMacroExpander.hpp>
      31             : #include <com/sun/star/uri/XExternalUriReferenceTranslator.hpp>
      32             : #include <com/sun/star/uri/ExternalUriReferenceTranslator.hpp>
      33             : #include <com/sun/star/uri/UriReferenceFactory.hpp>
      34             : 
      35             : #include "uno/current_context.hxx"
      36             : 
      37             : #include <string.h>
      38             : #include <errno.h>
      39             : #include <unistd.h>
      40             : 
      41             : //------------------------------------------------------------------------
      42             : // namespace directives
      43             : //------------------------------------------------------------------------
      44             : 
      45             : using com::sun::star::system::XSystemShellExecute;
      46             : using com::sun::star::system::SystemShellExecuteException;
      47             : 
      48             : using rtl::OString;
      49             : using rtl::OUString;
      50             : using rtl::OStringBuffer;
      51             : using rtl::OUStringBuffer;
      52             : using osl::FileBase;
      53             : 
      54             : using namespace ::com::sun::star::uno;
      55             : using namespace ::com::sun::star::lang;
      56             : using namespace ::com::sun::star::system::SystemShellExecuteFlags;
      57             : using namespace cppu;
      58             : 
      59             : #define SHELLEXEC_IMPL_NAME  "com.sun.star.comp.system.SystemShellExecute2"
      60             : 
      61             : //------------------------------------------------------------------------
      62             : // helper functions
      63             : //------------------------------------------------------------------------
      64             : 
      65             : namespace // private
      66             : {
      67           0 :     Sequence< OUString > SAL_CALL ShellExec_getSupportedServiceNames()
      68             :     {
      69           0 :         Sequence< OUString > aRet(1);
      70           0 :         aRet[0] = OUString("com.sun.star.sys.shell.SystemShellExecute");
      71           0 :         return aRet;
      72             :     }
      73             : }
      74             : 
      75           0 : void escapeForShell( rtl::OStringBuffer & rBuffer, const rtl::OString & rURL)
      76             : {
      77           0 :     sal_Int32 nmax = rURL.getLength();
      78           0 :     for(sal_Int32 n=0; n < nmax; ++n)
      79             :     {
      80             :         // escape every non alpha numeric characters (excluding a few "known good") by prepending a '\'
      81           0 :         sal_Char c = rURL[n];
      82           0 :         if( ( c < 'A' || c > 'Z' ) && ( c < 'a' || c > 'z' ) && ( c < '0' || c > '9' )  && c != '/' && c != '.' )
      83           0 :             rBuffer.append( '\\' );
      84             : 
      85           0 :         rBuffer.append( c );
      86             :     }
      87           0 : }
      88             : 
      89             : //-----------------------------------------------------------------------------------------
      90             : 
      91           0 : ShellExec::ShellExec( const Reference< XComponentContext >& xContext ) :
      92             :     WeakImplHelper2< XSystemShellExecute, XServiceInfo >(),
      93           0 :     m_xContext(xContext)
      94             : {
      95             :     try {
      96           0 :         Reference< XCurrentContext > xCurrentContext(getCurrentContext());
      97             : 
      98           0 :         if (xCurrentContext.is())
      99             :         {
     100           0 :             Any aValue = xCurrentContext->getValueByName(
     101           0 :                 OUString( "system.desktop-environment"  ) );
     102             : 
     103           0 :             OUString aDesktopEnvironment;
     104           0 :             if (aValue >>= aDesktopEnvironment)
     105             :             {
     106           0 :                 m_aDesktopEnvironment = OUStringToOString(aDesktopEnvironment, RTL_TEXTENCODING_ASCII_US);
     107           0 :             }
     108           0 :         }
     109           0 :     } catch (const RuntimeException &e) {
     110             :     }
     111           0 : }
     112             : 
     113             : //-------------------------------------------------
     114             : 
     115           0 : void SAL_CALL ShellExec::execute( const OUString& aCommand, const OUString& aParameter, sal_Int32 nFlags )
     116             :     throw (IllegalArgumentException, SystemShellExecuteException, RuntimeException)
     117             : {
     118           0 :     OStringBuffer aBuffer, aLaunchBuffer;
     119             : 
     120             :     // DESKTOP_LAUNCH, see http://freedesktop.org/pipermail/xdg/2004-August/004489.html
     121           0 :     static const char *pDesktopLaunch = getenv( "DESKTOP_LAUNCH" );
     122             : 
     123             :     // Check whether aCommand contains an absolute URI reference:
     124             :     css::uno::Reference< css::uri::XUriReference > uri(
     125           0 :         css::uri::UriReferenceFactory::create(m_xContext)->parse(aCommand));
     126           0 :     if (uri.is() && uri->isAbsolute())
     127             :     {
     128             :         // It seems to be a url ..
     129             :         // We need to re-encode file urls because osl_getFileURLFromSystemPath converts
     130             :         // to UTF-8 before encoding non ascii characters, which is not what other apps
     131             :         // expect.
     132             :         OUString aURL(
     133             :             com::sun::star::uri::ExternalUriReferenceTranslator::create(
     134           0 :                 m_xContext)->translateToExternal(aCommand));
     135           0 :         if ( aURL.isEmpty() && !aCommand.isEmpty() )
     136             :         {
     137             :             throw RuntimeException(
     138             :                 (OUString( "Cannot translate URI reference to external format: ")
     139           0 :                  + aCommand),
     140           0 :                 static_cast< cppu::OWeakObject * >(this));
     141             :         }
     142             : 
     143             : #ifdef MACOSX
     144             :         //TODO: Using open(1) with an argument that syntactically is an absolute
     145             :         // URI reference does not necessarily give expected results:
     146             :         // 1  If the given URI reference matches a supported scheme (e.g.,
     147             :         //  "mailto:foo"):
     148             :         // 1.1  If it matches an existing pathname (relative to CWD):  Results
     149             :         //  in "mailto:foo?\n[0]\tcancel\n[1]\tOpen the file\tmailto:foo\n[2]\t
     150             :         //  Open the URL\tmailto:foo\n\nWhich did you mean? Cancelled." on
     151             :         //  stderr and SystemShellExecuteException.
     152             :         // 1.2  If it does not match an exitsting pathname (relative to CWD):
     153             :         //  Results in the corresponding application being opened with the given
     154             :         //  document (e.g., Mail with a New Message).
     155             :         // 2  If the given URI reference does not match a supported scheme
     156             :         //  (e.g., "foo:bar"):
     157             :         // 2.1  If it matches an existing pathname (relative to CWD) pointing to
     158             :         //  an executable:  Results in execution of that executable.
     159             :         // 2.2  If it matches an existing pathname (relative to CWD) pointing to
     160             :         //  a non-executable regular file:  Results in opening it in TextEdit.
     161             :         // 2.3  If it matches an existing pathname (relative to CWD) pointing to
     162             :         //  a directory:  Results in opening it in Finder.
     163             :         // 2.4  If it does not match an exitsting pathname (relative to CWD):
     164             :         //  Results in "The file /.../foo:bar does not exits." (where "/..." is
     165             :         //  the CWD) on stderr and SystemShellExecuteException.
     166             :         aBuffer.append("open --");
     167             : #else
     168             :         // The url launchers are expected to be in the $BRAND_BASE_DIR/program
     169             :         // directory:
     170             :         com::sun::star::uno::Reference< com::sun::star::util::XMacroExpander >
     171           0 :             exp;
     172           0 :         if (!(m_xContext->getValueByName(
     173           0 :                   rtl::OUString( "/singletons/com.sun.star.util.theMacroExpander"))
     174           0 :               >>= exp)
     175           0 :             || !exp.is())
     176             :         {
     177             :             throw SystemShellExecuteException(
     178             :                 rtl::OUString(
     179             :                         "component context fails to supply singleton"
     180             :                         " com.sun.star.util.theMacroExpander of type"
     181             :                         " com.sun.star.util.XMacroExpander"),
     182           0 :                 static_cast< XSystemShellExecute * >(this), ENOENT);
     183             :         }
     184           0 :         OUString aProgramURL;
     185             :         try {
     186           0 :             aProgramURL = exp->expandMacros(
     187           0 :                 rtl::OUString( "$BRAND_BASE_DIR/program/"));
     188           0 :         } catch (com::sun::star::lang::IllegalArgumentException &)
     189             :         {
     190             :             throw SystemShellExecuteException(
     191             :                 OUString("Could not expand $BRAND_BASE_DIR path"),
     192           0 :                 static_cast < XSystemShellExecute * > (this), ENOENT );
     193             :         }
     194             : 
     195           0 :         OUString aProgram;
     196           0 :         if ( FileBase::E_None != FileBase::getSystemPathFromFileURL(aProgramURL, aProgram))
     197             :         {
     198             :             throw SystemShellExecuteException(
     199             :                 OUString("Cound not convert executable path"),
     200           0 :                 static_cast < XSystemShellExecute * > (this), ENOENT );
     201             :         }
     202             : 
     203           0 :         OString aTmp = OUStringToOString(aProgram, osl_getThreadTextEncoding());
     204           0 :         escapeForShell(aBuffer, aTmp);
     205             : 
     206             : #ifdef SOLARIS
     207             :         if ( m_aDesktopEnvironment.getLength() == 0 )
     208             :              m_aDesktopEnvironment = OString("GNOME");
     209             : #endif
     210             : 
     211             :         // Respect the desktop environment - if there is an executable named
     212             :         // <desktop-environement-is>-open-url, pass the url to this one instead
     213             :         // of the default "open-url" script.
     214           0 :         if ( !m_aDesktopEnvironment.isEmpty() )
     215             :         {
     216           0 :             OString aDesktopEnvironment(m_aDesktopEnvironment.toAsciiLowerCase());
     217           0 :             OStringBuffer aCopy(aTmp);
     218             : 
     219           0 :             aCopy.append(aDesktopEnvironment);
     220           0 :             aCopy.append("-open-url");
     221             : 
     222           0 :             if ( 0 == access( aCopy.getStr(), X_OK) )
     223             :             {
     224           0 :                 aBuffer.append(aDesktopEnvironment);
     225           0 :                 aBuffer.append("-");
     226           0 :             }
     227             :         }
     228             : 
     229           0 :         aBuffer.append("open-url");
     230             : #endif
     231           0 :         aBuffer.append(" ");
     232           0 :         escapeForShell(aBuffer, OUStringToOString(aURL, osl_getThreadTextEncoding()));
     233             : 
     234           0 :         if ( pDesktopLaunch && *pDesktopLaunch )
     235             :         {
     236           0 :             aLaunchBuffer.append( pDesktopLaunch );
     237           0 :             aLaunchBuffer.append(" ");
     238           0 :             escapeForShell(aLaunchBuffer, OUStringToOString(aURL, osl_getThreadTextEncoding()));
     239           0 :         }
     240           0 :     } else if ((nFlags & css::system::SystemShellExecuteFlags::URIS_ONLY) != 0)
     241             :     {
     242             :         throw css::lang::IllegalArgumentException(
     243             :             (rtl::OUString(
     244             :                     "XSystemShellExecute.execute URIS_ONLY with non-absolute"
     245             :                     " URI reference ")
     246           0 :              + aCommand),
     247           0 :             static_cast< cppu::OWeakObject * >(this), 0);
     248             :     } else {
     249           0 :         escapeForShell(aBuffer, OUStringToOString(aCommand, osl_getThreadTextEncoding()));
     250           0 :         aBuffer.append(" ");
     251           0 :         if( nFlags != 42 )
     252           0 :             escapeForShell(aBuffer, OUStringToOString(aParameter, osl_getThreadTextEncoding()));
     253             :         else
     254           0 :             aBuffer.append(OUStringToOString(aParameter, osl_getThreadTextEncoding()));
     255             :     }
     256             : 
     257             :     // Prefer DESKTOP_LAUNCH when available
     258           0 :     if ( aLaunchBuffer.getLength() > 0 )
     259             :     {
     260           0 :         FILE *pLaunch = popen( aLaunchBuffer.makeStringAndClear().getStr(), "w" );
     261           0 :         if ( pLaunch != NULL )
     262             :         {
     263           0 :             if ( 0 == pclose( pLaunch ) )
     264           0 :                 return;
     265             :         }
     266             :         // Failed, do not try DESKTOP_LAUNCH any more
     267           0 :         pDesktopLaunch = NULL;
     268             :     }
     269             : 
     270             :     OString cmd =
     271             : #ifdef LINUX
     272             :         // avoid blocking (call it in background)
     273           0 :         OStringBuffer().append( "( " ).append( aBuffer.makeStringAndClear() ).append( " ) &" ).makeStringAndClear();
     274             : #else
     275             :         aBuffer.makeStringAndClear();
     276             : #endif
     277           0 :     if ( 0 != pclose(popen(cmd.getStr(), "w")) )
     278             :     {
     279           0 :         int nerr = errno;
     280           0 :         throw SystemShellExecuteException(OUString::createFromAscii( strerror( nerr ) ),
     281           0 :             static_cast < XSystemShellExecute * > (this), nerr );
     282           0 :     }
     283             : }
     284             : 
     285             : 
     286             : // -------------------------------------------------
     287             : // XServiceInfo
     288             : // -------------------------------------------------
     289             : 
     290           0 : OUString SAL_CALL ShellExec::getImplementationName(  )
     291             :     throw( RuntimeException )
     292             : {
     293           0 :     return OUString(SHELLEXEC_IMPL_NAME );
     294             : }
     295             : 
     296             : // -------------------------------------------------
     297             : //  XServiceInfo
     298             : // -------------------------------------------------
     299             : 
     300           0 : sal_Bool SAL_CALL ShellExec::supportsService( const OUString& ServiceName )
     301             :     throw( RuntimeException )
     302             : {
     303           0 :     Sequence < OUString > SupportedServicesNames = ShellExec_getSupportedServiceNames();
     304             : 
     305           0 :     for ( sal_Int32 n = SupportedServicesNames.getLength(); n--; )
     306           0 :         if (SupportedServicesNames[n].compareTo(ServiceName) == 0)
     307           0 :             return sal_True;
     308             : 
     309           0 :     return sal_False;
     310             : }
     311             : 
     312             : // -------------------------------------------------
     313             : //  XServiceInfo
     314             : // -------------------------------------------------
     315             : 
     316           0 : Sequence< OUString > SAL_CALL ShellExec::getSupportedServiceNames(   )
     317             :     throw( RuntimeException )
     318             : {
     319           0 :     return ShellExec_getSupportedServiceNames();
     320             : }
     321             : 
     322             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10