fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / shell / source / unix / exec / shellexec.cxx
blob0239a668f1ffcb76402fdd3048affece5b376b13
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <config_folders.h>
22 #include <osl/diagnose.h>
23 #include <osl/thread.h>
24 #include <osl/process.h>
25 #include <osl/file.hxx>
26 #include <rtl/ustrbuf.hxx>
28 #include <rtl/uri.hxx>
29 #include "shellexec.hxx"
30 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
32 #include <com/sun/star/util/theMacroExpander.hpp>
33 #include <com/sun/star/uri/XExternalUriReferenceTranslator.hpp>
34 #include <com/sun/star/uri/ExternalUriReferenceTranslator.hpp>
35 #include <com/sun/star/uri/UriReferenceFactory.hpp>
36 #include <cppuhelper/supportsservice.hxx>
38 #include "uno/current_context.hxx"
40 #include <string.h>
41 #include <errno.h>
42 #include <unistd.h>
45 // namespace directives
48 using com::sun::star::system::XSystemShellExecute;
49 using com::sun::star::system::SystemShellExecuteException;
51 using osl::FileBase;
53 using namespace ::com::sun::star::uno;
54 using namespace ::com::sun::star::lang;
55 using namespace ::com::sun::star::system::SystemShellExecuteFlags;
56 using namespace cppu;
58 namespace // private
60 Sequence< OUString > SAL_CALL ShellExec_getSupportedServiceNames()
62 Sequence< OUString > aRet(1);
63 aRet[0] = "com.sun.star.system.SystemShellExecute";
64 return aRet;
68 void escapeForShell( OStringBuffer & rBuffer, const OString & rURL)
70 sal_Int32 nmax = rURL.getLength();
71 for(sal_Int32 n=0; n < nmax; ++n)
73 // escape every non alpha numeric characters (excluding a few "known good") by prepending a '\'
74 sal_Char c = rURL[n];
75 if( ( c < 'A' || c > 'Z' ) && ( c < 'a' || c > 'z' ) && ( c < '0' || c > '9' ) && c != '/' && c != '.' )
76 rBuffer.append( '\\' );
78 rBuffer.append( c );
84 ShellExec::ShellExec( const Reference< XComponentContext >& xContext ) :
85 WeakImplHelper2< XSystemShellExecute, XServiceInfo >(),
86 m_xContext(xContext)
88 try {
89 Reference< XCurrentContext > xCurrentContext(getCurrentContext());
91 if (xCurrentContext.is())
93 Any aValue = xCurrentContext->getValueByName(
94 OUString( "system.desktop-environment" ) );
96 OUString aDesktopEnvironment;
97 if (aValue >>= aDesktopEnvironment)
99 m_aDesktopEnvironment = OUStringToOString(aDesktopEnvironment, RTL_TEXTENCODING_ASCII_US);
102 } catch (const RuntimeException &) {
108 void SAL_CALL ShellExec::execute( const OUString& aCommand, const OUString& aParameter, sal_Int32 nFlags )
109 throw (IllegalArgumentException, SystemShellExecuteException, RuntimeException, std::exception)
111 OStringBuffer aBuffer, aLaunchBuffer;
113 // DESKTOP_LAUNCH, see http://freedesktop.org/pipermail/xdg/2004-August/004489.html
114 static const char *pDesktopLaunch = getenv( "DESKTOP_LAUNCH" );
116 // Check whether aCommand contains an absolute URI reference:
117 css::uno::Reference< css::uri::XUriReference > uri(
118 css::uri::UriReferenceFactory::create(m_xContext)->parse(aCommand));
119 if (uri.is() && uri->isAbsolute())
121 // It seems to be a url ..
122 // We need to re-encode file urls because osl_getFileURLFromSystemPath converts
123 // to UTF-8 before encoding non ascii characters, which is not what other apps
124 // expect.
125 OUString aURL(
126 com::sun::star::uri::ExternalUriReferenceTranslator::create(
127 m_xContext)->translateToExternal(aCommand));
128 if ( aURL.isEmpty() && !aCommand.isEmpty() )
130 throw RuntimeException(
131 "Cannot translate URI reference to external format: "
132 + aCommand,
133 static_cast< cppu::OWeakObject * >(this));
136 #ifdef MACOSX
137 //TODO: Using open(1) with an argument that syntactically is an absolute
138 // URI reference does not necessarily give expected results:
139 // 1 If the given URI reference matches a supported scheme (e.g.,
140 // "mailto:foo"):
141 // 1.1 If it matches an existing pathname (relative to CWD): Results
142 // in "mailto:foo?\n[0]\tcancel\n[1]\tOpen the file\tmailto:foo\n[2]\t
143 // Open the URL\tmailto:foo\n\nWhich did you mean? Cancelled." on
144 // stderr and SystemShellExecuteException.
145 // 1.2 If it does not match an exitsting pathname (relative to CWD):
146 // Results in the corresponding application being opened with the given
147 // document (e.g., Mail with a New Message).
148 // 2 If the given URI reference does not match a supported scheme
149 // (e.g., "foo:bar"):
150 // 2.1 If it matches an existing pathname (relative to CWD) pointing to
151 // an executable: Results in execution of that executable.
152 // 2.2 If it matches an existing pathname (relative to CWD) pointing to
153 // a non-executable regular file: Results in opening it in TextEdit.
154 // 2.3 If it matches an existing pathname (relative to CWD) pointing to
155 // a directory: Results in opening it in Finder.
156 // 2.4 If it does not match an exitsting pathname (relative to CWD):
157 // Results in "The file /.../foo:bar does not exits." (where "/..." is
158 // the CWD) on stderr and SystemShellExecuteException.
159 aBuffer.append("open --");
160 #else
161 // The url launchers are expected to be in the $BRAND_BASE_DIR/LIBO_LIBEXEC_FOLDER
162 // directory:
163 com::sun::star::uno::Reference< com::sun::star::util::XMacroExpander >
164 exp = com::sun::star::util::theMacroExpander::get(m_xContext);
165 OUString aProgramURL;
166 try {
167 aProgramURL = exp->expandMacros(
168 OUString( "$BRAND_BASE_DIR/" LIBO_LIBEXEC_FOLDER "/"));
169 } catch (com::sun::star::lang::IllegalArgumentException &)
171 throw SystemShellExecuteException(
172 "Could not expand $BRAND_BASE_DIR path",
173 static_cast < XSystemShellExecute * > (this), ENOENT );
176 OUString aProgram;
177 if ( FileBase::E_None != FileBase::getSystemPathFromFileURL(aProgramURL, aProgram))
179 throw SystemShellExecuteException(
180 "Cound not convert executable path",
181 static_cast < XSystemShellExecute * > (this), ENOENT );
184 OString aTmp = OUStringToOString(aProgram, osl_getThreadTextEncoding());
185 escapeForShell(aBuffer, aTmp);
187 #ifdef SOLARIS
188 if ( m_aDesktopEnvironment.getLength() == 0 )
189 m_aDesktopEnvironment = OString("GNOME");
190 #endif
192 // Respect the desktop environment - if there is an executable named
193 // <desktop-environement-is>-open-url, pass the url to this one instead
194 // of the default "open-url" script.
195 if ( !m_aDesktopEnvironment.isEmpty() )
197 OString aDesktopEnvironment(m_aDesktopEnvironment.toAsciiLowerCase());
198 OStringBuffer aCopy(aTmp);
200 aCopy.append(aDesktopEnvironment + "-open-url");
202 if ( 0 == access( aCopy.getStr(), X_OK) )
204 aBuffer.append(aDesktopEnvironment + "-");
208 aBuffer.append("open-url");
209 #endif
210 aBuffer.append(" ");
211 escapeForShell(aBuffer, OUStringToOString(aURL, osl_getThreadTextEncoding()));
213 if ( pDesktopLaunch && *pDesktopLaunch )
215 aLaunchBuffer.append( OString(pDesktopLaunch) + " ");
216 escapeForShell(aLaunchBuffer, OUStringToOString(aURL, osl_getThreadTextEncoding()));
218 } else if ((nFlags & css::system::SystemShellExecuteFlags::URIS_ONLY) != 0)
220 throw css::lang::IllegalArgumentException(
221 "XSystemShellExecute.execute URIS_ONLY with non-absolute"
222 " URI reference "
223 + aCommand,
224 static_cast< cppu::OWeakObject * >(this), 0);
225 } else {
226 escapeForShell(aBuffer, OUStringToOString(aCommand, osl_getThreadTextEncoding()));
227 aBuffer.append(" ");
228 if( nFlags != 42 )
229 escapeForShell(aBuffer, OUStringToOString(aParameter, osl_getThreadTextEncoding()));
230 else
231 aBuffer.append(OUStringToOString(aParameter, osl_getThreadTextEncoding()));
234 // Prefer DESKTOP_LAUNCH when available
235 if ( !aLaunchBuffer.isEmpty() )
237 FILE *pLaunch = popen( aLaunchBuffer.makeStringAndClear().getStr(), "w" );
238 if ( pLaunch != NULL )
240 if ( 0 == pclose( pLaunch ) )
241 return;
243 // Failed, do not try DESKTOP_LAUNCH any more
244 pDesktopLaunch = NULL;
247 OString cmd =
248 #ifdef LINUX
249 // avoid blocking (call it in background)
250 "( " + aBuffer.makeStringAndClear() + " ) &";
251 #else
252 aBuffer.makeStringAndClear();
253 #endif
254 FILE *pLaunch = popen(cmd.getStr(), "w");
255 if ( pLaunch != NULL )
257 if ( 0 == pclose( pLaunch ) )
258 return;
261 int nerr = errno;
262 throw SystemShellExecuteException(OUString::createFromAscii( strerror( nerr ) ),
263 static_cast < XSystemShellExecute * > (this), nerr );
266 // XServiceInfo
267 OUString SAL_CALL ShellExec::getImplementationName( )
268 throw( RuntimeException, std::exception )
270 return OUString("com.sun.star.comp.system.SystemShellExecute");
273 // XServiceInfo
274 sal_Bool SAL_CALL ShellExec::supportsService( const OUString& ServiceName )
275 throw( RuntimeException, std::exception )
277 return cppu::supportsService(this, ServiceName);
280 // XServiceInfo
281 Sequence< OUString > SAL_CALL ShellExec::getSupportedServiceNames( )
282 throw( RuntimeException, std::exception )
284 return ShellExec_getSupportedServiceNames();
287 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */