LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/shell/source/unix/exec - shellexec.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 89 0.0 %
Date: 2013-07-09 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/theMacroExpander.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 osl::FileBase;
      49             : 
      50             : using namespace ::com::sun::star::uno;
      51             : using namespace ::com::sun::star::lang;
      52             : using namespace ::com::sun::star::system::SystemShellExecuteFlags;
      53             : using namespace cppu;
      54             : 
      55             : #define SHELLEXEC_IMPL_NAME  "com.sun.star.comp.system.SystemShellExecute2"
      56             : 
      57             : //------------------------------------------------------------------------
      58             : // helper functions
      59             : //------------------------------------------------------------------------
      60             : 
      61             : namespace // private
      62             : {
      63           0 :     Sequence< OUString > SAL_CALL ShellExec_getSupportedServiceNames()
      64             :     {
      65           0 :         Sequence< OUString > aRet(1);
      66           0 :         aRet[0] = OUString("com.sun.star.sys.shell.SystemShellExecute");
      67           0 :         return aRet;
      68             :     }
      69             : }
      70             : 
      71           0 : void escapeForShell( OStringBuffer & rBuffer, const OString & rURL)
      72             : {
      73           0 :     sal_Int32 nmax = rURL.getLength();
      74           0 :     for(sal_Int32 n=0; n < nmax; ++n)
      75             :     {
      76             :         // escape every non alpha numeric characters (excluding a few "known good") by prepending a '\'
      77           0 :         sal_Char c = rURL[n];
      78           0 :         if( ( c < 'A' || c > 'Z' ) && ( c < 'a' || c > 'z' ) && ( c < '0' || c > '9' )  && c != '/' && c != '.' )
      79           0 :             rBuffer.append( '\\' );
      80             : 
      81           0 :         rBuffer.append( c );
      82             :     }
      83           0 : }
      84             : 
      85             : //-----------------------------------------------------------------------------------------
      86             : 
      87           0 : ShellExec::ShellExec( const Reference< XComponentContext >& xContext ) :
      88             :     WeakImplHelper2< XSystemShellExecute, XServiceInfo >(),
      89           0 :     m_xContext(xContext)
      90             : {
      91             :     try {
      92           0 :         Reference< XCurrentContext > xCurrentContext(getCurrentContext());
      93             : 
      94           0 :         if (xCurrentContext.is())
      95             :         {
      96           0 :             Any aValue = xCurrentContext->getValueByName(
      97           0 :                 OUString( "system.desktop-environment"  ) );
      98             : 
      99           0 :             OUString aDesktopEnvironment;
     100           0 :             if (aValue >>= aDesktopEnvironment)
     101             :             {
     102           0 :                 m_aDesktopEnvironment = OUStringToOString(aDesktopEnvironment, RTL_TEXTENCODING_ASCII_US);
     103           0 :             }
     104           0 :         }
     105           0 :     } catch (const RuntimeException &e) {
     106             :     }
     107           0 : }
     108             : 
     109             : //-------------------------------------------------
     110             : 
     111           0 : void SAL_CALL ShellExec::execute( const OUString& aCommand, const OUString& aParameter, sal_Int32 nFlags )
     112             :     throw (IllegalArgumentException, SystemShellExecuteException, RuntimeException)
     113             : {
     114           0 :     OStringBuffer aBuffer, aLaunchBuffer;
     115             : 
     116             :     // DESKTOP_LAUNCH, see http://freedesktop.org/pipermail/xdg/2004-August/004489.html
     117           0 :     static const char *pDesktopLaunch = getenv( "DESKTOP_LAUNCH" );
     118             : 
     119             :     // Check whether aCommand contains an absolute URI reference:
     120             :     css::uno::Reference< css::uri::XUriReference > uri(
     121           0 :         css::uri::UriReferenceFactory::create(m_xContext)->parse(aCommand));
     122           0 :     if (uri.is() && uri->isAbsolute())
     123             :     {
     124             :         // It seems to be a url ..
     125             :         // We need to re-encode file urls because osl_getFileURLFromSystemPath converts
     126             :         // to UTF-8 before encoding non ascii characters, which is not what other apps
     127             :         // expect.
     128             :         OUString aURL(
     129             :             com::sun::star::uri::ExternalUriReferenceTranslator::create(
     130           0 :                 m_xContext)->translateToExternal(aCommand));
     131           0 :         if ( aURL.isEmpty() && !aCommand.isEmpty() )
     132             :         {
     133             :             throw RuntimeException(
     134             :                 (OUString( "Cannot translate URI reference to external format: ")
     135           0 :                  + aCommand),
     136           0 :                 static_cast< cppu::OWeakObject * >(this));
     137             :         }
     138             : 
     139             : #ifdef MACOSX
     140             :         //TODO: Using open(1) with an argument that syntactically is an absolute
     141             :         // URI reference does not necessarily give expected results:
     142             :         // 1  If the given URI reference matches a supported scheme (e.g.,
     143             :         //  "mailto:foo"):
     144             :         // 1.1  If it matches an existing pathname (relative to CWD):  Results
     145             :         //  in "mailto:foo?\n[0]\tcancel\n[1]\tOpen the file\tmailto:foo\n[2]\t
     146             :         //  Open the URL\tmailto:foo\n\nWhich did you mean? Cancelled." on
     147             :         //  stderr and SystemShellExecuteException.
     148             :         // 1.2  If it does not match an exitsting pathname (relative to CWD):
     149             :         //  Results in the corresponding application being opened with the given
     150             :         //  document (e.g., Mail with a New Message).
     151             :         // 2  If the given URI reference does not match a supported scheme
     152             :         //  (e.g., "foo:bar"):
     153             :         // 2.1  If it matches an existing pathname (relative to CWD) pointing to
     154             :         //  an executable:  Results in execution of that executable.
     155             :         // 2.2  If it matches an existing pathname (relative to CWD) pointing to
     156             :         //  a non-executable regular file:  Results in opening it in TextEdit.
     157             :         // 2.3  If it matches an existing pathname (relative to CWD) pointing to
     158             :         //  a directory:  Results in opening it in Finder.
     159             :         // 2.4  If it does not match an exitsting pathname (relative to CWD):
     160             :         //  Results in "The file /.../foo:bar does not exits." (where "/..." is
     161             :         //  the CWD) on stderr and SystemShellExecuteException.
     162             :         aBuffer.append("open --");
     163             : #else
     164             :         // The url launchers are expected to be in the $BRAND_BASE_DIR/program
     165             :         // directory:
     166             :         com::sun::star::uno::Reference< com::sun::star::util::XMacroExpander >
     167           0 :             exp = com::sun::star::util::theMacroExpander::get(m_xContext);
     168           0 :         OUString aProgramURL;
     169             :         try {
     170           0 :             aProgramURL = exp->expandMacros(
     171           0 :                 OUString( "$BRAND_BASE_DIR/program/"));
     172           0 :         } catch (com::sun::star::lang::IllegalArgumentException &)
     173             :         {
     174             :             throw SystemShellExecuteException(
     175             :                 OUString("Could not expand $BRAND_BASE_DIR path"),
     176           0 :                 static_cast < XSystemShellExecute * > (this), ENOENT );
     177             :         }
     178             : 
     179           0 :         OUString aProgram;
     180           0 :         if ( FileBase::E_None != FileBase::getSystemPathFromFileURL(aProgramURL, aProgram))
     181             :         {
     182             :             throw SystemShellExecuteException(
     183             :                 OUString("Cound not convert executable path"),
     184           0 :                 static_cast < XSystemShellExecute * > (this), ENOENT );
     185             :         }
     186             : 
     187           0 :         OString aTmp = OUStringToOString(aProgram, osl_getThreadTextEncoding());
     188           0 :         escapeForShell(aBuffer, aTmp);
     189             : 
     190             : #ifdef SOLARIS
     191             :         if ( m_aDesktopEnvironment.getLength() == 0 )
     192             :              m_aDesktopEnvironment = OString("GNOME");
     193             : #endif
     194             : 
     195             :         // Respect the desktop environment - if there is an executable named
     196             :         // <desktop-environement-is>-open-url, pass the url to this one instead
     197             :         // of the default "open-url" script.
     198           0 :         if ( !m_aDesktopEnvironment.isEmpty() )
     199             :         {
     200           0 :             OString aDesktopEnvironment(m_aDesktopEnvironment.toAsciiLowerCase());
     201           0 :             OStringBuffer aCopy(aTmp);
     202             : 
     203           0 :             aCopy.append(aDesktopEnvironment + "-open-url");
     204             : 
     205           0 :             if ( 0 == access( aCopy.getStr(), X_OK) )
     206             :             {
     207           0 :                 aBuffer.append(aDesktopEnvironment + "-");
     208           0 :             }
     209             :         }
     210             : 
     211           0 :         aBuffer.append("open-url");
     212             : #endif
     213           0 :         aBuffer.append(" ");
     214           0 :         escapeForShell(aBuffer, OUStringToOString(aURL, osl_getThreadTextEncoding()));
     215             : 
     216           0 :         if ( pDesktopLaunch && *pDesktopLaunch )
     217             :         {
     218           0 :             aLaunchBuffer.append( OString(pDesktopLaunch) + " ");
     219           0 :             escapeForShell(aLaunchBuffer, OUStringToOString(aURL, osl_getThreadTextEncoding()));
     220           0 :         }
     221           0 :     } else if ((nFlags & css::system::SystemShellExecuteFlags::URIS_ONLY) != 0)
     222             :     {
     223             :         throw css::lang::IllegalArgumentException(
     224             :             (OUString(
     225             :                     "XSystemShellExecute.execute URIS_ONLY with non-absolute"
     226             :                     " URI reference ")
     227           0 :              + aCommand),
     228           0 :             static_cast< cppu::OWeakObject * >(this), 0);
     229             :     } else {
     230           0 :         escapeForShell(aBuffer, OUStringToOString(aCommand, osl_getThreadTextEncoding()));
     231           0 :         aBuffer.append(" ");
     232           0 :         if( nFlags != 42 )
     233           0 :             escapeForShell(aBuffer, OUStringToOString(aParameter, osl_getThreadTextEncoding()));
     234             :         else
     235           0 :             aBuffer.append(OUStringToOString(aParameter, osl_getThreadTextEncoding()));
     236             :     }
     237             : 
     238             :     // Prefer DESKTOP_LAUNCH when available
     239           0 :     if ( !aLaunchBuffer.isEmpty() )
     240             :     {
     241           0 :         FILE *pLaunch = popen( aLaunchBuffer.makeStringAndClear().getStr(), "w" );
     242           0 :         if ( pLaunch != NULL )
     243             :         {
     244           0 :             if ( 0 == pclose( pLaunch ) )
     245           0 :                 return;
     246             :         }
     247             :         // Failed, do not try DESKTOP_LAUNCH any more
     248           0 :         pDesktopLaunch = NULL;
     249             :     }
     250             : 
     251             :     OString cmd =
     252             : #ifdef LINUX
     253             :         // avoid blocking (call it in background)
     254           0 :         "( " + aBuffer.makeStringAndClear() +  " ) &";
     255             : #else
     256             :         aBuffer.makeStringAndClear();
     257             : #endif
     258           0 :     if ( 0 != pclose(popen(cmd.getStr(), "w")) )
     259             :     {
     260           0 :         int nerr = errno;
     261           0 :         throw SystemShellExecuteException(OUString::createFromAscii( strerror( nerr ) ),
     262           0 :             static_cast < XSystemShellExecute * > (this), nerr );
     263           0 :     }
     264             : }
     265             : 
     266             : 
     267             : // -------------------------------------------------
     268             : // XServiceInfo
     269             : // -------------------------------------------------
     270             : 
     271           0 : OUString SAL_CALL ShellExec::getImplementationName(  )
     272             :     throw( RuntimeException )
     273             : {
     274           0 :     return OUString(SHELLEXEC_IMPL_NAME );
     275             : }
     276             : 
     277             : // -------------------------------------------------
     278             : //  XServiceInfo
     279             : // -------------------------------------------------
     280             : 
     281           0 : sal_Bool SAL_CALL ShellExec::supportsService( const OUString& ServiceName )
     282             :     throw( RuntimeException )
     283             : {
     284           0 :     Sequence < OUString > SupportedServicesNames = ShellExec_getSupportedServiceNames();
     285             : 
     286           0 :     for ( sal_Int32 n = SupportedServicesNames.getLength(); n--; )
     287           0 :         if ( SupportedServicesNames[n] == ServiceName )
     288           0 :             return sal_True;
     289             : 
     290           0 :     return sal_False;
     291             : }
     292             : 
     293             : // -------------------------------------------------
     294             : //  XServiceInfo
     295             : // -------------------------------------------------
     296             : 
     297           0 : Sequence< OUString > SAL_CALL ShellExec::getSupportedServiceNames(   )
     298             :     throw( RuntimeException )
     299             : {
     300           0 :     return ShellExec_getSupportedServiceNames();
     301             : }
     302             : 
     303             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10