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 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_shell.hxx"
26 
27 // For MAXHOSTNAMELEN constant
28 #include <sys/param.h>
29 
30 #include <premac.h>
31 #include <SystemConfiguration/SystemConfiguration.h>
32 #include <Foundation/NSPathUtilities.h>
33 #include <postmac.h>
34 
35 #include "macbackend.hxx"
36 
37 #include "com/sun/star/beans/Optional.hpp"
38 #include "rtl/ustrbuf.hxx"
39 #include "osl/file.h"
40 
41 #define SPACE      ' '
42 #define SEMI_COLON ';'
43 
44 typedef struct
45 {
46     rtl::OUString Server;
47     sal_Int32 Port;
48 } ProxyEntry;
49 
50 typedef enum {
51     sHTTP,
52 	sHTTPS,
53     sFTP
54 } ServiceType;
55 
56 //------------------------------------------------------------------------
57 // helper functions
58 //------------------------------------------------------------------------
59 
60 namespace // private
61 {
62 
63 /*
64  * Returns current proxy settings for selected service type (HTTP or
65  * FTP) as a C string (in the buffer specified by host and hostSize)
66  * and a port number.
67  */
68 
69 bool GetProxySetting(ServiceType sType, char *host, size_t hostSize, UInt16 *port)
70 {
71     bool                result;
72     CFDictionaryRef     proxyDict;
73     CFNumberRef         enableNum;
74     int                 enable;
75     CFStringRef         hostStr;
76     CFNumberRef         portNum;
77     int                 portInt;
78 
79     proxyDict = SCDynamicStoreCopyProxies(NULL);
80 
81     if (!proxyDict)
82         return false;
83 
84 	CFStringRef proxiesEnable;
85 	CFStringRef proxiesProxy;
86 	CFStringRef proxiesPort;
87 
88 	switch ( sType )
89 	{
90 		case sHTTP : proxiesEnable =  kSCPropNetProxiesHTTPEnable;
91 					 proxiesProxy = kSCPropNetProxiesHTTPProxy;
92 					 proxiesPort = kSCPropNetProxiesHTTPPort;
93 			break;
94 		case sHTTPS: proxiesEnable = kSCPropNetProxiesHTTPSEnable;
95 					 proxiesProxy = kSCPropNetProxiesHTTPSProxy;
96 					 proxiesPort = kSCPropNetProxiesHTTPSPort;
97 			break;
98 		default: proxiesEnable = kSCPropNetProxiesFTPEnable;
99 				 proxiesProxy = kSCPropNetProxiesFTPProxy;
100 				 proxiesPort = kSCPropNetProxiesFTPPort;
101 			break;
102 	}
103     // Proxy enabled?
104     enableNum = (CFNumberRef) CFDictionaryGetValue( proxyDict,
105                                                    proxiesEnable );
106 
107     result = (enableNum != NULL) && (CFGetTypeID(enableNum) == CFNumberGetTypeID());
108 
109     if (result)
110         result = CFNumberGetValue(enableNum, kCFNumberIntType, &enable) && (enable != 0);
111 
112     // Proxy enabled -> get hostname
113     if (result)
114     {
115         hostStr = (CFStringRef) CFDictionaryGetValue( proxyDict,
116                                                      proxiesProxy );
117 
118         result = (hostStr != NULL) && (CFGetTypeID(hostStr) == CFStringGetTypeID());
119     }
120 
121     if (result)
122         result = CFStringGetCString(hostStr, host, (CFIndex) hostSize, kCFStringEncodingASCII);
123 
124     // Get proxy port
125     if (result)
126     {
127         portNum = (CFNumberRef) CFDictionaryGetValue( proxyDict,
128                                                      proxiesPort );
129 
130         result = (portNum != NULL) && (CFGetTypeID(portNum) == CFNumberGetTypeID());
131     }
132     else
133     {
134         CFRelease(proxyDict);
135         return false;
136     }
137 
138     if (result)
139         result = CFNumberGetValue(portNum, kCFNumberIntType, &portInt);
140 
141     if (result)
142         *port = (UInt16) portInt;
143 
144     if (proxyDict)
145         CFRelease(proxyDict);
146 
147     if (!result)
148     {
149         *host = 0;
150         *port = 0;
151     }
152 
153     return result;
154 }
155 
156 } // end private namespace
157 
158 //------------------------------------------------------------------------------
159 
160 MacOSXBackend::MacOSXBackend()
161 {
162 }
163 
164 //------------------------------------------------------------------------------
165 
166 MacOSXBackend::~MacOSXBackend(void)
167 {
168 }
169 
170 //------------------------------------------------------------------------------
171 
172 MacOSXBackend* MacOSXBackend::createInstance()
173 {
174     return new MacOSXBackend;
175 }
176 
177 // ---------------------------------------------------------------------------------------
178 
179 rtl::OUString CFStringToOUString(const CFStringRef sOrig) {
180     CFRetain(sOrig);
181 
182     CFIndex nStringLen = CFStringGetLength(sOrig)+1;
183 
184     // Allocate a c string buffer
185     char sBuffer[nStringLen];
186 
187     CFStringGetCString(sOrig, sBuffer, nStringLen, kCFStringEncodingASCII);
188 
189     CFRelease(sOrig);
190 
191     return rtl::OUString::createFromAscii((sal_Char*)sBuffer);
192 }
193 
194 rtl::OUString GetOUString( NSString* pStr )
195 {
196     if( ! pStr )
197         return rtl::OUString();
198     int nLen = [pStr length];
199     if( nLen == 0 )
200         return rtl::OUString();
201 
202     rtl::OUStringBuffer aBuf( nLen+1 );
203     aBuf.setLength( nLen );
204     [pStr getCharacters: const_cast<sal_Unicode*>(aBuf.getStr())];
205     return aBuf.makeStringAndClear();
206 }
207 
208 void MacOSXBackend::setPropertyValue(
209     rtl::OUString const &, css::uno::Any const &)
210     throw (
211         css::beans::UnknownPropertyException, css::beans::PropertyVetoException,
212         css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
213         css::uno::RuntimeException)
214 {
215     throw css::lang::IllegalArgumentException(
216         rtl::OUString(
217             RTL_CONSTASCII_USTRINGPARAM("setPropertyValue not supported")),
218         static_cast< cppu::OWeakObject * >(this), -1);
219 }
220 
221 css::uno::Any MacOSXBackend::getPropertyValue(
222     rtl::OUString const & PropertyName)
223     throw (
224         css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
225         css::uno::RuntimeException)
226 {
227     if (PropertyName.equalsAsciiL(
228             RTL_CONSTASCII_STRINGPARAM("WorkPathVariable")))
229     {
230         rtl::OUString aDocDir;
231         NSArray* pPaths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, true );
232         if( pPaths && [pPaths count] > 0 )
233         {
234             aDocDir = GetOUString( [pPaths objectAtIndex: 0] );
235 
236             rtl::OUString aDocURL;
237             if( aDocDir.getLength() > 0 &&
238                 osl_getFileURLFromSystemPath( aDocDir.pData, &aDocURL.pData ) == osl_File_E_None )
239             {
240                 return css::uno::makeAny(
241                     css::beans::Optional< css::uno::Any >(
242                         true, css::uno::makeAny( aDocURL ) ) );
243             }
244             else
245             {
246                 OSL_TRACE( "user documents list contains empty file path or conversion failed" );
247             }
248         }
249         else
250         {
251             OSL_TRACE( "Got nil or empty list of user document directories" );
252         }
253         return css::uno::makeAny(css::beans::Optional< css::uno::Any >());
254     } else if (PropertyName.equalsAsciiL(
255                    RTL_CONSTASCII_STRINGPARAM("ooInetFTPProxyName")))
256     {
257         ProxyEntry aFtpProxy;
258 
259         char host[MAXHOSTNAMELEN];
260         UInt16 port;
261         bool retVal;
262 
263         retVal = GetProxySetting(sFTP, host, 100, &port);
264 
265         if (retVal)
266         {
267             aFtpProxy.Server = rtl::OUString::createFromAscii( host );
268         }
269 
270         // ftp proxy name
271         if( aFtpProxy.Server.getLength() > 0 )
272         {
273             return css::uno::makeAny(
274                 css::beans::Optional< css::uno::Any >(
275                     true, uno::makeAny( aFtpProxy.Server ) ) );
276         }
277         return css::uno::makeAny(css::beans::Optional< css::uno::Any >());
278     } else if (PropertyName.equalsAsciiL(
279                    RTL_CONSTASCII_STRINGPARAM("ooInetFTPProxyPort")))
280     {
281         ProxyEntry aFtpProxy;
282 
283         char host[MAXHOSTNAMELEN];
284         UInt16 port;
285         bool retVal;
286 
287         retVal = GetProxySetting(sFTP, host, 100, &port);
288 
289         if (retVal)
290         {
291             aFtpProxy.Port = port;
292         }
293 
294         // ftp proxy port
295         if( aFtpProxy.Port > 0 )
296         {
297             return css::uno::makeAny(
298                 css::beans::Optional< css::uno::Any >(
299                     true, uno::makeAny( aFtpProxy.Port ) ) );
300         }
301         return css::uno::makeAny(css::beans::Optional< css::uno::Any >());
302     } else if (PropertyName.equalsAsciiL(
303                    RTL_CONSTASCII_STRINGPARAM("ooInetHTTPProxyName")))
304     {
305         ProxyEntry aHttpProxy;
306 
307         char host[MAXHOSTNAMELEN];
308         UInt16 port;
309         bool retVal;
310 
311         retVal = GetProxySetting(sHTTP, host, 100, &port);
312 
313         if (retVal)
314         {
315             aHttpProxy.Server = rtl::OUString::createFromAscii( host );
316         }
317 
318         // http proxy name
319         if( aHttpProxy.Server.getLength() > 0 )
320         {
321             return css::uno::makeAny(
322                 css::beans::Optional< css::uno::Any >(
323                     true, uno::makeAny( aHttpProxy.Server ) ) );
324         }
325         return css::uno::makeAny(css::beans::Optional< css::uno::Any >());
326     } else if (PropertyName.equalsAsciiL(
327                    RTL_CONSTASCII_STRINGPARAM("ooInetHTTPProxyPort")))
328     {
329         ProxyEntry aHttpProxy;
330 
331         char host[MAXHOSTNAMELEN];
332         UInt16 port;
333         bool retVal;
334 
335         retVal = GetProxySetting(sHTTP, host, 100, &port);
336 
337         if (retVal)
338         {
339             aHttpProxy.Port = port;
340         }
341 
342         // http proxy port
343         if( aHttpProxy.Port > 0 )
344         {
345             return css::uno::makeAny(
346                 css::beans::Optional< css::uno::Any >(
347                     true, uno::makeAny( aHttpProxy.Port ) ) );
348         }
349         return css::uno::makeAny(css::beans::Optional< css::uno::Any >());
350     } else if (PropertyName.equalsAsciiL(
351                    RTL_CONSTASCII_STRINGPARAM("ooInetHTTPSProxyName")))
352     {
353         ProxyEntry aHttpsProxy;
354 
355         char host[MAXHOSTNAMELEN];
356         UInt16 port;
357         bool retVal;
358 
359         retVal = GetProxySetting(sHTTPS, host, 100, &port);
360 
361         if (retVal)
362         {
363             aHttpsProxy.Server = rtl::OUString::createFromAscii( host );
364         }
365 
366         // https proxy name
367         if( aHttpsProxy.Server.getLength() > 0 )
368         {
369             return css::uno::makeAny(
370                 css::beans::Optional< css::uno::Any >(
371                     true, uno::makeAny( aHttpsProxy.Server ) ) );
372         }
373         return css::uno::makeAny(css::beans::Optional< css::uno::Any >());
374     } else if (PropertyName.equalsAsciiL(
375                    RTL_CONSTASCII_STRINGPARAM("ooInetHTTPSProxyPort")))
376     {
377         ProxyEntry aHttpsProxy;
378 
379         char host[MAXHOSTNAMELEN];
380         UInt16 port;
381         bool retVal;
382 
383         retVal = GetProxySetting(sHTTPS, host, 100, &port);
384 
385         if (retVal)
386         {
387             aHttpsProxy.Port = port;
388         }
389 
390         // https proxy port
391         if( aHttpsProxy.Port > 0 )
392         {
393             return css::uno::makeAny(
394                 css::beans::Optional< css::uno::Any >(
395                     true, uno::makeAny( aHttpsProxy.Port ) ) );
396         }
397         return css::uno::makeAny(css::beans::Optional< css::uno::Any >());
398     } else if (PropertyName.equalsAsciiL(
399                    RTL_CONSTASCII_STRINGPARAM("ooInetProxyType")))
400     {
401         // override default for ProxyType, which is "0" meaning "No proxies".
402         sal_Int32 nProperties = 1;
403         return css::uno::makeAny(
404             css::beans::Optional< css::uno::Any >(
405                 true, uno::makeAny( nProperties ) ) );
406     } else if (PropertyName.equalsAsciiL(
407                    RTL_CONSTASCII_STRINGPARAM("ooInetNoProxy")))
408     {
409         rtl::OUString aProxyBypassList;
410 
411         CFArrayRef rExceptionsList;
412         CFDictionaryRef rProxyDict = SCDynamicStoreCopyProxies(NULL);
413 
414         if (!rProxyDict)
415             rExceptionsList = false;
416         else
417             rExceptionsList = (CFArrayRef) CFDictionaryGetValue(rProxyDict, kSCPropNetProxiesExceptionsList);
418 
419         if (rExceptionsList)
420         {
421             for (CFIndex idx = 0; idx < CFArrayGetCount(rExceptionsList); idx++)
422             {
423                 CFStringRef rException = (CFStringRef) CFArrayGetValueAtIndex(rExceptionsList, idx);
424 
425                 if (idx>0)
426                     aProxyBypassList += rtl::OUString::createFromAscii( ";" );
427 
428                 aProxyBypassList += CFStringToOUString(rException);
429             }
430         }
431 
432         if (rProxyDict)
433             CFRelease(rProxyDict);
434 
435         // fill proxy bypass list
436         if( aProxyBypassList.getLength() > 0 )
437         {
438             return css::uno::makeAny(
439                 css::beans::Optional< css::uno::Any >(
440                     true,
441                     uno::makeAny( aProxyBypassList.replace( SPACE, SEMI_COLON ) ) ) );
442         }
443         return css::uno::makeAny(css::beans::Optional< css::uno::Any >());
444     } else {
445         throw css::beans::UnknownPropertyException(
446             PropertyName, static_cast< cppu::OWeakObject * >(this));
447     }
448 }
449 
450 //------------------------------------------------------------------------------
451 
452 rtl::OUString SAL_CALL MacOSXBackend::getBackendName(void)
453 {
454 	return rtl::OUString::createFromAscii("com.sun.star.comp.configuration.backend.MacOSXBackend");
455 }
456 
457 //------------------------------------------------------------------------------
458 
459 rtl::OUString SAL_CALL MacOSXBackend::getImplementationName(void)
460     throw (uno::RuntimeException)
461 {
462     return getBackendName();
463 }
464 
465 //------------------------------------------------------------------------------
466 
467 uno::Sequence<rtl::OUString> SAL_CALL MacOSXBackend::getBackendServiceNames(void)
468 {
469     uno::Sequence<rtl::OUString> aServiceNameList(1);
470     aServiceNameList[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.backend.MacOSXBackend"));
471 
472     return aServiceNameList;
473 }
474 
475 //------------------------------------------------------------------------------
476 
477 sal_Bool SAL_CALL MacOSXBackend::supportsService(const rtl::OUString& aServiceName)
478     throw (uno::RuntimeException)
479 {
480     uno::Sequence< rtl::OUString > const svc = getBackendServiceNames();
481 
482     for(sal_Int32 i = 0; i < svc.getLength(); ++i )
483         if(svc[i] == aServiceName)
484             return true;
485 
486     return false;
487 }
488 
489 //------------------------------------------------------------------------------
490 
491 uno::Sequence<rtl::OUString> SAL_CALL MacOSXBackend::getSupportedServiceNames(void)
492     throw (uno::RuntimeException)
493 {
494     return getBackendServiceNames();
495 }
496