Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <boost/unordered_map.hpp>
31 : : #include <vector>
32 : : #include <string.h>
33 : : #include "osl/diagnose.h"
34 : : #include "osl/time.h"
35 : : #include <rtl/string.h>
36 : : #include <ne_socket.h>
37 : : #include <ne_auth.h>
38 : : #include <ne_redirect.h>
39 : : #include <ne_ssl.h>
40 : :
41 : : #if NEON_VERSION < 0x0260
42 : : // old neon versions forgot to set this
43 : : extern "C" {
44 : : #endif
45 : : #include <ne_compress.h>
46 : : #if NEON_VERSION < 0x0260
47 : : }
48 : : #endif
49 : :
50 : : #include "libxml/parser.h"
51 : : #include "rtl/ustrbuf.hxx"
52 : : #include "comphelper/sequence.hxx"
53 : : #include <comphelper/stl_types.hxx>
54 : : #include "ucbhelper/simplecertificatevalidationrequest.hxx"
55 : :
56 : : #include "DAVAuthListener.hxx"
57 : : #include "NeonTypes.hxx"
58 : : #include "NeonSession.hxx"
59 : : #include "NeonInputStream.hxx"
60 : : #include "NeonPropFindRequest.hxx"
61 : : #include "NeonHeadRequest.hxx"
62 : : #include "NeonUri.hxx"
63 : : #include "LinkSequence.hxx"
64 : : #include "UCBDeadPropertyValue.hxx"
65 : :
66 : : #include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
67 : : #include <com/sun/star/security/XCertificate.hpp>
68 : : #include <com/sun/star/security/CertificateValidity.hpp>
69 : : #include <com/sun/star/security/CertificateContainerStatus.hpp>
70 : : #include <com/sun/star/security/CertificateContainer.hpp>
71 : : #include <com/sun/star/security/XCertificateContainer.hpp>
72 : : #include <com/sun/star/ucb/Lock.hpp>
73 : : #include <com/sun/star/beans/NamedValue.hpp>
74 : : #include <com/sun/star/xml/crypto/XSEInitializer.hpp>
75 : :
76 : : #include <boost/bind.hpp>
77 : :
78 : : using namespace com::sun::star;
79 : : using namespace webdav_ucp;
80 : :
81 : : #define SEINITIALIZER_COMPONENT "com.sun.star.xml.crypto.SEInitializer"
82 : :
83 : : #ifndef EOL
84 : : # define EOL "\r\n"
85 : : #endif
86 : :
87 : : // -------------------------------------------------------------------
88 : : // RequestData
89 : : // -------------------------------------------------------------------
90 : :
91 : 0 : struct RequestData
92 : : {
93 : : // POST
94 : : rtl::OUString aContentType;
95 : : rtl::OUString aReferer;
96 : :
97 : 0 : RequestData() {}
98 : 0 : RequestData( const rtl::OUString & rContentType,
99 : : const rtl::OUString & rReferer )
100 : 0 : : aContentType( rContentType ), aReferer( rReferer ) {}
101 : : };
102 : :
103 : : // -------------------------------------------------------------------
104 : : // RequestDataMap
105 : : // -------------------------------------------------------------------
106 : :
107 : : struct equalPtr
108 : : {
109 : 0 : bool operator()( const ne_request* p1, const ne_request* p2 ) const
110 : : {
111 : 0 : return p1 == p2;
112 : : }
113 : : };
114 : :
115 : : struct hashPtr
116 : : {
117 : 0 : size_t operator()( const ne_request* p ) const
118 : : {
119 : 0 : return (size_t)p;
120 : : }
121 : : };
122 : :
123 : : typedef boost::unordered_map
124 : : <
125 : : ne_request*,
126 : : RequestData,
127 : : hashPtr,
128 : : equalPtr
129 : : >
130 : : RequestDataMap;
131 : :
132 : : // -------------------------------------------------------------------
133 : : // Helper fuction
134 : : // -------------------------------------------------------------------
135 : 0 : static sal_uInt16 makeStatusCode( const rtl::OUString & rStatusText )
136 : : {
137 : : // Extract status code from session error string. Unfortunately
138 : : // neon provides no direct access to the status code...
139 : :
140 [ # # ]: 0 : if ( rStatusText.getLength() < 3 )
141 : : {
142 : : OSL_FAIL(
143 : : "makeStatusCode - status text string to short!" );
144 : 0 : return 0;
145 : : }
146 : :
147 : 0 : sal_Int32 nPos = rStatusText.indexOf( ' ' );
148 [ # # ]: 0 : if ( nPos == -1 )
149 : : {
150 : : OSL_FAIL( "makeStatusCode - wrong status text format!" );
151 : 0 : return 0;
152 : : }
153 : :
154 : 0 : return sal_uInt16( rStatusText.copy( 0, nPos ).toInt32() );
155 : : }
156 : :
157 : : // -------------------------------------------------------------------
158 : 0 : static bool noKeepAlive( const uno::Sequence< beans::NamedValue >& rFlags )
159 : : {
160 [ # # ]: 0 : if ( !rFlags.hasElements() )
161 : 0 : return false;
162 : :
163 : : // find "KeepAlive" property
164 : 0 : const beans::NamedValue* pAry(rFlags.getConstArray());
165 : 0 : const sal_Int32 nLen(rFlags.getLength());
166 : : const beans::NamedValue* pValue(
167 : : std::find_if(pAry,pAry+nLen,
168 : : boost::bind(comphelper::TNamedValueEqualFunctor(),
169 : : _1,
170 [ # # ][ # # ]: 0 : rtl::OUString("KeepAlive"))));
171 [ # # ][ # # ]: 0 : if ( pValue != pAry+nLen && !pValue->Value.get<sal_Bool>() )
[ # # ]
172 : 0 : return true;
173 : :
174 : 0 : return false;
175 : : }
176 : :
177 : : // -------------------------------------------------------------------
178 : 0 : struct NeonRequestContext
179 : : {
180 : : uno::Reference< io::XOutputStream > xOutputStream;
181 : : rtl::Reference< NeonInputStream > xInputStream;
182 : : const std::vector< ::rtl::OUString > * pHeaderNames;
183 : : DAVResource * pResource;
184 : :
185 : 0 : NeonRequestContext( uno::Reference< io::XOutputStream > & xOutStrm )
186 : : : xOutputStream( xOutStrm ), xInputStream( 0 ),
187 : 0 : pHeaderNames( 0 ), pResource( 0 ) {}
188 : :
189 : 0 : NeonRequestContext( const rtl::Reference< NeonInputStream > & xInStrm )
190 : : : xOutputStream( 0 ), xInputStream( xInStrm ),
191 : 0 : pHeaderNames( 0 ), pResource( 0 ) {}
192 : :
193 : 0 : NeonRequestContext( uno::Reference< io::XOutputStream > & xOutStrm,
194 : : const std::vector< ::rtl::OUString > & inHeaderNames,
195 : : DAVResource & ioResource )
196 : : : xOutputStream( xOutStrm ), xInputStream( 0 ),
197 : 0 : pHeaderNames( &inHeaderNames ), pResource( &ioResource ) {}
198 : :
199 : 0 : NeonRequestContext( const rtl::Reference< NeonInputStream > & xInStrm,
200 : : const std::vector< ::rtl::OUString > & inHeaderNames,
201 : : DAVResource & ioResource )
202 : : : xOutputStream( 0 ), xInputStream( xInStrm ),
203 : 0 : pHeaderNames( &inHeaderNames ), pResource( &ioResource ) {}
204 : : };
205 : :
206 : : //--------------------------------------------------------------------
207 : : //--------------------------------------------------------------------
208 : : //
209 : : // Callback functions
210 : : //
211 : : //--------------------------------------------------------------------
212 : : //--------------------------------------------------------------------
213 : :
214 : : // -------------------------------------------------------------------
215 : : // ResponseBlockReader
216 : : // A simple Neon response_block_reader for use with an XInputStream
217 : : // -------------------------------------------------------------------
218 : :
219 : 0 : extern "C" int NeonSession_ResponseBlockReader(void * inUserData,
220 : : const char * inBuf,
221 : : size_t inLen )
222 : : {
223 : : // neon sometimes calls this function with (inLen == 0)...
224 [ # # ]: 0 : if ( inLen > 0 )
225 : : {
226 : : NeonRequestContext * pCtx
227 : 0 : = static_cast< NeonRequestContext * >( inUserData );
228 : :
229 : : rtl::Reference< NeonInputStream > xInputStream(
230 : 0 : pCtx->xInputStream );
231 : :
232 [ # # ]: 0 : if ( xInputStream.is() )
233 [ # # ]: 0 : xInputStream->AddToStream( inBuf, inLen );
234 : : }
235 : 0 : return 0;
236 : : }
237 : :
238 : : // -------------------------------------------------------------------
239 : : // ResponseBlockWriter
240 : : // A simple Neon response_block_reader for use with an XOutputStream
241 : : // -------------------------------------------------------------------
242 : :
243 : 0 : extern "C" int NeonSession_ResponseBlockWriter( void * inUserData,
244 : : const char * inBuf,
245 : : size_t inLen )
246 : : {
247 : : // neon calls this function with (inLen == 0)...
248 [ # # ]: 0 : if ( inLen > 0 )
249 : : {
250 : : NeonRequestContext * pCtx
251 : 0 : = static_cast< NeonRequestContext * >( inUserData );
252 : : uno::Reference< io::XOutputStream > xOutputStream
253 : 0 : = pCtx->xOutputStream;
254 : :
255 [ # # ]: 0 : if ( xOutputStream.is() )
256 : : {
257 [ # # ]: 0 : const uno::Sequence< sal_Int8 > aSeq( (sal_Int8 *)inBuf, inLen );
258 [ # # ][ # # ]: 0 : xOutputStream->writeBytes( aSeq );
[ # # ]
259 : 0 : }
260 : : }
261 : 0 : return 0;
262 : : }
263 : :
264 : : // -------------------------------------------------------------------
265 : 0 : extern "C" int NeonSession_NeonAuth( void * inUserData,
266 : : #ifdef NE_FEATURE_SSPI
267 : : const char * inAuthProtocol,
268 : : #endif
269 : : const char * inRealm,
270 : : int attempt,
271 : : char * inoutUserName,
272 : : char * inoutPassWord )
273 : : {
274 : : /* The callback used to request the username and password in the given
275 : : * realm. The username and password must be copied into the buffers
276 : : * which are both of size NE_ABUFSIZ. The 'attempt' parameter is zero
277 : : * on the first call to the callback, and increases by one each time
278 : : * an attempt to authenticate fails.
279 : : *
280 : : * The callback must return zero to indicate that authentication
281 : : * should be attempted with the username/password, or non-zero to
282 : : * cancel the request. (if non-zero, username and password are
283 : : * ignored.) */
284 : :
285 : 0 : NeonSession * theSession = static_cast< NeonSession * >( inUserData );
286 : : DAVAuthListener * pListener
287 : 0 : = theSession->getRequestEnvironment().m_xAuthListener.get();
288 [ # # ]: 0 : if ( !pListener )
289 : : {
290 : : // abort
291 : 0 : return -1;
292 : : }
293 : 0 : rtl::OUString theUserName;
294 : 0 : rtl::OUString thePassWord;
295 : :
296 [ # # ]: 0 : if ( attempt == 0 )
297 : : {
298 : : // neon does not handle username supplied with request URI (for
299 : : // instance when doing FTP over proxy - last checked: 0.23.5 )
300 : :
301 : : try
302 : : {
303 [ # # ]: 0 : NeonUri uri( theSession->getRequestEnvironment().m_aRequestURI );
304 : 0 : rtl::OUString aUserInfo( uri.GetUserInfo() );
305 [ # # ]: 0 : if ( !aUserInfo.isEmpty() )
306 : : {
307 : 0 : sal_Int32 nPos = aUserInfo.indexOf( '@' );
308 [ # # ]: 0 : if ( nPos == -1 )
309 : : {
310 : 0 : theUserName = aUserInfo;
311 : : }
312 : : else
313 : : {
314 : 0 : theUserName = aUserInfo.copy( 0, nPos );
315 : 0 : thePassWord = aUserInfo.copy( nPos + 1 );
316 : : }
317 [ # # ]: 0 : }
318 : : }
319 : 0 : catch ( DAVException const & )
320 : : {
321 : : // abort
322 : 0 : return -1;
323 : : }
324 : : }
325 : : else
326 : : {
327 : : // username buffer is prefilled with user name from last attempt.
328 : 0 : theUserName = rtl::OUString::createFromAscii( inoutUserName );
329 : : // @@@ Neon does not initialize password buffer (last checked: 0.22.0).
330 : : //thePassWord = rtl::OUString::createFromAscii( inoutPassWord );
331 : : }
332 : :
333 : 0 : bool bCanUseSystemCreds = false;
334 : :
335 : : #ifdef NE_FEATURE_SSPI
336 : : bCanUseSystemCreds
337 : : = (attempt == 0) && // avoid endless loops
338 : : ne_has_support( NE_FEATURE_SSPI ) && // Windows-only feature.
339 : : ( ( ne_strcasecmp( inAuthProtocol, "NTLM" ) == 0 ) ||
340 : : ( ne_strcasecmp( inAuthProtocol, "Negotiate" ) == 0 ) );
341 : : #endif
342 : :
343 : : int theRetVal = pListener->authenticate(
344 : : rtl::OUString::createFromAscii( inRealm ),
345 : 0 : theSession->getHostName(),
346 : : theUserName,
347 : : thePassWord,
348 [ # # ]: 0 : bCanUseSystemCreds);
349 : :
350 : : rtl::OString aUser(
351 [ # # ]: 0 : rtl::OUStringToOString( theUserName, RTL_TEXTENCODING_UTF8 ) );
352 [ # # ]: 0 : if ( aUser.getLength() > ( NE_ABUFSIZ - 1 ) )
353 : : {
354 : : OSL_FAIL(
355 : : "NeonSession_NeonAuth - username to long!" );
356 : 0 : return -1;
357 : : }
358 : :
359 : : rtl::OString aPass(
360 [ # # ]: 0 : rtl::OUStringToOString( thePassWord, RTL_TEXTENCODING_UTF8 ) );
361 [ # # ]: 0 : if ( aPass.getLength() > ( NE_ABUFSIZ - 1 ) )
362 : : {
363 : : OSL_FAIL(
364 : : "NeonSession_NeonAuth - password to long!" );
365 : 0 : return -1;
366 : : }
367 : :
368 : : strcpy( inoutUserName, // #100211# - checked
369 [ # # ]: 0 : rtl::OUStringToOString( theUserName, RTL_TEXTENCODING_UTF8 ).getStr() );
370 : :
371 : : strcpy( inoutPassWord, // #100211# - checked
372 [ # # ]: 0 : rtl::OUStringToOString( thePassWord, RTL_TEXTENCODING_UTF8 ).getStr() );
373 : :
374 [ # # ]: 0 : return theRetVal;
375 : : }
376 : :
377 : : // -------------------------------------------------------------------
378 : :
379 : : namespace {
380 : : // -------------------------------------------------------------------
381 : : // Helper function
382 : 0 : ::rtl::OUString GetHostnamePart( const ::rtl::OUString& _rRawString )
383 : : {
384 : 0 : ::rtl::OUString sPart;
385 : 0 : ::rtl::OUString sPartId("CN=");
386 : 0 : sal_Int32 nContStart = _rRawString.indexOf( sPartId );
387 [ # # ]: 0 : if ( nContStart != -1 )
388 : : {
389 : 0 : nContStart = nContStart + sPartId.getLength();
390 : : sal_Int32 nContEnd
391 : 0 : = _rRawString.indexOf( sal_Unicode( ',' ), nContStart );
392 : 0 : sPart = _rRawString.copy( nContStart, nContEnd - nContStart );
393 : : }
394 : 0 : return sPart;
395 : : }
396 : : } // namespace
397 : :
398 : : // -------------------------------------------------------------------
399 : 0 : extern "C" int NeonSession_CertificationNotify( void *userdata,
400 : : int failures,
401 : : const ne_ssl_certificate *cert )
402 : : {
403 : : OSL_ASSERT( cert );
404 : :
405 : 0 : NeonSession * pSession = static_cast< NeonSession * >( userdata );
406 : 0 : uno::Reference< security::XCertificateContainer > xCertificateContainer;
407 : : try
408 : : {
409 : : xCertificateContainer
410 : : = uno::Reference< security::XCertificateContainer >(
411 [ # # # # ]: 0 : pSession->getMSF()->createInstance(
[ # # ]
412 : 0 : rtl::OUString( "com.sun.star.security.CertificateContainer" ) ),
413 [ # # ][ # # ]: 0 : uno::UNO_QUERY );
[ # # ]
414 : : }
415 [ # # ]: 0 : catch ( uno::Exception const & )
416 : : {
417 : : }
418 : :
419 [ # # ]: 0 : if ( !xCertificateContainer.is() )
420 : 0 : return 1;
421 : :
422 : 0 : failures = 0;
423 : :
424 [ # # ][ # # ]: 0 : char * dn = ne_ssl_readable_dname( ne_ssl_cert_subject( cert ) );
425 [ # # ]: 0 : rtl::OUString cert_subject( dn, strlen( dn ), RTL_TEXTENCODING_UTF8, 0 );
426 : :
427 : 0 : ne_free( dn );
428 : :
429 : : security::CertificateContainerStatus certificateContainer(
430 [ # # ]: 0 : xCertificateContainer->hasCertificate(
431 [ # # ]: 0 : pSession->getHostName(), cert_subject ) );
432 : :
433 [ # # ]: 0 : if ( certificateContainer != security::CertificateContainerStatus_NOCERT )
434 : : return
435 : : certificateContainer == security::CertificateContainerStatus_TRUSTED
436 : : ? 0
437 : 0 : : 1;
438 : :
439 : 0 : uno::Reference< xml::crypto::XSEInitializer > xSEInitializer;
440 : : try
441 : : {
442 : : xSEInitializer = uno::Reference< xml::crypto::XSEInitializer >(
443 [ # # # # ]: 0 : pSession->getMSF()->createInstance(
[ # # ]
444 : 0 : rtl::OUString( SEINITIALIZER_COMPONENT ) ),
445 [ # # ][ # # ]: 0 : uno::UNO_QUERY );
[ # # ]
446 : : }
447 [ # # ]: 0 : catch ( uno::Exception const & )
448 : : {
449 : : }
450 : :
451 [ # # ]: 0 : if ( !xSEInitializer.is() )
452 : 0 : return 1;
453 : :
454 : : uno::Reference< xml::crypto::XXMLSecurityContext > xSecurityContext(
455 [ # # ][ # # ]: 0 : xSEInitializer->createSecurityContext( rtl::OUString() ) );
456 : :
457 : : uno::Reference< xml::crypto::XSecurityEnvironment > xSecurityEnv(
458 [ # # ][ # # ]: 0 : xSecurityContext->getSecurityEnvironment() );
459 : :
460 : : //The end entity certificate
461 [ # # ]: 0 : char * eeCertB64 = ne_ssl_cert_export( cert );
462 : :
463 : 0 : rtl::OString sEECertB64( eeCertB64 );
464 : :
465 : : uno::Reference< security::XCertificate > xEECert(
466 [ # # ]: 0 : xSecurityEnv->createCertificateFromAscii(
467 [ # # ][ # # ]: 0 : rtl::OStringToOUString( sEECertB64, RTL_TEXTENCODING_ASCII_US ) ) );
468 : :
469 : 0 : ne_free( eeCertB64 );
470 : 0 : eeCertB64 = 0;
471 : :
472 [ # # ]: 0 : std::vector< uno::Reference< security::XCertificate > > vecCerts;
473 : 0 : const ne_ssl_certificate * issuerCert = cert;
474 : 0 : do
475 : : {
476 : : //get the intermediate certificate
477 : : //the returned value is const ! Therfore it does not need to be freed
478 : : //with ne_ssl_cert_free, which takes a non-const argument
479 [ # # ]: 0 : issuerCert = ne_ssl_cert_signedby( issuerCert );
480 [ # # ]: 0 : if ( NULL == issuerCert )
481 : : break;
482 : :
483 [ # # ]: 0 : char * imCertB64 = ne_ssl_cert_export( issuerCert );
484 : 0 : rtl::OString sInterMediateCertB64( imCertB64 );
485 : 0 : ne_free( imCertB64 );
486 : :
487 : : uno::Reference< security::XCertificate> xImCert(
488 [ # # ]: 0 : xSecurityEnv->createCertificateFromAscii(
489 [ # # ][ # # ]: 0 : rtl::OStringToOUString( sInterMediateCertB64, RTL_TEXTENCODING_ASCII_US ) ) );
490 [ # # ]: 0 : if ( xImCert.is() )
491 [ # # ]: 0 : vecCerts.push_back( xImCert );
492 : : }
493 : : while ( 1 );
494 : :
495 [ # # ]: 0 : sal_Int64 certValidity = xSecurityEnv->verifyCertificate( xEECert,
496 [ # # ][ # # ]: 0 : ::comphelper::containerToSequence( vecCerts ) );
[ # # ]
497 : :
498 [ # # ]: 0 : if ( pSession->isDomainMatch(
499 [ # # ][ # # ]: 0 : GetHostnamePart( xEECert.get()->getSubjectName() ) ) )
[ # # ]
500 : : {
501 : : // if host name matched with certificate then look if the
502 : : // certificate was ok
503 [ # # ]: 0 : if( certValidity == security::CertificateValidity::VALID )
504 : 0 : return 0;
505 : : }
506 : :
507 : : const uno::Reference< ucb::XCommandEnvironment > xEnv(
508 : 0 : pSession->getRequestEnvironment().m_xEnv );
509 [ # # ]: 0 : if ( xEnv.is() )
510 : : {
511 : 0 : failures = static_cast< int >( certValidity );
512 : :
513 : : uno::Reference< task::XInteractionHandler > xIH(
514 [ # # ][ # # ]: 0 : xEnv->getInteractionHandler() );
515 [ # # ]: 0 : if ( xIH.is() )
516 : : {
517 : : rtl::Reference< ucbhelper::SimpleCertificateValidationRequest >
518 : : xRequest( new ucbhelper::SimpleCertificateValidationRequest(
519 [ # # ]: 0 : (sal_Int32)failures, xEECert, pSession->getHostName() ) );
520 [ # # ][ # # ]: 0 : xIH->handle( xRequest.get() );
[ # # ][ # # ]
521 : :
522 : : rtl::Reference< ucbhelper::InteractionContinuation > xSelection
523 [ # # ]: 0 : = xRequest->getSelection();
524 : :
525 [ # # ]: 0 : if ( xSelection.is() )
526 : : {
527 : : uno::Reference< task::XInteractionApprove > xApprove(
528 [ # # ]: 0 : xSelection.get(), uno::UNO_QUERY );
529 [ # # ]: 0 : if ( xApprove.is() )
530 : : {
531 [ # # ]: 0 : xCertificateContainer->addCertificate(
532 [ # # ]: 0 : pSession->getHostName(), cert_subject, sal_True );
533 : 0 : return 0;
534 : : }
535 : : else
536 : : {
537 : : // Don't trust cert
538 [ # # ]: 0 : xCertificateContainer->addCertificate(
539 [ # # ]: 0 : pSession->getHostName(), cert_subject, sal_False );
540 : 0 : return 1;
541 : 0 : }
542 [ # # ][ # # ]: 0 : }
543 : : }
544 : : else
545 : : {
546 : : // Don't trust cert
547 [ # # ]: 0 : xCertificateContainer->addCertificate(
548 [ # # ]: 0 : pSession->getHostName(), cert_subject, sal_False );
549 : 0 : return 1;
550 [ # # ]: 0 : }
551 : : }
552 : 0 : return 1;
553 : : }
554 : :
555 : : // -------------------------------------------------------------------
556 : 0 : extern "C" void NeonSession_PreSendRequest( ne_request * req,
557 : : void * userdata,
558 : : ne_buffer * headers )
559 : : {
560 : : // userdata -> value returned by 'create'
561 : :
562 : 0 : NeonSession * pSession = static_cast< NeonSession * >( userdata );
563 [ # # ]: 0 : if ( pSession )
564 : : {
565 : : // If there is a proxy server in between, it shall never use
566 : : // cached data. We always want 'up-to-date' data.
567 [ # # ]: 0 : ne_buffer_concat( headers, "Pragma: no-cache", EOL, NULL );
568 : : // alternative, but understoud by HTTP 1.1 servers only:
569 : : // ne_buffer_concat( headers, "Cache-Control: max-age=0", EOL, NULL );
570 : :
571 : : const RequestDataMap * pRequestData
572 : : = static_cast< const RequestDataMap* >(
573 : 0 : pSession->getRequestData() );
574 : :
575 [ # # ]: 0 : RequestDataMap::const_iterator it = pRequestData->find( req );
576 [ # # ][ # # ]: 0 : if ( it != pRequestData->end() )
577 : : {
578 [ # # ][ # # ]: 0 : if ( !(*it).second.aContentType.isEmpty() )
579 : : {
580 : 0 : char * pData = headers->data;
581 [ # # ]: 0 : if ( strstr( pData, "Content-Type:" ) == NULL )
582 : : {
583 : : rtl::OString aType
584 [ # # ]: 0 : = rtl::OUStringToOString( (*it).second.aContentType,
585 [ # # ]: 0 : RTL_TEXTENCODING_UTF8 );
586 : : ne_buffer_concat( headers, "Content-Type: ",
587 [ # # ]: 0 : aType.getStr(), EOL, NULL );
588 : : }
589 : : }
590 : :
591 [ # # ][ # # ]: 0 : if ( !(*it).second.aReferer.isEmpty() )
592 : : {
593 : 0 : char * pData = headers->data;
594 [ # # ]: 0 : if ( strstr( pData, "Referer:" ) == NULL )
595 : : {
596 : : rtl::OString aReferer
597 [ # # ]: 0 : = rtl::OUStringToOString( (*it).second.aReferer,
598 [ # # ]: 0 : RTL_TEXTENCODING_UTF8 );
599 : : ne_buffer_concat( headers, "Referer: ",
600 [ # # ]: 0 : aReferer.getStr(), EOL, NULL );
601 : : }
602 : : }
603 : : }
604 : :
605 : : const DAVRequestHeaders & rHeaders
606 : 0 : = pSession->getRequestEnvironment().m_aRequestHeaders;
607 : :
608 : 0 : DAVRequestHeaders::const_iterator it1( rHeaders.begin() );
609 : 0 : const DAVRequestHeaders::const_iterator end1( rHeaders.end() );
610 : :
611 [ # # ][ # # ]: 0 : while ( it1 != end1 )
612 : : {
613 : : rtl::OString aHeader
614 : 0 : = rtl::OUStringToOString( (*it1).first,
615 [ # # ]: 0 : RTL_TEXTENCODING_UTF8 );
616 : : rtl::OString aValue
617 : 0 : = rtl::OUStringToOString( (*it1).second,
618 [ # # ]: 0 : RTL_TEXTENCODING_UTF8 );
619 : : ne_buffer_concat( headers, aHeader.getStr(), ": ",
620 [ # # ]: 0 : aValue.getStr(), EOL, NULL );
621 : :
622 : 0 : ++it1;
623 : 0 : }
624 : : }
625 : 0 : }
626 : :
627 : : // -------------------------------------------------------------------
628 : : // static members!
629 : : bool NeonSession::m_bGlobalsInited = false;
630 : : //See https://bugzilla.redhat.com/show_bug.cgi?id=544619#c4
631 : : //neon is threadsafe, but uses gnutls which is only thread-safe
632 : : //if initialized to be thread-safe. cups, unfortunately, generally
633 : : //initializes it first, and as non-thread-safe, leaving the entire
634 : : //stack unsafe
635 : 2 : osl::Mutex aGlobalNeonMutex;
636 : 2 : NeonLockStore NeonSession::m_aNeonLockStore;
637 : :
638 : : // -------------------------------------------------------------------
639 : : // Constructor
640 : : // -------------------------------------------------------------------
641 : 0 : NeonSession::NeonSession(
642 : : const rtl::Reference< DAVSessionFactory > & rSessionFactory,
643 : : const rtl::OUString& inUri,
644 : : const uno::Sequence< beans::NamedValue >& rFlags,
645 : : const ucbhelper::InternetProxyDecider & rProxyDecider )
646 : : throw ( DAVException )
647 : : : DAVSession( rSessionFactory ),
648 : : m_aFlags( rFlags ),
649 : : m_pHttpSession( 0 ),
650 [ # # ]: 0 : m_pRequestData( new RequestDataMap ),
651 [ # # ][ # # ]: 0 : m_rProxyDecider( rProxyDecider )
[ # # ][ # # ]
652 : : {
653 [ # # ]: 0 : NeonUri theUri( inUri );
654 : 0 : m_aScheme = theUri.GetScheme();
655 : 0 : m_aHostName = theUri.GetHost();
656 [ # # ]: 0 : m_nPort = theUri.GetPort();
657 : 0 : }
658 : :
659 : : // -------------------------------------------------------------------
660 : : // Destructor
661 : : // -------------------------------------------------------------------
662 [ # # ][ # # ]: 0 : NeonSession::~NeonSession( )
[ # # ]
663 : : {
664 [ # # ]: 0 : if ( m_pHttpSession )
665 : : {
666 : : {
667 [ # # ]: 0 : osl::Guard< osl::Mutex > theGlobalGuard( aGlobalNeonMutex );
668 [ # # ][ # # ]: 0 : ne_session_destroy( m_pHttpSession );
669 : : }
670 : 0 : m_pHttpSession = 0;
671 : : }
672 [ # # ][ # # ]: 0 : delete static_cast< RequestDataMap * >( m_pRequestData );
673 [ # # ]: 0 : }
674 : :
675 : : // -------------------------------------------------------------------
676 : 0 : void NeonSession::Init( const DAVRequestEnvironment & rEnv )
677 : : throw ( DAVException )
678 : : {
679 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
680 [ # # ]: 0 : m_aEnv = rEnv;
681 [ # # ][ # # ]: 0 : Init();
682 : 0 : }
683 : :
684 : : // -------------------------------------------------------------------
685 : 0 : void NeonSession::Init()
686 : : throw ( DAVException )
687 : : {
688 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
689 : :
690 : 0 : bool bCreateNewSession = false;
691 : :
692 [ # # ]: 0 : if ( m_pHttpSession == 0 )
693 : : {
694 : : // Ensure that Neon sockets are initialized
695 [ # # ]: 0 : osl::Guard< osl::Mutex > theGlobalGuard( aGlobalNeonMutex );
696 [ # # ]: 0 : if ( !m_bGlobalsInited )
697 : : {
698 [ # # ][ # # ]: 0 : if ( ne_sock_init() != 0 )
699 : : throw DAVException( DAVException::DAV_SESSION_CREATE,
700 : : NeonUri::makeConnectionEndPointString(
701 [ # # ]: 0 : m_aHostName, m_nPort ) );
702 : :
703 : : // #122205# - libxml2 needs to be initialized once if used by
704 : : // multithreaded programs like OOo.
705 [ # # ]: 0 : xmlInitParser();
706 : : #if 0
707 : : // for more debug flags see ne_utils.h; NE_DEBUGGING must be defined
708 : : // while compiling neon in order to actually activate neon debug
709 : : // output.
710 : : ne_debug_init( stderr, NE_DBG_FLUSH
711 : : | NE_DBG_HTTP
712 : : // | NE_DBG_HTTPBODY
713 : : // | NE_DBG_HTTPAUTH
714 : : // | NE_DBG_XML
715 : : // | NE_DBG_XMLPARSE
716 : : // | NE_DBG_LOCKS
717 : : );
718 : : #endif
719 : 0 : m_bGlobalsInited = true;
720 : : }
721 : :
722 [ # # ]: 0 : const ucbhelper::InternetProxyServer & rProxyCfg = getProxySettings();
723 : :
724 : 0 : m_aProxyName = rProxyCfg.aName;
725 : 0 : m_nProxyPort = rProxyCfg.nPort;
726 : :
727 : : // Not yet initialized. Create new session.
728 [ # # ]: 0 : bCreateNewSession = true;
729 : : }
730 : : else
731 : : {
732 : : // #112271# Check whether proxy settings are still valid (They may
733 : : // change at any time). If not, create new Neon session.
734 : :
735 [ # # ]: 0 : const ucbhelper::InternetProxyServer & rProxyCfg = getProxySettings();
736 : :
737 [ # # ][ # # ]: 0 : if ( ( rProxyCfg.aName != m_aProxyName )
[ # # ]
738 : : || ( rProxyCfg.nPort != m_nProxyPort ) )
739 : : {
740 : 0 : m_aProxyName = rProxyCfg.aName;
741 : 0 : m_nProxyPort = rProxyCfg.nPort;
742 : :
743 : : // new session needed, destroy old first
744 : : {
745 [ # # ]: 0 : osl::Guard< osl::Mutex > theGlobalGuard( aGlobalNeonMutex );
746 [ # # ][ # # ]: 0 : ne_session_destroy( m_pHttpSession );
747 : : }
748 : 0 : m_pHttpSession = 0;
749 : 0 : bCreateNewSession = true;
750 : : }
751 : : }
752 : :
753 [ # # ]: 0 : if ( bCreateNewSession )
754 : : {
755 : : // @@@ For FTP over HTTP proxy inUserInfo is needed to be able to
756 : : // build the complete request URI (including user:pass), but
757 : : // currently (0.22.0) neon does not allow to pass the user info
758 : : // to the session
759 : :
760 : : {
761 [ # # ]: 0 : osl::Guard< osl::Mutex > theGlobalGuard( aGlobalNeonMutex );
762 : : m_pHttpSession = ne_session_create(
763 : : rtl::OUStringToOString( m_aScheme, RTL_TEXTENCODING_UTF8 ).getStr(),
764 : : /* theUri.GetUserInfo(),
765 : : @@@ for FTP via HTTP proxy, but not supported by Neon */
766 : : rtl::OUStringToOString( m_aHostName, RTL_TEXTENCODING_UTF8 ).getStr(),
767 [ # # ][ # # ]: 0 : m_nPort );
[ # # ][ # # ]
768 : : }
769 : :
770 [ # # ]: 0 : if ( m_pHttpSession == 0 )
771 : : throw DAVException( DAVException::DAV_SESSION_CREATE,
772 : : NeonUri::makeConnectionEndPointString(
773 [ # # ]: 0 : m_aHostName, m_nPort ) );
774 : :
775 : : // Register the session with the lock store
776 [ # # ]: 0 : m_aNeonLockStore.registerSession( m_pHttpSession );
777 : :
778 [ # # ]: 0 : if ( m_aScheme.equalsIgnoreAsciiCase(
779 : 0 : rtl::OUString( "https" ) ) )
780 : : {
781 : : // Set a failure callback for certificate check
782 : : ne_ssl_set_verify(
783 [ # # ]: 0 : m_pHttpSession, NeonSession_CertificationNotify, this);
784 : : }
785 : :
786 : : // Add hooks (i.e. for adding additional headers to the request)
787 : :
788 : : #if 0
789 : : /* Hook called when a request is created. */
790 : : //typedef void (*ne_create_request_fn)(ne_request *req, void *userdata,
791 : : // const char *method, const char *path);
792 : :
793 : : ne_hook_create_request( m_pHttpSession, create_req_hook_fn, this );
794 : : #endif
795 : :
796 : : /* Hook called before the request is sent. 'header' is the raw HTTP
797 : : * header before the trailing CRLF is added: add in more here. */
798 : : //typedef void (*ne_pre_send_fn)(ne_request *req, void *userdata,
799 : : // ne_buffer *header);
800 : :
801 [ # # ]: 0 : ne_hook_pre_send( m_pHttpSession, NeonSession_PreSendRequest, this );
802 : : #if 0
803 : : /* Hook called after the request is sent. May return:
804 : : * NE_OK everything is okay
805 : : * NE_RETRY try sending the request again.
806 : : * anything else signifies an error, and the request is failed. The
807 : : * return code is passed back the _dispatch caller, so the session error
808 : : * must also be set appropriately (ne_set_error).
809 : : */
810 : : //typedef int (*ne_post_send_fn)(ne_request *req, void *userdata,
811 : : // const ne_status *status);
812 : :
813 : : ne_hook_post_send( m_pHttpSession, post_send_req_hook_fn, this );
814 : :
815 : : /* Hook called when the request is destroyed. */
816 : : //typedef void (*ne_destroy_req_fn)(ne_request *req, void *userdata);
817 : :
818 : : ne_hook_destroy_request( m_pHttpSession, destroy_req_hook_fn, this );
819 : :
820 : : /* Hook called when the session is destroyed. */
821 : : //typedef void (*ne_destroy_sess_fn)(void *userdata);
822 : :
823 : : ne_hook_destroy_session( m_pHttpSession, destroy_sess_hook_fn, this );
824 : : #endif
825 : :
826 [ # # ]: 0 : if ( !m_aProxyName.isEmpty() )
827 : : {
828 : : ne_session_proxy( m_pHttpSession,
829 : : rtl::OUStringToOString(
830 : : m_aProxyName,
831 : : RTL_TEXTENCODING_UTF8 ).getStr(),
832 [ # # ][ # # ]: 0 : m_nProxyPort );
833 : : }
834 : :
835 : : // avoid KeepAlive?
836 [ # # ][ # # ]: 0 : if ( noKeepAlive(m_aFlags) )
837 [ # # ]: 0 : ne_set_session_flag( m_pHttpSession, NE_SESSFLAG_PERSIST, 0 );
838 : :
839 : : // Register for redirects.
840 [ # # ]: 0 : ne_redirect_register( m_pHttpSession );
841 : :
842 : : // authentication callbacks.
843 : : #if NEON_VERSION >= 0x0260
844 [ # # ]: 0 : ne_add_server_auth( m_pHttpSession, NE_AUTH_ALL, NeonSession_NeonAuth, this );
845 [ # # ]: 0 : ne_add_proxy_auth ( m_pHttpSession, NE_AUTH_ALL, NeonSession_NeonAuth, this );
846 : : #else
847 : : ne_set_server_auth( m_pHttpSession, NeonSession_NeonAuth, this );
848 : : ne_set_proxy_auth ( m_pHttpSession, NeonSession_NeonAuth, this );
849 : : #endif
850 [ # # ]: 0 : }
851 : 0 : }
852 : :
853 : : // -------------------------------------------------------------------
854 : : // virtual
855 : 0 : sal_Bool NeonSession::CanUse( const rtl::OUString & inUri,
856 : : const uno::Sequence< beans::NamedValue >& rFlags )
857 : : {
858 : : try
859 : : {
860 [ # # ]: 0 : NeonUri theUri( inUri );
861 [ # # # # : 0 : if ( ( theUri.GetPort() == m_nPort ) &&
# # ][ # # ]
[ # # ]
862 : 0 : ( theUri.GetHost() == m_aHostName ) &&
863 : 0 : ( theUri.GetScheme() == m_aScheme ) &&
864 [ # # ]: 0 : ( rFlags == m_aFlags ) )
865 [ # # ]: 0 : return sal_True;
[ # # # # ]
866 : : }
867 : 0 : catch ( DAVException const & )
868 : : {
869 : 0 : return sal_False;
870 : : }
871 : 0 : return sal_False;
872 : : }
873 : :
874 : : // -------------------------------------------------------------------
875 : : // virtual
876 : 0 : sal_Bool NeonSession::UsesProxy()
877 : : {
878 : 0 : Init();
879 : 0 : return !m_aProxyName.isEmpty() ;
880 : : }
881 : :
882 : : // -------------------------------------------------------------------
883 : : // OPTIONS
884 : : // -------------------------------------------------------------------
885 : 0 : void NeonSession::OPTIONS( const rtl::OUString & inPath,
886 : : DAVCapabilities & outCapabilities,
887 : : const DAVRequestEnvironment & rEnv )
888 : : throw( DAVException )
889 : : {
890 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
891 : :
892 [ # # ]: 0 : Init( rEnv );
893 : :
894 : : HttpServerCapabilities servercaps;
895 : 0 : memset( &servercaps, 0, sizeof( servercaps ) );
896 : :
897 : : int theRetVal = ne_options( m_pHttpSession,
898 : : rtl::OUStringToOString(
899 : : inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
900 [ # # ][ # # ]: 0 : &servercaps );
901 : :
902 [ # # ]: 0 : HandleError( theRetVal, inPath, rEnv );
903 : :
904 : 0 : outCapabilities.class1 = !!servercaps.dav_class1;
905 : 0 : outCapabilities.class2 = !!servercaps.dav_class2;
906 [ # # ]: 0 : outCapabilities.executable = !!servercaps.dav_executable;
907 : 0 : }
908 : :
909 : : // -------------------------------------------------------------------
910 : : // PROPFIND - allprop & named
911 : : // -------------------------------------------------------------------
912 : 0 : void NeonSession::PROPFIND( const rtl::OUString & inPath,
913 : : const Depth inDepth,
914 : : const std::vector< rtl::OUString > & inPropNames,
915 : : std::vector< DAVResource > & ioResources,
916 : : const DAVRequestEnvironment & rEnv )
917 : : throw ( DAVException )
918 : : {
919 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
920 : :
921 [ # # ]: 0 : Init( rEnv );
922 : :
923 : 0 : int theRetVal = NE_OK;
924 : : NeonPropFindRequest theRequest( m_pHttpSession,
925 : : rtl::OUStringToOString(
926 : : inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
927 : : inDepth,
928 : : inPropNames,
929 : : ioResources,
930 [ # # ][ # # ]: 0 : theRetVal );
931 : :
932 [ # # ][ # # ]: 0 : HandleError( theRetVal, inPath, rEnv );
[ # # ]
933 : 0 : }
934 : :
935 : : // -------------------------------------------------------------------
936 : : // PROPFIND - propnames
937 : : // -------------------------------------------------------------------
938 : 0 : void NeonSession::PROPFIND( const rtl::OUString & inPath,
939 : : const Depth inDepth,
940 : : std::vector< DAVResourceInfo > & ioResInfo,
941 : : const DAVRequestEnvironment & rEnv )
942 : : throw( DAVException )
943 : : {
944 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
945 : :
946 [ # # ]: 0 : Init( rEnv );
947 : :
948 : 0 : int theRetVal = NE_OK;
949 : : NeonPropFindRequest theRequest( m_pHttpSession,
950 : : rtl::OUStringToOString(
951 : : inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
952 : : inDepth,
953 : : ioResInfo,
954 [ # # ][ # # ]: 0 : theRetVal );
955 : :
956 [ # # ][ # # ]: 0 : HandleError( theRetVal, inPath, rEnv );
[ # # ]
957 : 0 : }
958 : :
959 : : // -------------------------------------------------------------------
960 : : // PROPPATCH
961 : : // -------------------------------------------------------------------
962 : 0 : void NeonSession::PROPPATCH( const rtl::OUString & inPath,
963 : : const std::vector< ProppatchValue > & inValues,
964 : : const DAVRequestEnvironment & rEnv )
965 : : throw( DAVException )
966 : : {
967 : : /* @@@ Which standard live properties can be set by the client?
968 : : This is a known WebDAV RFC issue ( verified: 04/10/2001 )
969 : : --> http://www.ics.uci.edu/pub/ietf/webdav/protocol/issues.html
970 : :
971 : : mod_dav implementation:
972 : :
973 : : creationdate r ( File System prop )
974 : : displayname w
975 : : getcontentlanguage r ( #ifdef DAV_DISABLE_WRITEABLE_PROPS )
976 : : getcontentlength r ( File System prop )
977 : : getcontenttype r ( #ifdef DAV_DISABLE_WRITEABLE_PROPS )
978 : : getetag r ( File System prop )
979 : : getlastmodified r ( File System prop )
980 : : lockdiscovery r
981 : : resourcetype r
982 : : source w
983 : : supportedlock r
984 : : executable w ( #ifndef WIN32 )
985 : :
986 : : All dead properties are of course writable.
987 : : */
988 : :
989 : 0 : int theRetVal = NE_OK;
990 : :
991 : : int n; // for the "for" loop
992 : :
993 : : // Generate the list of properties we want to set.
994 : 0 : int nPropCount = inValues.size();
995 : : ne_proppatch_operation* pItems
996 : 0 : = new ne_proppatch_operation[ nPropCount + 1 ];
997 [ # # ]: 0 : for ( n = 0; n < nPropCount; ++n )
998 : : {
999 : 0 : const ProppatchValue & rValue = inValues[ n ];
1000 : :
1001 : : // Split fullname into namespace and name!
1002 : 0 : ne_propname * pName = new ne_propname;
1003 : 0 : DAVProperties::createNeonPropName( rValue.name, *pName );
1004 : 0 : pItems[ n ].name = pName;
1005 : :
1006 [ # # ]: 0 : if ( rValue.operation == PROPSET )
1007 : : {
1008 : 0 : pItems[ n ].type = ne_propset;
1009 : :
1010 : 0 : rtl::OUString aStringValue;
1011 [ # # ][ # # ]: 0 : if ( DAVProperties::isUCBDeadProperty( *pName ) )
1012 : : {
1013 : : // DAV dead property added by WebDAV UCP?
1014 [ # # ]: 0 : if ( !UCBDeadPropertyValue::toXML( rValue.value,
1015 [ # # ]: 0 : aStringValue ) )
1016 : : {
1017 : : // Error!
1018 : 0 : pItems[ n ].value = 0;
1019 : 0 : theRetVal = NE_ERROR;
1020 : 0 : nPropCount = n + 1;
1021 : : break;
1022 : : }
1023 : : }
1024 [ # # ]: 0 : else if ( !( rValue.value >>= aStringValue ) )
1025 : : {
1026 : : // complex properties...
1027 [ # # ]: 0 : if ( rValue.name == DAVProperties::SOURCE )
1028 : : {
1029 [ # # ]: 0 : uno::Sequence< ucb::Link > aLinks;
1030 [ # # ][ # # ]: 0 : if ( rValue.value >>= aLinks )
1031 : : {
1032 [ # # ]: 0 : LinkSequence::toXML( aLinks, aStringValue );
1033 : : }
1034 : : else
1035 : : {
1036 : : // Error!
1037 : 0 : pItems[ n ].value = 0;
1038 : 0 : theRetVal = NE_ERROR;
1039 : 0 : nPropCount = n + 1;
1040 : : break;
1041 [ # # ][ # # ]: 0 : }
1042 : : }
1043 : : else
1044 : : {
1045 : : OSL_FAIL( "NeonSession::PROPPATCH - unsupported type!" );
1046 : : // Error!
1047 : 0 : pItems[ n ].value = 0;
1048 : 0 : theRetVal = NE_ERROR;
1049 : 0 : nPropCount = n + 1;
1050 : : break;
1051 : : }
1052 : : }
1053 : 0 : pItems[ n ].value
1054 : : = strdup( rtl::OUStringToOString( aStringValue,
1055 [ # # ][ # # ]: 0 : RTL_TEXTENCODING_UTF8 ).getStr() );
1056 : : }
1057 : : else
1058 : : {
1059 : 0 : pItems[ n ].type = ne_propremove;
1060 : 0 : pItems[ n ].value = 0;
1061 : : }
1062 : : }
1063 : :
1064 [ # # ]: 0 : if ( theRetVal == NE_OK )
1065 : : {
1066 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
1067 : :
1068 [ # # ]: 0 : Init( rEnv );
1069 : :
1070 : 0 : pItems[ n ].name = 0;
1071 : :
1072 : : theRetVal = ne_proppatch( m_pHttpSession,
1073 : : rtl::OUStringToOString(
1074 : : inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1075 [ # # ][ # # ]: 0 : pItems );
[ # # ]
1076 : : }
1077 : :
1078 [ # # ]: 0 : for ( n = 0; n < nPropCount; ++n )
1079 : : {
1080 : 0 : free( (void *)pItems[ n ].name->name );
1081 : 0 : delete pItems[ n ].name;
1082 : 0 : free( (void *)pItems[ n ].value );
1083 : : }
1084 : :
1085 [ # # ]: 0 : delete [] pItems;
1086 : :
1087 : 0 : HandleError( theRetVal, inPath, rEnv );
1088 : 0 : }
1089 : :
1090 : : // -------------------------------------------------------------------
1091 : : // HEAD
1092 : : // -------------------------------------------------------------------
1093 : 0 : void NeonSession::HEAD( const ::rtl::OUString & inPath,
1094 : : const std::vector< ::rtl::OUString > & inHeaderNames,
1095 : : DAVResource & ioResource,
1096 : : const DAVRequestEnvironment & rEnv )
1097 : : throw( DAVException )
1098 : : {
1099 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
1100 : :
1101 [ # # ]: 0 : Init( rEnv );
1102 : :
1103 : 0 : int theRetVal = NE_OK;
1104 : : NeonHeadRequest theRequest( m_pHttpSession,
1105 : : inPath,
1106 : : inHeaderNames,
1107 : : ioResource,
1108 [ # # ]: 0 : theRetVal );
1109 : :
1110 [ # # ][ # # ]: 0 : HandleError( theRetVal, inPath, rEnv );
[ # # ]
1111 : 0 : }
1112 : :
1113 : : // -------------------------------------------------------------------
1114 : : // GET
1115 : : // -------------------------------------------------------------------
1116 : : uno::Reference< io::XInputStream >
1117 : 0 : NeonSession::GET( const rtl::OUString & inPath,
1118 : : const DAVRequestEnvironment & rEnv )
1119 : : throw ( DAVException )
1120 : : {
1121 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
1122 : :
1123 [ # # ]: 0 : Init( rEnv );
1124 : :
1125 [ # # ]: 0 : rtl::Reference< NeonInputStream > xInputStream( new NeonInputStream );
1126 [ # # ]: 0 : NeonRequestContext aCtx( xInputStream );
1127 : : int theRetVal = GET( m_pHttpSession,
1128 : : rtl::OUStringToOString(
1129 : : inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1130 : : NeonSession_ResponseBlockReader,
1131 : : false,
1132 [ # # ][ # # ]: 0 : &aCtx );
1133 : :
1134 [ # # ]: 0 : HandleError( theRetVal, inPath, rEnv );
1135 : :
1136 [ # # ][ # # ]: 0 : return uno::Reference< io::XInputStream >( xInputStream.get() );
[ # # ]
1137 : : }
1138 : :
1139 : : // -------------------------------------------------------------------
1140 : : // GET
1141 : : // -------------------------------------------------------------------
1142 : 0 : void NeonSession::GET( const rtl::OUString & inPath,
1143 : : uno::Reference< io::XOutputStream > & ioOutputStream,
1144 : : const DAVRequestEnvironment & rEnv )
1145 : : throw ( DAVException )
1146 : : {
1147 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
1148 : :
1149 [ # # ]: 0 : Init( rEnv );
1150 : :
1151 [ # # ]: 0 : NeonRequestContext aCtx( ioOutputStream );
1152 : : int theRetVal = GET( m_pHttpSession,
1153 : : rtl::OUStringToOString(
1154 : : inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1155 : : NeonSession_ResponseBlockWriter,
1156 : : false,
1157 [ # # ][ # # ]: 0 : &aCtx );
1158 : :
1159 [ # # ][ # # ]: 0 : HandleError( theRetVal, inPath, rEnv );
[ # # ]
1160 : 0 : }
1161 : :
1162 : : // -------------------------------------------------------------------
1163 : : // GET
1164 : : // -------------------------------------------------------------------
1165 : : uno::Reference< io::XInputStream >
1166 : 0 : NeonSession::GET( const rtl::OUString & inPath,
1167 : : const std::vector< ::rtl::OUString > & inHeaderNames,
1168 : : DAVResource & ioResource,
1169 : : const DAVRequestEnvironment & rEnv )
1170 : : throw ( DAVException )
1171 : : {
1172 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
1173 : :
1174 [ # # ]: 0 : Init( rEnv );
1175 : :
1176 : 0 : ioResource.uri = inPath;
1177 : 0 : ioResource.properties.clear();
1178 : :
1179 [ # # ]: 0 : rtl::Reference< NeonInputStream > xInputStream( new NeonInputStream );
1180 [ # # ]: 0 : NeonRequestContext aCtx( xInputStream, inHeaderNames, ioResource );
1181 : : int theRetVal = GET( m_pHttpSession,
1182 : : rtl::OUStringToOString(
1183 : : inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1184 : : NeonSession_ResponseBlockReader,
1185 : : true,
1186 [ # # ][ # # ]: 0 : &aCtx );
1187 : :
1188 [ # # ]: 0 : HandleError( theRetVal, inPath, rEnv );
1189 : :
1190 [ # # ][ # # ]: 0 : return uno::Reference< io::XInputStream >( xInputStream.get() );
[ # # ]
1191 : : }
1192 : :
1193 : : // -------------------------------------------------------------------
1194 : : // GET
1195 : : // -------------------------------------------------------------------
1196 : 0 : void NeonSession::GET( const rtl::OUString & inPath,
1197 : : uno::Reference< io::XOutputStream > & ioOutputStream,
1198 : : const std::vector< ::rtl::OUString > & inHeaderNames,
1199 : : DAVResource & ioResource,
1200 : : const DAVRequestEnvironment & rEnv )
1201 : : throw ( DAVException )
1202 : : {
1203 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
1204 : :
1205 [ # # ]: 0 : Init( rEnv );
1206 : :
1207 : 0 : ioResource.uri = inPath;
1208 : 0 : ioResource.properties.clear();
1209 : :
1210 [ # # ]: 0 : NeonRequestContext aCtx( ioOutputStream, inHeaderNames, ioResource );
1211 : : int theRetVal = GET( m_pHttpSession,
1212 : : rtl::OUStringToOString(
1213 : : inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1214 : : NeonSession_ResponseBlockWriter,
1215 : : true,
1216 [ # # ][ # # ]: 0 : &aCtx );
1217 : :
1218 [ # # ][ # # ]: 0 : HandleError( theRetVal, inPath, rEnv );
[ # # ]
1219 : 0 : }
1220 : :
1221 : : // -------------------------------------------------------------------
1222 : : // PUT
1223 : : // -------------------------------------------------------------------
1224 : 0 : void NeonSession::PUT( const rtl::OUString & inPath,
1225 : : const uno::Reference< io::XInputStream > & inInputStream,
1226 : : const DAVRequestEnvironment & rEnv )
1227 : : throw ( DAVException )
1228 : : {
1229 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
1230 : :
1231 [ # # ]: 0 : uno::Sequence< sal_Int8 > aDataToSend;
1232 [ # # ][ # # ]: 0 : if ( !getDataFromInputStream( inInputStream, aDataToSend, false ) )
1233 : 0 : throw DAVException( DAVException::DAV_INVALID_ARG );
1234 : :
1235 [ # # ]: 0 : Init( rEnv );
1236 : :
1237 : : int theRetVal = PUT( m_pHttpSession,
1238 : : rtl::OUStringToOString(
1239 : : inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1240 : : reinterpret_cast< const char * >(
1241 : 0 : aDataToSend.getConstArray() ),
1242 [ # # ][ # # ]: 0 : aDataToSend.getLength() );
1243 : :
1244 [ # # ][ # # ]: 0 : HandleError( theRetVal, inPath, rEnv );
[ # # ]
1245 : 0 : }
1246 : :
1247 : : // -------------------------------------------------------------------
1248 : : // POST
1249 : : // -------------------------------------------------------------------
1250 : : uno::Reference< io::XInputStream >
1251 : 0 : NeonSession::POST( const rtl::OUString & inPath,
1252 : : const rtl::OUString & rContentType,
1253 : : const rtl::OUString & rReferer,
1254 : : const uno::Reference< io::XInputStream > & inInputStream,
1255 : : const DAVRequestEnvironment & rEnv )
1256 : : throw ( DAVException )
1257 : : {
1258 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
1259 : :
1260 [ # # ]: 0 : uno::Sequence< sal_Int8 > aDataToSend;
1261 [ # # ][ # # ]: 0 : if ( !getDataFromInputStream( inInputStream, aDataToSend, true ) )
1262 : 0 : throw DAVException( DAVException::DAV_INVALID_ARG );
1263 : :
1264 [ # # ]: 0 : Init( rEnv );
1265 : :
1266 [ # # ]: 0 : rtl::Reference< NeonInputStream > xInputStream( new NeonInputStream );
1267 [ # # ]: 0 : NeonRequestContext aCtx( xInputStream );
1268 : : int theRetVal = POST( m_pHttpSession,
1269 : : rtl::OUStringToOString(
1270 : : inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1271 : : reinterpret_cast< const char * >(
1272 : 0 : aDataToSend.getConstArray() ),
1273 : : NeonSession_ResponseBlockReader,
1274 : : &aCtx,
1275 : : rContentType,
1276 [ # # ][ # # ]: 0 : rReferer );
1277 : :
1278 [ # # ]: 0 : HandleError( theRetVal, inPath, rEnv );
1279 : :
1280 [ # # ][ # # ]: 0 : return uno::Reference< io::XInputStream >( xInputStream.get() );
[ # # ][ # # ]
1281 : : }
1282 : :
1283 : : // -------------------------------------------------------------------
1284 : : // POST
1285 : : // -------------------------------------------------------------------
1286 : 0 : void NeonSession::POST( const rtl::OUString & inPath,
1287 : : const rtl::OUString & rContentType,
1288 : : const rtl::OUString & rReferer,
1289 : : const uno::Reference< io::XInputStream > & inInputStream,
1290 : : uno::Reference< io::XOutputStream > & oOutputStream,
1291 : : const DAVRequestEnvironment & rEnv )
1292 : : throw ( DAVException )
1293 : : {
1294 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
1295 : :
1296 [ # # ]: 0 : uno::Sequence< sal_Int8 > aDataToSend;
1297 [ # # ][ # # ]: 0 : if ( !getDataFromInputStream( inInputStream, aDataToSend, true ) )
1298 : 0 : throw DAVException( DAVException::DAV_INVALID_ARG );
1299 : :
1300 [ # # ]: 0 : Init( rEnv );
1301 : :
1302 [ # # ]: 0 : NeonRequestContext aCtx( oOutputStream );
1303 : : int theRetVal = POST( m_pHttpSession,
1304 : : rtl::OUStringToOString(
1305 : : inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1306 : : reinterpret_cast< const char * >(
1307 : 0 : aDataToSend.getConstArray() ),
1308 : : NeonSession_ResponseBlockWriter,
1309 : : &aCtx,
1310 : : rContentType,
1311 [ # # ][ # # ]: 0 : rReferer );
1312 : :
1313 [ # # ][ # # ]: 0 : HandleError( theRetVal, inPath, rEnv );
[ # # ][ # # ]
1314 : 0 : }
1315 : :
1316 : : // -------------------------------------------------------------------
1317 : : // MKCOL
1318 : : // -------------------------------------------------------------------
1319 : 0 : void NeonSession::MKCOL( const rtl::OUString & inPath,
1320 : : const DAVRequestEnvironment & rEnv )
1321 : : throw ( DAVException )
1322 : : {
1323 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
1324 : :
1325 [ # # ]: 0 : Init( rEnv );
1326 : :
1327 : : int theRetVal = ne_mkcol( m_pHttpSession,
1328 : : rtl::OUStringToOString(
1329 [ # # ][ # # ]: 0 : inPath, RTL_TEXTENCODING_UTF8 ).getStr() );
1330 : :
1331 [ # # ][ # # ]: 0 : HandleError( theRetVal, inPath, rEnv );
1332 : 0 : }
1333 : :
1334 : : // -------------------------------------------------------------------
1335 : : // COPY
1336 : : // -------------------------------------------------------------------
1337 : 0 : void NeonSession::COPY( const rtl::OUString & inSourceURL,
1338 : : const rtl::OUString & inDestinationURL,
1339 : : const DAVRequestEnvironment & rEnv,
1340 : : sal_Bool inOverWrite )
1341 : : throw ( DAVException )
1342 : : {
1343 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
1344 : :
1345 [ # # ]: 0 : Init( rEnv );
1346 : :
1347 [ # # ]: 0 : NeonUri theSourceUri( inSourceURL );
1348 [ # # ]: 0 : NeonUri theDestinationUri( inDestinationURL );
1349 : :
1350 : : int theRetVal = ne_copy( m_pHttpSession,
1351 : : inOverWrite ? 1 : 0,
1352 : : NE_DEPTH_INFINITE,
1353 : : rtl::OUStringToOString(
1354 : 0 : theSourceUri.GetPath(),
1355 : : RTL_TEXTENCODING_UTF8 ).getStr(),
1356 : : rtl::OUStringToOString(
1357 : 0 : theDestinationUri.GetPath(),
1358 [ # # ][ # # ]: 0 : RTL_TEXTENCODING_UTF8 ).getStr() );
[ # # ][ # # ]
1359 : :
1360 [ # # ][ # # ]: 0 : HandleError( theRetVal, inSourceURL, rEnv );
[ # # ][ # # ]
1361 : 0 : }
1362 : :
1363 : : // -------------------------------------------------------------------
1364 : : // MOVE
1365 : : // -------------------------------------------------------------------
1366 : 0 : void NeonSession::MOVE( const rtl::OUString & inSourceURL,
1367 : : const rtl::OUString & inDestinationURL,
1368 : : const DAVRequestEnvironment & rEnv,
1369 : : sal_Bool inOverWrite )
1370 : : throw ( DAVException )
1371 : : {
1372 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
1373 : :
1374 [ # # ]: 0 : Init( rEnv );
1375 : :
1376 [ # # ]: 0 : NeonUri theSourceUri( inSourceURL );
1377 [ # # ]: 0 : NeonUri theDestinationUri( inDestinationURL );
1378 : : int theRetVal = ne_move( m_pHttpSession,
1379 : : inOverWrite ? 1 : 0,
1380 : : rtl::OUStringToOString(
1381 : 0 : theSourceUri.GetPath(),
1382 : : RTL_TEXTENCODING_UTF8 ).getStr(),
1383 : : rtl::OUStringToOString(
1384 : 0 : theDestinationUri.GetPath(),
1385 [ # # ][ # # ]: 0 : RTL_TEXTENCODING_UTF8 ).getStr() );
[ # # ][ # # ]
1386 : :
1387 [ # # ][ # # ]: 0 : HandleError( theRetVal, inSourceURL, rEnv );
[ # # ][ # # ]
1388 : 0 : }
1389 : :
1390 : : // -------------------------------------------------------------------
1391 : : // DESTROY
1392 : : // -------------------------------------------------------------------
1393 : 0 : void NeonSession::DESTROY( const rtl::OUString & inPath,
1394 : : const DAVRequestEnvironment & rEnv )
1395 : : throw ( DAVException )
1396 : : {
1397 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
1398 : :
1399 [ # # ]: 0 : Init( rEnv );
1400 : :
1401 : : int theRetVal = ne_delete( m_pHttpSession,
1402 : : rtl::OUStringToOString(
1403 [ # # ][ # # ]: 0 : inPath, RTL_TEXTENCODING_UTF8 ).getStr() );
1404 : :
1405 [ # # ][ # # ]: 0 : HandleError( theRetVal, inPath, rEnv );
1406 : 0 : }
1407 : :
1408 : : // -------------------------------------------------------------------
1409 : : namespace
1410 : : {
1411 : 0 : sal_Int32 lastChanceToSendRefreshRequest( TimeValue const & rStart,
1412 : : int timeout )
1413 : : {
1414 : : TimeValue aEnd;
1415 [ # # ]: 0 : osl_getSystemTime( &aEnd );
1416 : :
1417 : : // Try to estimate a safe absolute time for sending the
1418 : : // lock refresh request.
1419 : 0 : sal_Int32 lastChanceToSendRefreshRequest = -1;
1420 [ # # ]: 0 : if ( timeout != NE_TIMEOUT_INFINITE )
1421 : : {
1422 : 0 : sal_Int32 calltime = aEnd.Seconds - rStart.Seconds;
1423 [ # # ]: 0 : if ( calltime <= timeout )
1424 : : {
1425 : : lastChanceToSendRefreshRequest
1426 : 0 : = aEnd.Seconds + timeout - calltime;
1427 : : }
1428 : : else
1429 : : {
1430 : : OSL_TRACE( "No chance to refresh lock before timeout!" );
1431 : : }
1432 : : }
1433 : 0 : return lastChanceToSendRefreshRequest;
1434 : : }
1435 : :
1436 : : } // namespace
1437 : :
1438 : : // -------------------------------------------------------------------
1439 : : // LOCK (set new lock)
1440 : : // -------------------------------------------------------------------
1441 : 0 : void NeonSession::LOCK( const ::rtl::OUString & inPath,
1442 : : ucb::Lock & rLock,
1443 : : const DAVRequestEnvironment & rEnv )
1444 : : throw ( DAVException )
1445 : : {
1446 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
1447 : :
1448 [ # # ]: 0 : Init( rEnv );
1449 : :
1450 : : /* Create a depth zero, exclusive write lock, with default timeout
1451 : : * (allowing a server to pick a default). token, owner and uri are
1452 : : * unset. */
1453 [ # # ]: 0 : NeonLock * theLock = ne_lock_create();
1454 : :
1455 : : // Set the lock uri
1456 : : ne_uri aUri;
1457 : : ne_uri_parse( rtl::OUStringToOString( makeAbsoluteURL( inPath ),
1458 : : RTL_TEXTENCODING_UTF8 ).getStr(),
1459 [ # # ][ # # ]: 0 : &aUri );
[ # # ]
1460 : 0 : theLock->uri = aUri;
1461 : :
1462 : : // Set the lock depth
1463 [ # # # # ]: 0 : switch( rLock.Depth )
1464 : : {
1465 : : case ucb::LockDepth_ZERO:
1466 : 0 : theLock->depth = NE_DEPTH_ZERO;
1467 : 0 : break;
1468 : : case ucb::LockDepth_ONE:
1469 : 0 : theLock->depth = NE_DEPTH_ONE;
1470 : 0 : break;
1471 : : case ucb::LockDepth_INFINITY:
1472 : 0 : theLock->depth = NE_DEPTH_INFINITE;
1473 : 0 : break;
1474 : : default:
1475 : 0 : throw DAVException( DAVException::DAV_INVALID_ARG );
1476 : : }
1477 : :
1478 : : // Set the lock scope
1479 [ # # # ]: 0 : switch ( rLock.Scope )
1480 : : {
1481 : : case ucb::LockScope_EXCLUSIVE:
1482 : 0 : theLock->scope = ne_lockscope_exclusive;
1483 : 0 : break;
1484 : : case ucb::LockScope_SHARED:
1485 : 0 : theLock->scope = ne_lockscope_shared;
1486 : 0 : break;
1487 : : default:
1488 : 0 : throw DAVException( DAVException::DAV_INVALID_ARG );
1489 : : }
1490 : :
1491 : : // Set the lock timeout
1492 : 0 : theLock->timeout = (long)rLock.Timeout;
1493 : :
1494 : : // Set the lock owner
1495 : 0 : rtl::OUString aValue;
1496 : 0 : rLock.Owner >>= aValue;
1497 : : theLock->owner =
1498 : : ne_strdup( rtl::OUStringToOString( aValue,
1499 [ # # ][ # # ]: 0 : RTL_TEXTENCODING_UTF8 ).getStr() );
1500 : : TimeValue startCall;
1501 [ # # ]: 0 : osl_getSystemTime( &startCall );
1502 : :
1503 [ # # ]: 0 : int theRetVal = ne_lock( m_pHttpSession, theLock );
1504 : :
1505 [ # # ]: 0 : if ( theRetVal == NE_OK )
1506 : : {
1507 : : m_aNeonLockStore.addLock( theLock,
1508 : : this,
1509 : : lastChanceToSendRefreshRequest(
1510 [ # # ][ # # ]: 0 : startCall, theLock->timeout ) );
[ # # ][ # # ]
1511 : :
1512 [ # # ]: 0 : uno::Sequence< rtl::OUString > aTokens( 1 );
1513 [ # # ]: 0 : aTokens[ 0 ] = rtl::OUString::createFromAscii( theLock->token );
1514 [ # # ]: 0 : rLock.LockTokens = aTokens;
1515 : :
1516 : : OSL_TRACE( "NeonSession::LOCK: created lock for %s. token: %s",
1517 : : rtl::OUStringToOString( makeAbsoluteURL( inPath ),
1518 : : RTL_TEXTENCODING_UTF8 ).getStr(),
1519 [ # # ]: 0 : theLock->token );
1520 : : }
1521 : : else
1522 : : {
1523 [ # # ]: 0 : ne_lock_destroy( theLock );
1524 : :
1525 : : OSL_TRACE( "NeonSession::LOCK: obtaining lock for %s failed!",
1526 : : rtl::OUStringToOString( makeAbsoluteURL( inPath ),
1527 : : RTL_TEXTENCODING_UTF8 ).getStr() );
1528 : : }
1529 : :
1530 [ # # ][ # # ]: 0 : HandleError( theRetVal, inPath, rEnv );
1531 : 0 : }
1532 : :
1533 : : // -------------------------------------------------------------------
1534 : : // LOCK (refresh existing lock)
1535 : : // -------------------------------------------------------------------
1536 : 0 : sal_Int64 NeonSession::LOCK( const ::rtl::OUString & inPath,
1537 : : sal_Int64 nTimeout,
1538 : : const DAVRequestEnvironment & rEnv )
1539 : : throw ( DAVException )
1540 : : {
1541 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
1542 : :
1543 : : // Try to get the neon lock from lock store
1544 : : NeonLock * theLock
1545 [ # # ][ # # ]: 0 : = m_aNeonLockStore.findByUri( makeAbsoluteURL( inPath ) );
1546 [ # # ]: 0 : if ( !theLock )
1547 : 0 : throw DAVException( DAVException::DAV_NOT_LOCKED );
1548 : :
1549 [ # # ]: 0 : Init( rEnv );
1550 : :
1551 : : // refresh existing lock.
1552 : 0 : theLock->timeout = static_cast< long >( nTimeout );
1553 : :
1554 : : TimeValue startCall;
1555 [ # # ]: 0 : osl_getSystemTime( &startCall );
1556 : :
1557 [ # # ]: 0 : int theRetVal = ne_lock_refresh( m_pHttpSession, theLock );
1558 : :
1559 [ # # ]: 0 : if ( theRetVal == NE_OK )
1560 : : {
1561 : : m_aNeonLockStore.updateLock( theLock,
1562 : : lastChanceToSendRefreshRequest(
1563 [ # # ][ # # ]: 0 : startCall, theLock->timeout ) );
1564 : : }
1565 : :
1566 [ # # ]: 0 : HandleError( theRetVal, inPath, rEnv );
1567 : :
1568 [ # # ]: 0 : return theLock->timeout;
1569 : : }
1570 : :
1571 : : // -------------------------------------------------------------------
1572 : : // LOCK (refresh existing lock)
1573 : : // -------------------------------------------------------------------
1574 : 0 : bool NeonSession::LOCK( NeonLock * pLock,
1575 : : sal_Int32 & rlastChanceToSendRefreshRequest )
1576 : : {
1577 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
1578 : :
1579 : : #if OSL_DEBUG_LEVEL > 0
1580 : : char * p = ne_uri_unparse( &(pLock->uri) );
1581 : : OSL_TRACE( "NeonSession::LOCK: Refreshing lock for %s.", p );
1582 : : ne_free( p );
1583 : : #endif
1584 : :
1585 : : // refresh existing lock.
1586 : :
1587 : : TimeValue startCall;
1588 [ # # ]: 0 : osl_getSystemTime( &startCall );
1589 : :
1590 [ # # ][ # # ]: 0 : if ( ne_lock_refresh( m_pHttpSession, pLock ) == NE_OK )
1591 : : {
1592 : : rlastChanceToSendRefreshRequest
1593 [ # # ]: 0 : = lastChanceToSendRefreshRequest( startCall, pLock->timeout );
1594 : :
1595 : : OSL_TRACE( "Lock successfully refreshed." );
1596 : 0 : return true;
1597 : : }
1598 : : else
1599 : : {
1600 : : OSL_TRACE( "Lock not refreshed!" );
1601 : 0 : return false;
1602 [ # # ]: 0 : }
1603 : : }
1604 : :
1605 : : // -------------------------------------------------------------------
1606 : : // UNLOCK
1607 : : // -------------------------------------------------------------------
1608 : 0 : void NeonSession::UNLOCK( const ::rtl::OUString & inPath,
1609 : : const DAVRequestEnvironment & rEnv )
1610 : : throw ( DAVException )
1611 : : {
1612 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
1613 : :
1614 : : // get the neon lock from lock store
1615 : : NeonLock * theLock
1616 [ # # ][ # # ]: 0 : = m_aNeonLockStore.findByUri( makeAbsoluteURL( inPath ) );
1617 [ # # ]: 0 : if ( !theLock )
1618 : 0 : throw DAVException( DAVException::DAV_NOT_LOCKED );
1619 : :
1620 [ # # ]: 0 : Init( rEnv );
1621 : :
1622 [ # # ]: 0 : int theRetVal = ne_unlock( m_pHttpSession, theLock );
1623 : :
1624 [ # # ]: 0 : if ( theRetVal == NE_OK )
1625 : : {
1626 [ # # ]: 0 : m_aNeonLockStore.removeLock( theLock );
1627 [ # # ]: 0 : ne_lock_destroy( theLock );
1628 : : }
1629 : : else
1630 : : {
1631 : : OSL_TRACE( "NeonSession::UNLOCK: unlocking of %s failed.",
1632 : : rtl::OUStringToOString( makeAbsoluteURL( inPath ),
1633 : : RTL_TEXTENCODING_UTF8 ).getStr() );
1634 : : }
1635 : :
1636 [ # # ][ # # ]: 0 : HandleError( theRetVal, inPath, rEnv );
1637 : 0 : }
1638 : :
1639 : : // -------------------------------------------------------------------
1640 : : // UNLOCK
1641 : : // -------------------------------------------------------------------
1642 : 0 : bool NeonSession::UNLOCK( NeonLock * pLock )
1643 : : {
1644 [ # # ]: 0 : osl::Guard< osl::Mutex > theGuard( m_aMutex );
1645 : :
1646 : : #if OSL_DEBUG_LEVEL > 0
1647 : : char * p = ne_uri_unparse( &(pLock->uri) );
1648 : : OSL_TRACE( "NeonSession::UNLOCK: Unlocking %s.", p );
1649 : : ne_free( p );
1650 : : #endif
1651 : :
1652 [ # # ][ # # ]: 0 : if ( ne_unlock( m_pHttpSession, pLock ) == NE_OK )
1653 : : {
1654 : : OSL_TRACE( "UNLOCK succeeded." );
1655 : 0 : return true;
1656 : : }
1657 : : else
1658 : : {
1659 : : OSL_TRACE( "UNLOCK failed!" );
1660 : 0 : return false;
1661 [ # # ]: 0 : }
1662 : : }
1663 : :
1664 : : // -------------------------------------------------------------------
1665 : 0 : void NeonSession::abort()
1666 : : throw ( DAVException )
1667 : : {
1668 [ # # ]: 0 : if ( m_pHttpSession )
1669 : : {
1670 [ # # ]: 0 : osl::Guard< osl::Mutex > theGlobalGuard( aGlobalNeonMutex );
1671 [ # # ][ # # ]: 0 : ne_close_connection( m_pHttpSession );
1672 : : }
1673 : 0 : }
1674 : :
1675 : : // -------------------------------------------------------------------
1676 : 0 : const ucbhelper::InternetProxyServer & NeonSession::getProxySettings() const
1677 : : {
1678 [ # # ][ # # ]: 0 : if ( m_aScheme == "http" || m_aScheme == "https" )
[ # # ]
1679 : : {
1680 : : return m_rProxyDecider.getProxy( m_aScheme,
1681 : : m_aHostName,
1682 : 0 : m_nPort );
1683 : : }
1684 : : else
1685 : : {
1686 : : return m_rProxyDecider.getProxy( m_aScheme,
1687 : : rtl::OUString() /* not used */,
1688 [ # # ]: 0 : -1 /* not used */ );
1689 : : }
1690 : : }
1691 : :
1692 : : // -------------------------------------------------------------------
1693 : : namespace {
1694 : :
1695 : 0 : bool containsLocktoken( const uno::Sequence< ucb::Lock > & rLocks,
1696 : : const char * token )
1697 : : {
1698 [ # # ]: 0 : for ( sal_Int32 n = 0; n < rLocks.getLength(); ++n )
1699 : : {
1700 : : const uno::Sequence< rtl::OUString > & rTokens
1701 : 0 : = rLocks[ n ].LockTokens;
1702 [ # # ]: 0 : for ( sal_Int32 m = 0; m < rTokens.getLength(); ++m )
1703 : : {
1704 [ # # ]: 0 : if ( rTokens[ m ].equalsAscii( token ) )
1705 : 0 : return true;
1706 : : }
1707 : : }
1708 : 0 : return false;
1709 : : }
1710 : :
1711 : : } // namespace
1712 : :
1713 : : // -------------------------------------------------------------------
1714 : 0 : bool NeonSession::removeExpiredLocktoken( const rtl::OUString & inURL,
1715 : : const DAVRequestEnvironment & rEnv )
1716 : : {
1717 : 0 : NeonLock * theLock = m_aNeonLockStore.findByUri( inURL );
1718 [ # # ]: 0 : if ( !theLock )
1719 : 0 : return false;
1720 : :
1721 : : // do a lockdiscovery to check whether this lock is still valid.
1722 : : try
1723 : : {
1724 : : // @@@ Alternative: use ne_lock_discover() => less overhead
1725 : :
1726 [ # # ]: 0 : std::vector< DAVResource > aResources;
1727 [ # # ]: 0 : std::vector< rtl::OUString > aPropNames;
1728 [ # # ]: 0 : aPropNames.push_back( DAVProperties::LOCKDISCOVERY );
1729 : :
1730 [ # # ]: 0 : PROPFIND( rEnv.m_aRequestURI, DAVZERO, aPropNames, aResources, rEnv );
1731 : :
1732 [ # # ]: 0 : if ( aResources.empty() )
1733 : 0 : return false;
1734 : :
1735 : : std::vector< DAVPropertyValue >::const_iterator it
1736 [ # # ]: 0 : = aResources[ 0 ].properties.begin();
1737 : : std::vector< DAVPropertyValue >::const_iterator end
1738 [ # # ]: 0 : = aResources[ 0 ].properties.end();
1739 : :
1740 [ # # ][ # # ]: 0 : while ( it != end )
1741 : : {
1742 [ # # ]: 0 : if ( (*it).Name.equals( DAVProperties::LOCKDISCOVERY ) )
1743 : : {
1744 [ # # ]: 0 : uno::Sequence< ucb::Lock > aLocks;
1745 [ # # ][ # # ]: 0 : if ( !( (*it).Value >>= aLocks ) )
1746 : 0 : return false;
1747 : :
1748 [ # # ][ # # ]: 0 : if ( !containsLocktoken( aLocks, theLock->token ) )
1749 : : {
1750 : : // expired!
1751 : : break;
1752 : : }
1753 : :
1754 : : // still valid.
1755 [ # # ][ # # ]: 0 : return false;
1756 : : }
1757 : 0 : ++it;
1758 : : }
1759 : :
1760 : : // No lockdiscovery prop in propfind result / locktoken not found
1761 : : // in propfind result -> not locked
1762 : : OSL_TRACE( "NeonSession::removeExpiredLocktoken: Removing "
1763 : : " expired lock token for %s. token: %s",
1764 : : rtl::OUStringToOString( inURL,
1765 : : RTL_TEXTENCODING_UTF8 ).getStr(),
1766 : : theLock->token );
1767 : :
1768 [ # # ]: 0 : m_aNeonLockStore.removeLock( theLock );
1769 [ # # ]: 0 : ne_lock_destroy( theLock );
1770 [ # # ]: 0 : return true;
1771 : : }
1772 : 0 : catch ( DAVException const & )
1773 : : {
1774 : : }
1775 : 0 : return false;
1776 : : }
1777 : :
1778 : : // -------------------------------------------------------------------
1779 : : // HandleError
1780 : : // Common Error Handler
1781 : : // -------------------------------------------------------------------
1782 : 0 : void NeonSession::HandleError( int nError,
1783 : : const rtl::OUString & inPath,
1784 : : const DAVRequestEnvironment & rEnv )
1785 : : throw ( DAVException )
1786 : : {
1787 [ # # ]: 0 : m_aEnv = DAVRequestEnvironment();
1788 : :
1789 : : // Map error code to DAVException.
1790 [ # # # # : 0 : switch ( nError )
# # # # #
# # ]
1791 : : {
1792 : : case NE_OK:
1793 : 0 : return;
1794 : :
1795 : : case NE_ERROR: // Generic error
1796 : : {
1797 : : rtl::OUString aText = rtl::OUString::createFromAscii(
1798 [ # # ]: 0 : ne_get_error( m_pHttpSession ) );
1799 : :
1800 : 0 : sal_uInt16 code = makeStatusCode( aText );
1801 : :
1802 [ # # ]: 0 : if ( code == SC_LOCKED )
1803 : : {
1804 [ # # ]: 0 : if ( m_aNeonLockStore.findByUri(
1805 [ # # ][ # # ]: 0 : makeAbsoluteURL( inPath ) ) == 0 )
1806 : : {
1807 : : // locked by 3rd party
1808 : 0 : throw DAVException( DAVException::DAV_LOCKED );
1809 : : }
1810 : : else
1811 : : {
1812 : : // locked by ourself
1813 : 0 : throw DAVException( DAVException::DAV_LOCKED_SELF );
1814 : : }
1815 : : }
1816 : :
1817 : : // Special handling for 400 and 412 status codes, which may indicate
1818 : : // that a lock previously obtained by us has been released meanwhile
1819 : : // by the server. Unfortunately, RFC is not clear at this point,
1820 : : // thus server implementations behave different...
1821 [ # # ][ # # ]: 0 : else if ( code == SC_BAD_REQUEST || code == SC_PRECONDITION_FAILED )
1822 : : {
1823 [ # # ][ # # ]: 0 : if ( removeExpiredLocktoken( makeAbsoluteURL( inPath ), rEnv ) )
[ # # ]
1824 : 0 : throw DAVException( DAVException::DAV_LOCK_EXPIRED );
1825 : : }
1826 : :
1827 : 0 : throw DAVException( DAVException::DAV_HTTP_ERROR, aText, code );
1828 : : }
1829 : : case NE_LOOKUP: // Name lookup failed.
1830 : : throw DAVException( DAVException::DAV_HTTP_LOOKUP,
1831 : : NeonUri::makeConnectionEndPointString(
1832 [ # # ]: 0 : m_aHostName, m_nPort ) );
1833 : :
1834 : : case NE_AUTH: // User authentication failed on server
1835 : : throw DAVException( DAVException::DAV_HTTP_AUTH,
1836 : : NeonUri::makeConnectionEndPointString(
1837 [ # # ]: 0 : m_aHostName, m_nPort ) );
1838 : :
1839 : : case NE_PROXYAUTH: // User authentication failed on proxy
1840 : : throw DAVException( DAVException::DAV_HTTP_AUTHPROXY,
1841 : : NeonUri::makeConnectionEndPointString(
1842 [ # # ]: 0 : m_aProxyName, m_nProxyPort ) );
1843 : :
1844 : : case NE_CONNECT: // Could not connect to server
1845 : : throw DAVException( DAVException::DAV_HTTP_CONNECT,
1846 : : NeonUri::makeConnectionEndPointString(
1847 [ # # ]: 0 : m_aHostName, m_nPort ) );
1848 : :
1849 : : case NE_TIMEOUT: // Connection timed out
1850 : : throw DAVException( DAVException::DAV_HTTP_TIMEOUT,
1851 : : NeonUri::makeConnectionEndPointString(
1852 [ # # ]: 0 : m_aHostName, m_nPort ) );
1853 : :
1854 : : case NE_FAILED: // The precondition failed
1855 : : throw DAVException( DAVException::DAV_HTTP_FAILED,
1856 : : NeonUri::makeConnectionEndPointString(
1857 [ # # ]: 0 : m_aHostName, m_nPort ) );
1858 : :
1859 : : case NE_RETRY: // Retry request (ne_end_request ONLY)
1860 : : throw DAVException( DAVException::DAV_HTTP_RETRY,
1861 : : NeonUri::makeConnectionEndPointString(
1862 [ # # ]: 0 : m_aHostName, m_nPort ) );
1863 : :
1864 : : case NE_REDIRECT:
1865 : : {
1866 [ # # ][ # # ]: 0 : NeonUri aUri( ne_redirect_location( m_pHttpSession ) );
1867 : : throw DAVException(
1868 : 0 : DAVException::DAV_HTTP_REDIRECT, aUri.GetURI() );
1869 : : }
1870 : : default:
1871 : : {
1872 : : OSL_TRACE( "NeonSession::HandleError : Unknown Neon error code!" );
1873 : : throw DAVException( DAVException::DAV_HTTP_ERROR,
1874 : : rtl::OUString::createFromAscii(
1875 [ # # ]: 0 : ne_get_error( m_pHttpSession ) ) );
1876 : : }
1877 : : }
1878 : : }
1879 : :
1880 : : // -------------------------------------------------------------------
1881 : : namespace {
1882 : :
1883 : 0 : void runResponseHeaderHandler( void * userdata,
1884 : : const char * value )
1885 : : {
1886 : 0 : rtl::OUString aHeader( rtl::OUString::createFromAscii( value ) );
1887 : 0 : sal_Int32 nPos = aHeader.indexOf( ':' );
1888 : :
1889 [ # # ]: 0 : if ( nPos != -1 )
1890 : : {
1891 : 0 : rtl::OUString aHeaderName( aHeader.copy( 0, nPos ) );
1892 : :
1893 : : NeonRequestContext * pCtx
1894 : 0 : = static_cast< NeonRequestContext * >( userdata );
1895 : :
1896 : : // Note: Empty vector means that all headers are requested.
1897 : 0 : bool bIncludeIt = ( pCtx->pHeaderNames->empty() );
1898 : :
1899 [ # # ]: 0 : if ( !bIncludeIt )
1900 : : {
1901 : : // Check whether this header was requested.
1902 : : std::vector< ::rtl::OUString >::const_iterator it(
1903 : 0 : pCtx->pHeaderNames->begin() );
1904 : : const std::vector< ::rtl::OUString >::const_iterator end(
1905 : 0 : pCtx->pHeaderNames->end() );
1906 : :
1907 [ # # ][ # # ]: 0 : while ( it != end )
1908 : : {
1909 : : // header names are case insensitive
1910 [ # # ]: 0 : if ( (*it).equalsIgnoreAsciiCase( aHeaderName ) )
1911 : : {
1912 : 0 : aHeaderName = (*it);
1913 : 0 : break;
1914 : : }
1915 : 0 : ++it;
1916 : : }
1917 : :
1918 [ # # ][ # # ]: 0 : if ( it != end )
1919 : 0 : bIncludeIt = true;
1920 : : }
1921 : :
1922 [ # # ]: 0 : if ( bIncludeIt )
1923 : : {
1924 : : // Create & set the PropertyValue
1925 : 0 : DAVPropertyValue thePropertyValue;
1926 : 0 : thePropertyValue.IsCaseSensitive = false;
1927 : 0 : thePropertyValue.Name = aHeaderName;
1928 : :
1929 [ # # ]: 0 : if ( nPos < aHeader.getLength() )
1930 [ # # ]: 0 : thePropertyValue.Value <<= aHeader.copy( nPos + 1 ).trim();
1931 : :
1932 : : // Add the newly created PropertyValue
1933 [ # # ]: 0 : pCtx->pResource->properties.push_back( thePropertyValue );
1934 : 0 : }
1935 : 0 : }
1936 : 0 : }
1937 : :
1938 : : } // namespace
1939 : :
1940 : : // -------------------------------------------------------------------
1941 : : // static
1942 : 0 : int NeonSession::GET( ne_session * sess,
1943 : : const char * uri,
1944 : : ne_block_reader reader,
1945 : : bool getheaders,
1946 : : void * userdata )
1947 : : {
1948 : : //struct get_context ctx;
1949 : 0 : ne_request * req = ne_request_create( sess, "GET", uri );
1950 : : int ret;
1951 : :
1952 : : ne_decompress * dc
1953 : 0 : = ne_decompress_reader( req, ne_accept_2xx, reader, userdata );
1954 : :
1955 : : {
1956 [ # # ]: 0 : osl::Guard< osl::Mutex > theGlobalGuard( aGlobalNeonMutex );
1957 [ # # ][ # # ]: 0 : ret = ne_request_dispatch( req );
1958 : : }
1959 : :
1960 [ # # ]: 0 : if ( getheaders )
1961 : : {
1962 : 0 : void *cursor = NULL;
1963 : : const char *name, *value;
1964 [ # # ][ # # ]: 0 : while ( ( cursor = ne_response_header_iterate(
1965 : : req, cursor, &name, &value ) ) != NULL )
1966 : : {
1967 : : char buffer[8192];
1968 : :
1969 [ # # ]: 0 : ne_snprintf(buffer, sizeof buffer, "%s: %s", name, value);
1970 [ # # ]: 0 : runResponseHeaderHandler(userdata, buffer);
1971 : : }
1972 : : }
1973 : :
1974 [ # # ][ # # ]: 0 : if ( ret == NE_OK && ne_get_status( req )->klass != 2 )
1975 : 0 : ret = NE_ERROR;
1976 : :
1977 [ # # ]: 0 : if ( dc != 0 )
1978 : 0 : ne_decompress_destroy(dc);
1979 : :
1980 : 0 : ne_request_destroy( req );
1981 : 0 : return ret;
1982 : : }
1983 : :
1984 : : // -------------------------------------------------------------------
1985 : : // static
1986 : 0 : int NeonSession::PUT( ne_session * sess,
1987 : : const char * uri,
1988 : : const char * buffer,
1989 : : size_t size)
1990 : : {
1991 : 0 : ne_request * req = ne_request_create( sess, "PUT", uri );
1992 : : int ret;
1993 : :
1994 : 0 : ne_lock_using_resource( req, uri, 0 );
1995 : 0 : ne_lock_using_parent( req, uri );
1996 : :
1997 : 0 : ne_set_request_body_buffer( req, buffer, size );
1998 : :
1999 : : {
2000 [ # # ]: 0 : osl::Guard< osl::Mutex > theGlobalGuard( aGlobalNeonMutex );
2001 [ # # ][ # # ]: 0 : ret = ne_request_dispatch( req );
2002 : : }
2003 : :
2004 [ # # ][ # # ]: 0 : if ( ret == NE_OK && ne_get_status( req )->klass != 2 )
2005 : 0 : ret = NE_ERROR;
2006 : :
2007 : 0 : ne_request_destroy( req );
2008 : 0 : return ret;
2009 : : }
2010 : :
2011 : : // -------------------------------------------------------------------
2012 : 0 : int NeonSession::POST( ne_session * sess,
2013 : : const char * uri,
2014 : : const char * buffer,
2015 : : ne_block_reader reader,
2016 : : void * userdata,
2017 : : const rtl::OUString & rContentType,
2018 : : const rtl::OUString & rReferer )
2019 : : {
2020 [ # # ]: 0 : ne_request * req = ne_request_create( sess, "POST", uri );
2021 : : //struct get_context ctx;
2022 : : int ret;
2023 : :
2024 : 0 : RequestDataMap * pData = 0;
2025 : :
2026 [ # # ][ # # ]: 0 : if ( !rContentType.isEmpty() || !rReferer.isEmpty() )
[ # # ]
2027 : : {
2028 : : // Remember contenttype and referer. Data will be added to HTTP request
2029 : : // header in in 'PreSendRequest' callback.
2030 : 0 : pData = static_cast< RequestDataMap* >( m_pRequestData );
2031 [ # # ]: 0 : (*pData)[ req ] = RequestData( rContentType, rReferer );
2032 : : }
2033 : :
2034 : : //ctx.total = -1;
2035 : : //ctx.fd = fd;
2036 : : //ctx.error = 0;
2037 : : //ctx.session = sess;
2038 : :
2039 : : ///* Read the value of the Content-Length header into ctx.total */
2040 : : //ne_add_response_header_handler( req, "Content-Length",
2041 : : // ne_handle_numeric_header, &ctx.total );
2042 : :
2043 [ # # ]: 0 : ne_add_response_body_reader( req, ne_accept_2xx, reader, userdata );
2044 : :
2045 [ # # ]: 0 : ne_set_request_body_buffer( req, buffer, strlen( buffer ) );
2046 : :
2047 : : {
2048 [ # # ]: 0 : osl::Guard< osl::Mutex > theGlobalGuard( aGlobalNeonMutex );
2049 [ # # ][ # # ]: 0 : ret = ne_request_dispatch( req );
2050 : : }
2051 : :
2052 : : //if ( ctx.error )
2053 : : // ret = NE_ERROR;
2054 : : //else
2055 [ # # ][ # # ]: 0 : if ( ret == NE_OK && ne_get_status( req )->klass != 2 )
[ # # ]
2056 : 0 : ret = NE_ERROR;
2057 : :
2058 [ # # ]: 0 : ne_request_destroy( req );
2059 : :
2060 [ # # ]: 0 : if ( pData )
2061 : : {
2062 : : // Remove request data from session's list.
2063 [ # # ]: 0 : RequestDataMap::iterator it = pData->find( req );
2064 [ # # ][ # # ]: 0 : if ( it != pData->end() )
2065 [ # # ]: 0 : pData->erase( it );
2066 : : }
2067 : :
2068 : 0 : return ret;
2069 : : }
2070 : :
2071 : : // -------------------------------------------------------------------
2072 : : // static
2073 : : bool
2074 : 0 : NeonSession::getDataFromInputStream(
2075 : : const uno::Reference< io::XInputStream > & xStream,
2076 : : uno::Sequence< sal_Int8 > & rData,
2077 : : bool bAppendTrailingZeroByte )
2078 : : {
2079 [ # # ]: 0 : if ( xStream.is() )
2080 : : {
2081 [ # # ]: 0 : uno::Reference< io::XSeekable > xSeekable( xStream, uno::UNO_QUERY );
2082 [ # # ]: 0 : if ( xSeekable.is() )
2083 : : {
2084 : : try
2085 : : {
2086 : : sal_Int32 nSize
2087 [ # # ][ # # ]: 0 : = sal::static_int_cast<sal_Int32>(xSeekable->getLength());
2088 : : sal_Int32 nRead
2089 [ # # ][ # # ]: 0 : = xStream->readBytes( rData, nSize );
2090 : :
2091 [ # # ]: 0 : if ( nRead == nSize )
2092 : : {
2093 [ # # ]: 0 : if ( bAppendTrailingZeroByte )
2094 : : {
2095 [ # # ]: 0 : rData.realloc( nSize + 1 );
2096 [ # # ]: 0 : rData[ nSize ] = sal_Int8( 0 );
2097 : : }
2098 : 0 : return true;
2099 : : }
2100 : : }
2101 [ # # ]: 0 : catch ( io::NotConnectedException const & )
2102 : : {
2103 : : // readBytes
2104 : : }
2105 [ # # ]: 0 : catch ( io::BufferSizeExceededException const & )
2106 : : {
2107 : : // readBytes
2108 : : }
2109 [ # # ]: 0 : catch ( io::IOException const & )
2110 : : {
2111 : : // getLength, readBytes
2112 : : }
2113 : : }
2114 : : else
2115 : : {
2116 : : try
2117 : : {
2118 [ # # ]: 0 : uno::Sequence< sal_Int8 > aBuffer;
2119 : 0 : sal_Int32 nPos = 0;
2120 : :
2121 [ # # ][ # # ]: 0 : sal_Int32 nRead = xStream->readSomeBytes( aBuffer, 65536 );
2122 [ # # ]: 0 : while ( nRead > 0 )
2123 : : {
2124 [ # # ]: 0 : if ( rData.getLength() < ( nPos + nRead ) )
2125 [ # # ]: 0 : rData.realloc( nPos + nRead );
2126 : :
2127 [ # # ]: 0 : aBuffer.realloc( nRead );
2128 [ # # ]: 0 : rtl_copyMemory( (void*)( rData.getArray() + nPos ),
2129 : 0 : (const void*)aBuffer.getConstArray(),
2130 [ # # ]: 0 : nRead );
2131 : 0 : nPos += nRead;
2132 : :
2133 [ # # ]: 0 : aBuffer.realloc( 0 );
2134 [ # # ][ # # ]: 0 : nRead = xStream->readSomeBytes( aBuffer, 65536 );
2135 : : }
2136 : :
2137 [ # # ]: 0 : if ( bAppendTrailingZeroByte )
2138 : : {
2139 [ # # ]: 0 : rData.realloc( nPos + 1 );
2140 [ # # ]: 0 : rData[ nPos ] = sal_Int8( 0 );
2141 : : }
2142 [ # # ]: 0 : return true;
[ # # # # ]
2143 : : }
2144 [ # # ]: 0 : catch ( io::NotConnectedException const & )
2145 : : {
2146 : : // readBytes
2147 : : }
2148 [ # # ]: 0 : catch ( io::BufferSizeExceededException const & )
2149 : : {
2150 : : // readBytes
2151 : : }
2152 [ # # ]: 0 : catch ( io::IOException const & )
2153 : : {
2154 : : // readBytes
2155 : : }
2156 [ # # ]: 0 : }
2157 : : }
2158 [ # # # # ]: 0 : return false;
2159 : : }
2160 : :
2161 : : // ---------------------------------------------------------------------
2162 : : sal_Bool
2163 : 0 : NeonSession::isDomainMatch( rtl::OUString certHostName )
2164 : : {
2165 : 0 : rtl::OUString hostName = getHostName();
2166 : :
2167 [ # # ]: 0 : if (hostName.equalsIgnoreAsciiCase( certHostName ) )
2168 : 0 : return sal_True;
2169 : :
2170 [ # # # # ]: 0 : if ( 0 == certHostName.indexOf( '*' ) &&
[ # # ]
2171 : 0 : hostName.getLength() >= certHostName.getLength() )
2172 : : {
2173 : 0 : rtl::OUString cmpStr = certHostName.copy( 1 );
2174 : :
2175 [ # # ]: 0 : if ( hostName.matchIgnoreAsciiCase(
2176 : 0 : cmpStr, hostName.getLength() - cmpStr.getLength() ) )
2177 [ # # ]: 0 : return sal_True;
2178 : : }
2179 : 0 : return sal_False;
2180 : : }
2181 : :
2182 : : // ---------------------------------------------------------------------
2183 : 0 : rtl::OUString NeonSession::makeAbsoluteURL( rtl::OUString const & rURL ) const
2184 : : {
2185 : : try
2186 : : {
2187 : : // Is URL relative or already absolute?
2188 [ # # ]: 0 : if ( rURL[ 0 ] != sal_Unicode( '/' ) )
2189 : : {
2190 : : // absolute.
2191 : 0 : return rtl::OUString( rURL );
2192 : : }
2193 : : else
2194 : : {
2195 : : ne_uri aUri;
2196 : 0 : memset( &aUri, 0, sizeof( aUri ) );
2197 : :
2198 [ # # ]: 0 : ne_fill_server_uri( m_pHttpSession, &aUri );
2199 : : aUri.path
2200 : : = ne_strdup( rtl::OUStringToOString(
2201 [ # # ][ # # ]: 0 : rURL, RTL_TEXTENCODING_UTF8 ).getStr() );
2202 [ # # ]: 0 : NeonUri aNeonUri( &aUri );
2203 [ # # ]: 0 : ne_uri_free( &aUri );
2204 [ # # ][ # # ]: 0 : return aNeonUri.GetURI();
2205 : : }
2206 : : }
2207 : 0 : catch ( DAVException const & )
2208 : : {
2209 : : }
2210 : : // error.
2211 : 0 : return rtl::OUString();
2212 [ + - ][ + - ]: 6 : }
2213 : :
2214 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|