1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
30 
31 //_________________________________________________________________________________________________________________
32 //	my own includes
33 //_________________________________________________________________________________________________________________
34 #include <dispatch/systemexec.hxx>
35 #include <threadhelp/readguard.hxx>
36 #include <general.h>
37 #include <services.h>
38 
39 //_________________________________________________________________________________________________________________
40 //	interface includes
41 //_________________________________________________________________________________________________________________
42 #include <com/sun/star/system/XSystemShellExecute.hpp>
43 #include <com/sun/star/util/XStringSubstitution.hpp>
44 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
45 #include <com/sun/star/frame/DispatchResultState.hpp>
46 
47 //_________________________________________________________________________________________________________________
48 //	includes of other projects
49 //_________________________________________________________________________________________________________________
50 
51 #include <vcl/svapp.hxx>
52 
53 //_________________________________________________________________________________________________________________
54 //	namespace
55 //_________________________________________________________________________________________________________________
56 
57 namespace framework{
58 
59 //_________________________________________________________________________________________________________________
60 //	non exported const
61 //_________________________________________________________________________________________________________________
62 
63 #define PROTOCOL_VALUE      "systemexecute:"
64 #define PROTOCOL_LENGTH     14
65 
66 //_________________________________________________________________________________________________________________
67 //	non exported definitions
68 //_________________________________________________________________________________________________________________
69 
70 //_________________________________________________________________________________________________________________
71 //	declarations
72 //_________________________________________________________________________________________________________________
73 
74 //_________________________________________________________________________________________________________________
75 // XInterface, XTypeProvider, XServiceInfo
76 
77 DEFINE_XINTERFACE_5(SystemExec                                      ,
78                     OWeakObject                                     ,
79                     DIRECT_INTERFACE(css::lang::XTypeProvider      ),
80                     DIRECT_INTERFACE(css::lang::XServiceInfo       ),
81                     DIRECT_INTERFACE(css::frame::XDispatchProvider ),
82                     DIRECT_INTERFACE(css::frame::XNotifyingDispatch),
83                     DIRECT_INTERFACE(css::frame::XDispatch         ))
84 
85 DEFINE_XTYPEPROVIDER_5(SystemExec                    ,
86                        css::lang::XTypeProvider      ,
87                        css::lang::XServiceInfo       ,
88                        css::frame::XDispatchProvider ,
89                        css::frame::XNotifyingDispatch,
90                        css::frame::XDispatch         )
91 
92 DEFINE_XSERVICEINFO_MULTISERVICE(SystemExec                   ,
93                                  ::cppu::OWeakObject          ,
94                                  SERVICENAME_PROTOCOLHANDLER  ,
95                                  IMPLEMENTATIONNAME_SYSTEMEXEC)
96 
97 DEFINE_INIT_SERVICE(SystemExec,
98                     {
99                         /*Attention
100                             I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
101                             to create a new instance of this class by our own supported service factory.
102                             see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
103                         */
104                     }
105                    )
106 
107 //_________________________________________________________________________________________________________________
108 
109 SystemExec::SystemExec( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
110 		//	Init baseclasses first
111         : ThreadHelpBase( &Application::GetSolarMutex() )
112         , OWeakObject   (                               )
113         // Init member
114         , m_xFactory    ( xFactory                      )
115 {
116 }
117 
118 //_________________________________________________________________________________________________________________
119 
120 SystemExec::~SystemExec()
121 {
122     m_xFactory = NULL;
123 }
124 
125 //_________________________________________________________________________________________________________________
126 
127 css::uno::Reference< css::frame::XDispatch > SAL_CALL SystemExec::queryDispatch( const css::util::URL&  aURL    ,
128                                                                                  const ::rtl::OUString&,
129                                                                                        sal_Int32 ) throw( css::uno::RuntimeException )
130 {
131     css::uno::Reference< css::frame::XDispatch > xDispatcher;
132     if (aURL.Complete.compareToAscii(PROTOCOL_VALUE,PROTOCOL_LENGTH)==0)
133         xDispatcher = this;
134     return xDispatcher;
135 }
136 
137 //_________________________________________________________________________________________________________________
138 
139 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL SystemExec::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor ) throw( css::uno::RuntimeException )
140 {
141     sal_Int32 nCount = lDescriptor.getLength();
142     css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount );
143     for( sal_Int32 i=0; i<nCount; ++i )
144     {
145         lDispatcher[i] = this->queryDispatch(
146                             lDescriptor[i].FeatureURL,
147                             lDescriptor[i].FrameName,
148                             lDescriptor[i].SearchFlags);
149     }
150     return lDispatcher;
151 }
152 
153 //_________________________________________________________________________________________________________________
154 
155 void SAL_CALL SystemExec::dispatch( const css::util::URL&                                  aURL       ,
156                                     const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) throw( css::uno::RuntimeException )
157 {
158     dispatchWithNotification(aURL, lArguments, css::uno::Reference< css::frame::XDispatchResultListener >());
159 }
160 
161 //_________________________________________________________________________________________________________________
162 
163 void SAL_CALL SystemExec::dispatchWithNotification( const css::util::URL&                                             aURL      ,
164                                                     const css::uno::Sequence< css::beans::PropertyValue >&,
165                                                     const css::uno::Reference< css::frame::XDispatchResultListener >& xListener ) throw( css::uno::RuntimeException )
166 {
167     // convert "systemexec:file:///c:/temp/test.html" => "file:///c:/temp/test.html"
168     sal_Int32 c = aURL.Complete.getLength()-PROTOCOL_LENGTH;
169     if (c<1) // we dont check for valid URLs here! The system will show an error message ...
170     {
171         impl_notifyResultListener(xListener, css::frame::DispatchResultState::FAILURE);
172         return;
173     }
174     ::rtl::OUString sSystemURLWithVariables = aURL.Complete.copy(PROTOCOL_LENGTH, c);
175 
176     // SAFE ->
177     ReadGuard aReadLock(m_aLock);
178     css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory;
179     aReadLock.unlock();
180     // <- SAFE
181 
182     // TODO check security settings ...
183 
184     try
185     {
186         css::uno::Reference< css::util::XStringSubstitution > xPathSubst(
187             xFactory->createInstance(SERVICENAME_SUBSTITUTEPATHVARIABLES),
188             css::uno::UNO_QUERY_THROW);
189 
190         ::rtl::OUString sSystemURL = xPathSubst->substituteVariables(sSystemURLWithVariables, sal_True); // sal_True force an exception if unknown variables exists !
191 
192         css::uno::Reference< css::system::XSystemShellExecute > xShell(
193             xFactory->createInstance(SERVICENAME_SYSTEMSHELLEXECUTE),
194             css::uno::UNO_QUERY_THROW);
195 
196         xShell->execute(sSystemURL, ::rtl::OUString(), css::system::SystemShellExecuteFlags::DEFAULTS);
197         impl_notifyResultListener(xListener, css::frame::DispatchResultState::SUCCESS);
198     }
199     catch(const css::uno::Exception&)
200         {
201             impl_notifyResultListener(xListener, css::frame::DispatchResultState::FAILURE);
202         }
203 }
204 
205 //_________________________________________________________________________________________________________________
206 
207 void SAL_CALL SystemExec::addStatusListener( const css::uno::Reference< css::frame::XStatusListener >&,
208                                              const css::util::URL& ) throw( css::uno::RuntimeException )
209 {
210     // not suported yet
211 }
212 
213 //_________________________________________________________________________________________________________________
214 
215 void SAL_CALL SystemExec::removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >&,
216                                                 const css::util::URL& ) throw( css::uno::RuntimeException )
217 {
218     // not suported yet
219 }
220 
221 //_________________________________________________________________________________________________________________
222 
223 void SystemExec::impl_notifyResultListener(const css::uno::Reference< css::frame::XDispatchResultListener >& xListener,
224                                            const sal_Int16                                                   nState   )
225 {
226     if (xListener.is())
227     {
228         css::frame::DispatchResultEvent aEvent;
229         aEvent.State = nState;
230         xListener->dispatchFinished(aEvent);
231     }
232 }
233 
234 }       //  namespace framework
235