1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_shell.hxx"
24 
25 #include "syscmdmail.hxx"
26 #include "cmdmailmsg.hxx"
27 
28 #include <com/sun/star/system/MailClientFlags.hpp>
29 #include <com/sun/star/container/XNameAccess.hpp>
30 #include <com/sun/star/beans/PropertyValue.hpp>
31 #include <com/sun/star/beans/XPropertySet.hpp>
32 
33 #include <osl/file.hxx>
34 #include <osl/thread.hxx>
35 #include <rtl/bootstrap.hxx>
36 #include <rtl/strbuf.hxx>
37 
38 #include <unistd.h>
39 
40 using com::sun::star::beans::PropertyValue;
41 using com::sun::star::container::XNameAccess;
42 using com::sun::star::system::XMailClient;
43 using com::sun::star::system::XMailMessage;
44 using rtl::OString;
45 using rtl::OStringBuffer;
46 using rtl::OUString;
47 using rtl::OUStringToOString;
48 
49 using namespace com::sun::star::lang;
50 using namespace com::sun::star::system::MailClientFlags;
51 using namespace com::sun::star::uno;
52 
53 #define COMP_SERVICE_NAME  "com.sun.star.system.SystemMailProvider"
54 #define COMP_IMPL_NAME     "com.sun.star.comp.system.unx.SystemMailProvider"
55 
56 namespace shell
57 {
58 
59 namespace
60 {
escapeDoubleQuotes(OStringBuffer & rBuffer,const OUString & ustr,rtl_TextEncoding iEncoding)61     static void escapeDoubleQuotes( OStringBuffer &rBuffer,
62                                     const OUString &ustr,
63                                     rtl_TextEncoding iEncoding )
64     {
65         const OString rStr( OUStringToOString( ustr, iEncoding ) );
66         sal_Int32 nIndex = rStr.indexOf('"');
67         if ( nIndex == -1 )
68             rBuffer.append( rStr );
69         else
70         {
71             const sal_Char *pStart = rStr.getStr();
72             const sal_Char *pFrom = pStart;
73             const sal_Int32 nLen = rStr.getLength();
74             sal_Int32 nPrev = 0;;
75             do
76             {
77                 rBuffer.append( pFrom, nIndex - nPrev );
78                 rBuffer.append( RTL_CONSTASCII_STRINGPARAM( "\\\"" ) );
79                 nIndex++;
80                 pFrom = pStart + nIndex;
81                 nPrev = nIndex;
82             }
83             while ( ( nIndex = rStr.indexOf( '"' , nIndex ) ) != -1  );
84 
85             rBuffer.append( pFrom, nLen - nPrev );
86         }
87     }
88 }
89 
SystemCommandMail(const Reference<XComponentContext> & xContext)90 SystemCommandMail::SystemCommandMail(
91     const Reference< XComponentContext >& xContext )
92     : SystemCommandMail_Base( m_aMutex )
93     , m_xContext( xContext )
94 {
95     try
96     {
97         m_xConfigurationProvider.set(
98             m_xContext->getServiceManager()->createInstanceWithContext(
99                 OUString( RTL_CONSTASCII_USTRINGPARAM(
100                     "com.sun.star.configuration.ConfigurationProvider") ),
101                 m_xContext ),
102             UNO_QUERY );
103     }
104     catch(...){}
105 }
106 
~SystemCommandMail()107 SystemCommandMail::~SystemCommandMail()
108 {
109     m_xConfigurationProvider.clear();
110     m_xContext.clear();
111 }
112 
113 Reference< XMailClient > SAL_CALL
queryMailClient()114 SystemCommandMail::queryMailClient()
115 throw ( RuntimeException )
116 {
117     return Reference< XMailClient >(
118         static_cast < cppu::OWeakObject * >( this ), UNO_QUERY );
119 }
120 
121 
122 Reference< XMailMessage > SAL_CALL
createMailMessage()123 SystemCommandMail::createMailMessage()
124 throw ( RuntimeException )
125 {
126     return Reference< XMailMessage >(
127         static_cast< cppu::OWeakObject *>(
128             new CmdMailMsg() ),
129         UNO_QUERY );
130 }
131 
132 
133 void SAL_CALL
sendMailMessage(const Reference<XMailMessage> & xMailMessage,sal_Int32)134 SystemCommandMail::sendMailMessage(
135     const Reference< XMailMessage >& xMailMessage,
136     sal_Int32 /*aFlag*/ )
137 throw (IllegalArgumentException, Exception, RuntimeException)
138 {
139     osl::ClearableMutexGuard aGuard( m_aMutex );
140     Reference< XMultiServiceFactory > xConfigurationProvider = m_xConfigurationProvider;
141     aGuard.clear();
142 
143     if ( ! xMailMessage.is() )
144     {
145         throw IllegalArgumentException(
146             OUString(RTL_CONSTASCII_USTRINGPARAM( "No message specified" )),
147             static_cast < XMailClient * > (this), 1 );
148     }
149 
150     if( ! xConfigurationProvider.is() )
151     {
152         throw Exception(
153             OUString(RTL_CONSTASCII_USTRINGPARAM( "Can not access configuration" )),
154             static_cast < XMailClient * > (this) );
155     }
156 
157     OStringBuffer aBuffer;
158     aBuffer.append("\"");
159 
160     OUString aProgramURL(RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/program/senddoc"));
161     rtl::Bootstrap::expandMacros(aProgramURL);
162     OUString aProgram;
163     if ( osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL(aProgramURL, aProgram))
164     {
165         throw Exception(
166             OUString(RTL_CONSTASCII_USTRINGPARAM("Cound not convert executable path")),
167             static_cast < XMailClient * > (this));
168     }
169 
170     const rtl_TextEncoding iEncoding = osl_getThreadTextEncoding();
171     aBuffer.append(OUStringToOString(aProgram, iEncoding));
172     aBuffer.append("\" ");
173 
174     try
175     {
176         // Query XNameAccess interface of the org.openoffice.Office.Common/ExternalMailer
177         // configuration node to retriece the users preferred email application. This may
178         // transparently by redirected to e.g. the corresponding GConf setting in GNOME.
179         OUString aConfigRoot = OUString(
180             RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Office.Common/ExternalMailer" ) );
181 
182         PropertyValue aProperty;
183         aProperty.Name = OUString( RTL_CONSTASCII_USTRINGPARAM("nodepath" ));
184         aProperty.Value = makeAny( aConfigRoot );
185 
186         Sequence< Any > aArgumentList( 1 );
187         aArgumentList[0] = makeAny( aProperty );
188 
189         Reference< XNameAccess > xNameAccess =
190             Reference< XNameAccess > (
191                 xConfigurationProvider->createInstanceWithArguments(
192                     OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationAccess" )),
193                     aArgumentList ),
194                 UNO_QUERY );
195 
196         if( xNameAccess.is() )
197         {
198             OUString aMailer;
199 
200             // Retrieve the value for "Program" node and append it feed senddoc with it
201             // using the (undocumented) --mailclient switch
202             xNameAccess->getByName( OUString( RTL_CONSTASCII_USTRINGPARAM("Program") ) ) >>= aMailer;
203 
204             if( aMailer.getLength() )
205             {
206                 // make sure we have a system path
207                 osl::FileBase::getSystemPathFromFileURL( aMailer, aMailer );
208 
209                 aBuffer.append("--mailclient ");
210                 aBuffer.append(OUStringToOString( aMailer, iEncoding ));
211                 aBuffer.append(" ");
212             }
213 #ifdef MACOSX
214             else
215                 aBuffer.append("--mailclient Mail ");
216 #endif
217         }
218 
219     }
220     catch( RuntimeException e )
221     {
222         OSL_TRACE( "RuntimeException caught accessing configuration provider." );
223         OSL_TRACE( OUStringToOString( e.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
224         throw e;
225     }
226 
227     // Append body if set in the message
228     OUString ustr = xMailMessage->getBody();
229     if ( ustr.getLength() > 0 )
230     {
231         aBuffer.append("--body \"");
232         escapeDoubleQuotes( aBuffer, ustr, iEncoding );
233         aBuffer.append("\" ");
234     }
235 
236     // Append subject if set in the message
237     ustr = xMailMessage->getSubject();
238     if ( ustr.getLength() > 0 )
239     {
240         aBuffer.append("--subject \"");
241         escapeDoubleQuotes( aBuffer, ustr, iEncoding );
242         aBuffer.append("\" ");
243     }
244 
245     // Append originator if set in the message
246     if ( xMailMessage->getOriginator().getLength() > 0 )
247     {
248         aBuffer.append("--from \"");
249         aBuffer.append(OUStringToOString(xMailMessage->getOriginator(), iEncoding));
250         aBuffer.append("\" ");
251     }
252 
253     // Append receipient if set in the message
254     if ( xMailMessage->getRecipient().getLength() > 0 )
255     {
256         aBuffer.append("--to \"");
257         aBuffer.append(OUStringToOString(xMailMessage->getRecipient(), iEncoding));
258         aBuffer.append("\" ");
259     }
260 
261     // Append carbon copy receipients set in the message
262     Sequence< OUString > aStringList = xMailMessage->getCcRecipient();
263     sal_Int32 n, nmax = aStringList.getLength();
264     for ( n = 0; n < nmax; n++ )
265     {
266         aBuffer.append("--cc \"");
267         aBuffer.append(OUStringToOString(aStringList[n], iEncoding));
268         aBuffer.append("\" ");
269     }
270 
271     // Append blind carbon copy receipients set in the message
272     aStringList = xMailMessage->getBccRecipient();
273     nmax = aStringList.getLength();
274     for ( n = 0; n < nmax; n++ )
275     {
276         aBuffer.append("--bcc \"");
277         aBuffer.append(OUStringToOString(aStringList[n], iEncoding));
278         aBuffer.append("\" ");
279     }
280 
281     // Append attachments set in the message
282     aStringList = xMailMessage->getAttachement();
283     nmax = aStringList.getLength();
284     for ( n = 0; n < nmax; n++ )
285     {
286         OUString aSystemPath;
287         if ( osl::FileBase::E_None == osl::FileBase::getSystemPathFromFileURL(aStringList[n], aSystemPath) )
288         {
289             aBuffer.append("--attach \"");
290             aBuffer.append(OUStringToOString(aSystemPath, iEncoding));
291             aBuffer.append("\" ");
292         }
293     }
294 
295     OString cmd = aBuffer.makeStringAndClear();
296     if ( 0 != pclose(popen(cmd.getStr(), "w")) )
297     {
298         throw ::com::sun::star::uno::Exception(
299             OUString(RTL_CONSTASCII_USTRINGPARAM( "No mail client configured" )),
300             static_cast < XMailClient * > (this) );
301     }
302 }
303 
304 OUString SAL_CALL
getImplementationName()305 SystemCommandMail::getImplementationName(  )
306 throw( RuntimeException )
307 {
308     return getImplementationName_static();
309 }
310 
311 sal_Bool SAL_CALL
supportsService(const OUString & ServiceName)312 SystemCommandMail::supportsService(
313     const OUString& ServiceName )
314 throw( RuntimeException )
315 {
316     Sequence < OUString > SupportedServicesNames = getSupportedServiceNames_static();
317 
318     for ( sal_Int32 n = SupportedServicesNames.getLength(); n--; )
319         if (SupportedServicesNames[n].compareTo(ServiceName) == 0)
320             return sal_True;
321 
322     return sal_False;
323 }
324 
325 Sequence< OUString > SAL_CALL
getSupportedServiceNames()326 SystemCommandMail::getSupportedServiceNames()
327 throw( RuntimeException )
328 {
329     return getSupportedServiceNames_static();
330 }
331 
332 Reference< XInterface >
Create(const Reference<XComponentContext> & xContext)333 SystemCommandMail::Create(
334     const Reference< XComponentContext > &xContext)
335 {
336     return Reference< XInterface >(
337         static_cast< cppu::OWeakObject *>(
338             new SystemCommandMail( xContext ) ) );
339 }
340 
341 OUString
getImplementationName_static()342 SystemCommandMail::getImplementationName_static()
343 {
344     return OUString( RTL_CONSTASCII_USTRINGPARAM( COMP_IMPL_NAME ) );
345 }
346 
347 Sequence< OUString >
getSupportedServiceNames_static()348 SystemCommandMail::getSupportedServiceNames_static()
349 {
350     Sequence< OUString > aRet(1);
351     aRet[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( COMP_SERVICE_NAME ) );
352     return aRet;
353 }
354 
355 }
356