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 #ifndef INCLUDED_CURLSESSION_HXX
25 #define INCLUDED_CURLSESSION_HXX
26 
27 #include <vector>
28 #include <boost/shared_ptr.hpp>
29 #include <osl/mutex.hxx>
30 #include <comphelper/componentcontext.hxx>
31 #include <comphelper/logging.hxx>
32 #include "DAVResource.hxx"
33 #include "DAVSession.hxx"
34 #include "CurlTypes.hxx"
35 #include "CurlRequest.hxx"
36 #include "CurlLockStore.hxx"
37 #include "CurlUri.hxx"
38 #include "CurlInputStream.hxx"
39 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
40 #include <curl/curl.h>
41 #include <openssl/ssl.h>
42 
43 namespace ucbhelper { class ProxyDecider; }
44 
45 namespace http_dav_ucp
46 {
47 
48 // -------------------------------------------------------------------
49 // CurlSession
50 // A DAVSession implementation using the Curl library
51 // -------------------------------------------------------------------
52 
53 class CurlSession : public DAVSession
54 {
55 private:
56     osl::Mutex                      m_aMutex;
57     ::comphelper::ComponentContext  m_aContext;
58     ::comphelper::EventLogger       m_aLogger;
59 
60     CurlUri                 m_aUri;
61 
62     rtl::OUString           m_aProxyName;
63     sal_Int32               m_nProxyPort;
64     // The server, according RFC7231
65     // http://tools.ietf.org/html/rfc7231#section-7.4.2
66     rtl::OString            m_aServerHeaderField;
67 
68     CURL*                   m_pCurl;
69     bool                    m_bUseChunkedEncoding;
70     bool                    m_bTransferEncodingSwitched;
71 
72     const ucbhelper::InternetProxyDecider & m_rProxyDecider;
73 
74     DAVRequestEnvironment m_aEnv;
75 
76     static CurlLockStore m_aCurlLockStore;
77 
78     bool isSSLNeeded();
79 
80 
81     rtl::OUString           composeCurrentUri( const rtl::OUString & inPath );
82     void                    addEnvironmentRequestHeaders( CurlRequest &curlRequest,
83                                                           const DAVRequestEnvironment &env )
84                                 throw ( DAVException );
85     void                    processResponse( CurlRequest &curlRequest,
86                                              CURLcode curlCode )
87                                 throw ( DAVException );
88 
89     static CURLcode         Curl_SSLContextCallback( CURL *curl,
90                                                      void *ssl_ctx,
91                                                      void *userptr );
92     static int              OPENSSL_ValidateServerCertificate( int preverify_ok,
93                                                                X509_STORE_CTX *x509_ctx );
94     int                     validateServerX509Certificate( X509_STORE_CTX *x509StoreContext,
95                                                            int preverifyOk );
96     int                     verifyCertificateChain (
97                                 std::vector< uno::Sequence< sal_Int8 > > &asn1DerCertificates );
98 
99     static int              Curl_DebugCallback( CURL *,
100                                                 curl_infotype type,
101                                                 unsigned char *data,
102                                                 size_t size,
103                                                 void* userdata );
104     int                     curlDebugOutput( curl_infotype type, char *data, int size );
105 
106     static bool             Curl_ProvideCredentials( long statusCode,
107                                                      void *userdata ) throw (DAVException);
108     bool                    provideCredentials( const DAVRequestEnvironment &env,
109                                                 CurlRequest &request,
110                                                 long statusCode ) throw (DAVException);
111 
112 protected:
113     virtual ~CurlSession();
114 
115 public:
116     CurlSession( const rtl::Reference< DAVSessionFactory > & rSessionFactory,
117                  const rtl::OUString& inUri,
118                  const ucbhelper::InternetProxyDecider & rProxyDecider )
119         throw ( DAVException );
120 
121     // DAVSession methods
122     virtual sal_Bool CanUse( const ::rtl::OUString & inUri );
123 
124     virtual sal_Bool UsesProxy();
125 
126     const DAVRequestEnvironment & getRequestEnvironment() const
127     { return m_aEnv; }
128 
129     // allprop & named
130     virtual void
131     PROPFIND( const ::rtl::OUString & inPath,
132               const Depth inDepth,
133               const std::vector< ::rtl::OUString > & inPropNames,
134               std::vector< DAVResource > & ioResources,
135               const DAVRequestEnvironment & rEnv )
136         throw ( DAVException );
137 
138     // propnames
139     virtual void
140     PROPFIND( const ::rtl::OUString & inPath,
141               const Depth inDepth,
142               std::vector< DAVResourceInfo >& ioResInfo,
143               const DAVRequestEnvironment & rEnv )
144         throw ( DAVException );
145 
146     virtual void
147     PROPPATCH( const ::rtl::OUString & inPath,
148                const std::vector< ProppatchValue > & inValues,
149                const DAVRequestEnvironment & rEnv )
150         throw ( DAVException );
151 
152     virtual void
153     HEAD( const ::rtl::OUString &  inPath,
154           const std::vector< ::rtl::OUString > & inHeaderNames,
155           DAVResource & ioResource,
156           const DAVRequestEnvironment & rEnv )
157         throw ( DAVException );
158 
159     virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
160     GET( const ::rtl::OUString & inPath,
161          const DAVRequestEnvironment & rEnv )
162         throw ( DAVException );
163 
164     virtual void
165     GET( const ::rtl::OUString & inPath,
166          com::sun::star::uno::Reference<
167              com::sun::star::io::XOutputStream > &  ioOutputStream,
168          const DAVRequestEnvironment & rEnv )
169         throw ( DAVException );
170 
171     virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
172     GET( const ::rtl::OUString & inPath,
173          const std::vector< ::rtl::OUString > & inHeaderNames,
174          DAVResource & ioResource,
175          const DAVRequestEnvironment & rEnv )
176         throw ( DAVException );
177 
178     virtual void
179     GET( const ::rtl::OUString & inPath,
180          com::sun::star::uno::Reference<
181              com::sun::star::io::XOutputStream > & ioOutputStream,
182          const std::vector< ::rtl::OUString > & inHeaderNames,
183          DAVResource & ioResource,
184          const DAVRequestEnvironment & rEnv )
185         throw ( DAVException );
186 
187     virtual void
188     PUT( const ::rtl::OUString & inPath,
189          const com::sun::star::uno::Reference<
190              com::sun::star::io::XInputStream > & inInputStream,
191          const DAVRequestEnvironment & rEnv )
192         throw ( DAVException );
193 
194     virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
195     POST( const rtl::OUString & inPath,
196           const rtl::OUString & rContentType,
197           const rtl::OUString & rReferer,
198           const com::sun::star::uno::Reference<
199               com::sun::star::io::XInputStream > & inInputStream,
200           const DAVRequestEnvironment & rEnv )
201         throw ( DAVException );
202 
203     virtual void
204     POST( const rtl::OUString & inPath,
205           const rtl::OUString & rContentType,
206           const rtl::OUString & rReferer,
207           const com::sun::star::uno::Reference<
208               com::sun::star::io::XInputStream > & inInputStream,
209           com::sun::star::uno::Reference<
210               com::sun::star::io::XOutputStream > & oOutputStream,
211           const DAVRequestEnvironment & rEnv )
212         throw ( DAVException );
213 
214     virtual void
215     MKCOL( const ::rtl::OUString & inPath,
216            const DAVRequestEnvironment & rEnv )
217         throw ( DAVException );
218 
219     virtual void
220     COPY( const ::rtl::OUString & inSourceURL,
221           const ::rtl::OUString & inDestinationURL,
222           const DAVRequestEnvironment & rEnv,
223           sal_Bool inOverWrite )
224         throw ( DAVException );
225 
226     virtual void
227     MOVE( const ::rtl::OUString & inSourceURL,
228           const ::rtl::OUString & inDestinationURL,
229           const DAVRequestEnvironment & rEnv,
230           sal_Bool inOverWrite )
231         throw ( DAVException );
232 
233     virtual void DESTROY( const ::rtl::OUString & inPath,
234                           const DAVRequestEnvironment & rEnv )
235         throw ( DAVException );
236 
237     // set new lock.
238     virtual void LOCK( const ::rtl::OUString & inURL,
239                        com::sun::star::ucb::Lock & inLock,
240                        const DAVRequestEnvironment & rEnv )
241         throw ( DAVException );
242 
243     // refresh existing lock.
244     virtual sal_Int64 LOCK( const ::rtl::OUString & inURL,
245                             sal_Int64 nTimeout,
246                             const DAVRequestEnvironment & rEnv )
247         throw ( DAVException );
248 
249     virtual void UNLOCK( const ::rtl::OUString & inURL,
250                          const DAVRequestEnvironment & rEnv )
251         throw ( DAVException );
252 
253     // helpers
254     virtual void abort()
255         throw ( DAVException );
256 
257     const rtl::OUString & getHostName() const { return m_aUri.GetHost(); }
258     int getPort() const { return m_aUri.GetPort(); }
259 
260     const ::uno::Reference< ::lang::XMultiServiceFactory > getMSF()
261     { return m_xFactory->getServiceFactory(); }
262 
263     sal_Bool isDomainMatch( rtl::OUString certHostName );
264 
265     const rtl::OString & getServerHeaderField() { return m_aServerHeaderField; };
266 
267 private:
268     friend class CurlLockStore;
269 
270     void Init( void )
271         throw ( DAVException );
272 
273     void Init( const DAVRequestEnvironment & rEnv )
274         throw ( DAVException );
275 
276     const ucbhelper::InternetProxyServer & getProxySettings() const;
277 
278     void propfind( CurlRequest &curlRequest,
279                    const rtl::OUString &inPath,
280                    const Depth inDepth,
281                    const std::vector< ::rtl::OUString > * propNames,
282                    const bool onlyPropertyNames,
283                    const DAVRequestEnvironment & rEnv );
284 
285     bool removeExpiredLocktoken( const rtl::OUString & inURL,
286                                  const DAVRequestEnvironment & rEnv );
287 
288     // refresh lock, called by CurlLockStore::refreshLocks
289     bool LOCK( CurlLock * pLock,
290                sal_Int32 & rlastChanceToSendRefreshRequest );
291 
292     // unlock, called by CurlLockStore::~CurlLockStore
293     bool UNLOCK( CurlLock * pLock );
294 
295     /*
296     // low level GET implementation, used by public GET implementations
297     static int GET( CurlConnection * sess,
298                     const char * uri,
299                     //ne_block_reader reader,
300                     bool getheaders,
301                     void * userdata );
302 
303     // Buffer-based PUT implementation. Serf only has file descriptor-
304     // based API.
305     static int PUT( CurlConnection * sess,
306                     const char * uri,
307                     const char * buffer,
308                     size_t size );
309 
310     // Buffer-based POST implementation. Serf only has file descriptor-
311     // based API.
312     int POST( CurlConnection * sess,
313               const char * uri,
314               const char * buffer,
315               //ne_block_reader reader,
316               void * userdata,
317               const rtl::OUString & rContentType,
318               const rtl::OUString & rReferer );
319     */
320 
321     // Helper: XInputStream -> Sequence< sal_Int8 >
322     static bool getDataFromInputStream(
323         const com::sun::star::uno::Reference<
324             com::sun::star::io::XInputStream > & xStream,
325         com::sun::star::uno::Sequence< sal_Int8 > & rData,
326         bool bAppendTrailingZeroByte );
327 
328     /*
329     rtl::OUString makeAbsoluteURL( rtl::OUString const & rURL ) const;
330     */
331 };
332 
333 } // namespace http_dav_ucp
334 
335 #endif // INCLUDED_CURLSESSION_HXX
336