30 #include <unordered_map>
34 #include <osl/diagnose.h>
35 #include <osl/thread.h>
37 #include <ne_socket.h>
39 #include <ne_redirect.h>
44 #include <ne_compress.h>
47 #include <libxml/parser.h>
61 #include <officecfg/Inet.hxx>
62 #include <com/sun/star/io/BufferSizeExceededException.hpp>
63 #include <com/sun/star/io/IOException.hpp>
64 #include <com/sun/star/io/NotConnectedException.hpp>
65 #include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
66 #include <com/sun/star/security/XCertificate.hpp>
67 #include <com/sun/star/security/CertificateValidity.hpp>
68 #include <com/sun/star/security/CertificateContainerStatus.hpp>
69 #include <com/sun/star/security/CertificateContainer.hpp>
70 #include <com/sun/star/security/XCertificateContainer.hpp>
71 #include <com/sun/star/ucb/Lock.hpp>
72 #include <com/sun/star/beans/NamedValue.hpp>
73 #include <com/sun/star/xml/crypto/SEInitializer.hpp>
88 OUString aContentType;
92 RequestData(
const OUString & rContentType,
93 const OUString & rReferer )
94 : aContentType( rContentType ), aReferer( rReferer ) {}
99 bool operator()(
const ne_request* p1,
const ne_request* p2 )
const
107 size_t operator()(
const ne_request*
p )
const
109 return reinterpret_cast<size_t>(p);
115 typedef std::unordered_map
129 if ( rStatusText.getLength() < 3 )
131 SAL_WARN(
"ucb.ucp.webdav",
"makeStatusCode - status text string to short!" );
135 sal_Int32
nPos = rStatusText.indexOf(
' ' );
138 SAL_WARN(
"ucb.ucp.webdav",
"makeStatusCode - wrong status text format!" );
142 return sal_uInt16( rStatusText.copy( 0, nPos ).toInt32() );
145 static bool noKeepAlive(
const uno::Sequence< beans::NamedValue >& rFlags )
147 if ( !rFlags.hasElements() )
151 const beans::NamedValue* pValue(
152 std::find_if(rFlags.begin(), rFlags.end(),
153 [] (beans::NamedValue
const& rNV) {
return rNV.Name ==
"KeepAlive"; } ));
154 return pValue != rFlags.end() && !pValue->Value.get<
bool>();
159 struct NeonRequestContext
161 uno::Reference< io::XOutputStream > xOutputStream;
163 const std::vector< OUString > * pHeaderNames;
166 explicit NeonRequestContext( uno::Reference< io::XOutputStream >
const & xOutStrm )
167 : xOutputStream( xOutStrm ),
168 pHeaderNames( nullptr ), pResource( nullptr ) {}
171 : xInputStream( xInStrm ),
172 pHeaderNames( nullptr ), pResource( nullptr ) {}
174 NeonRequestContext( uno::Reference< io::XOutputStream >
const & xOutStrm,
175 const std::vector< OUString > & inHeaderNames,
177 : xOutputStream( xOutStrm ),
178 pHeaderNames( &inHeaderNames ), pResource( &ioResource ) {}
181 const std::vector< OUString > & inHeaderNames,
183 : xInputStream( xInStrm ),
184 pHeaderNames( &inHeaderNames ), pResource( &ioResource ) {}
186 void ResponseBlockReader(
const char * inBuf,
size_t inLen)
188 if (xInputStream.is())
189 xInputStream->AddToStream( inBuf, inLen );
192 void ResponseBlockWriter(
const char * inBuf,
size_t inLen)
194 if (xOutputStream.is())
196 const uno::Sequence< sal_Int8 >
aSeq( reinterpret_cast<sal_Int8 const *>(inBuf), inLen );
197 xOutputStream->writeBytes( aSeq );
215 NeonRequestContext * pCtx =
static_cast<NeonRequestContext*
>(inUserData);
216 pCtx->ResponseBlockReader(inBuf, inLen);
229 NeonRequestContext * pCtx =
static_cast<NeonRequestContext*
>(inUserData);
230 pCtx->ResponseBlockWriter(inBuf, inLen);
236 #
if defined NE_FEATURE_SSPI && ! defined SYSTEM_NEON
237 const char * inAuthProtocol,
239 const char * inRealm,
241 char * inoutUserName,
242 char * inoutPassWord )
256 const char * pAuthProtocol;
257 #if defined NE_FEATURE_SSPI && ! defined SYSTEM_NEON
258 pAuthProtocol = inAuthProtocol;
260 pAuthProtocol =
nullptr;
262 return theSession->
NeonAuth(pAuthProtocol, inRealm, attempt, inoutUserName, inoutPassWord);
267 int NeonSession::NeonAuth(
const char* inAuthProtocol,
const char* inRealm,
268 int attempt,
char* inoutUserName,
char * inoutPassWord)
270 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
284 = getRequestEnvironment().m_xAuthListener.get();
290 OUString theUserName;
291 OUString thePassWord;
300 NeonUri uri( getRequestEnvironment().m_aRequestURI );
302 if ( !aUserInfo.isEmpty() )
304 sal_Int32
nPos = aUserInfo.indexOf(
'@' );
307 theUserName = aUserInfo;
311 theUserName = aUserInfo.copy( 0, nPos );
312 thePassWord = aUserInfo.copy( nPos + 1 );
325 theUserName = OUString::createFromAscii( inoutUserName );
330 #if defined NE_FEATURE_SSPI && ! defined SYSTEM_NEON
331 const bool bCanUseSystemCreds
333 ne_has_support( NE_FEATURE_SSPI ) &&
334 ( ( ne_strcasecmp( inAuthProtocol,
"NTLM" ) == 0 ) ||
335 ( ne_strcasecmp( inAuthProtocol,
"Negotiate" ) == 0 ) );
337 (
void)inAuthProtocol;
338 const bool bCanUseSystemCreds =
false;
342 OUString::createFromAscii( inRealm ),
349 if ( aUser.getLength() > ( NE_ABUFSIZ - 1 ) )
351 SAL_WARN(
"ucb.ucp.webdav",
"NeonSession_NeonAuth - username too long!" );
356 if ( aPass.getLength() > ( NE_ABUFSIZ - 1 ) )
358 SAL_WARN(
"ucb.ucp.webdav",
"NeonSession_NeonAuth - password too long!" );
363 strcpy( inoutUserName, aUser.getStr() );
364 strcpy( inoutPassWord, aPass.getStr() );
370 OUString GetHostnamePart(
const OUString& _rRawString )
373 OUString sPartId(
"CN=");
374 sal_Int32 nContStart = _rRawString.indexOf( sPartId );
375 if ( nContStart != -1 )
377 nContStart += sPartId.getLength();
378 sal_Int32 nContEnd = _rRawString.indexOf(
',', nContStart );
379 sPart = nContEnd != -1 ?
380 _rRawString.copy(nContStart, nContEnd - nContStart) :
381 _rRawString.copy(nContStart);
391 const ne_ssl_certificate *cert )
399 int NeonSession::CertificationNotify(
const ne_ssl_certificate *cert)
401 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
405 uno::Reference< security::XCertificateContainer > xCertificateContainer;
410 catch ( uno::Exception
const & )
414 if ( !xCertificateContainer.is() )
417 char * dn = ne_ssl_readable_dname( ne_ssl_cert_subject( cert ) );
418 OUString cert_subject( dn, strlen( dn ), RTL_TEXTENCODING_UTF8, 0 );
422 security::CertificateContainerStatus certificateContainer(
423 xCertificateContainer->hasCertificate(
424 getHostName(), cert_subject ) );
426 if ( certificateContainer != security::CertificateContainerStatus_NOCERT )
428 certificateContainer == security::CertificateContainerStatus_TRUSTED
432 uno::Reference< xml::crypto::XSEInitializer > xSEInitializer;
437 catch ( uno::Exception
const & )
441 if ( !xSEInitializer.is() )
444 uno::Reference< xml::crypto::XXMLSecurityContext > xSecurityContext(
445 xSEInitializer->createSecurityContext( OUString() ) );
447 uno::Reference< xml::crypto::XSecurityEnvironment > xSecurityEnv(
448 xSecurityContext->getSecurityEnvironment() );
451 char * eeCertB64 = ne_ssl_cert_export( cert );
453 OString sEECertB64( eeCertB64 );
455 uno::Reference< security::XCertificate > xEECert(
456 xSecurityEnv->createCertificateFromAscii(
457 OStringToOUString( sEECertB64, RTL_TEXTENCODING_ASCII_US ) ) );
459 ne_free( eeCertB64 );
462 std::vector< uno::Reference< security::XCertificate > > vecCerts;
463 const ne_ssl_certificate * issuerCert = cert;
469 issuerCert = ne_ssl_cert_signedby( issuerCert );
470 if (
nullptr == issuerCert )
473 char * imCertB64 = ne_ssl_cert_export( issuerCert );
474 OString sInterMediateCertB64( imCertB64 );
475 ne_free( imCertB64 );
477 uno::Reference< security::XCertificate> xImCert(
478 xSecurityEnv->createCertificateFromAscii(
479 OStringToOUString( sInterMediateCertB64, RTL_TEXTENCODING_ASCII_US ) ) );
481 vecCerts.push_back( xImCert );
485 sal_Int64 certValidity = xSecurityEnv->verifyCertificate( xEECert,
489 GetHostnamePart( xEECert->getSubjectName() ) ) )
493 if( certValidity == security::CertificateValidity::VALID )
497 const uno::Reference< ucb::XCommandEnvironment > xEnv(
498 getRequestEnvironment().m_xEnv );
501 uno::Reference< task::XInteractionHandler > xIH(
502 xEnv->getInteractionHandler() );
507 static_cast<sal_Int32>(certValidity), xEECert, getHostName() ) );
508 xIH->handle( xRequest );
511 = xRequest->getSelection();
513 if ( xSelection.is() )
515 uno::Reference< task::XInteractionApprove > xApprove(
516 xSelection.get(), uno::UNO_QUERY );
519 xCertificateContainer->addCertificate(
520 getHostName(), cert_subject,
true );
526 xCertificateContainer->addCertificate(
527 getHostName(), cert_subject,
false );
535 xCertificateContainer->addCertificate(
536 getHostName(), cert_subject,
false );
547 ne_buffer * headers )
558 void NeonSession::PreSendRequest(ne_request* req, ne_buffer* headers)
560 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
564 ne_buffer_concat( headers,
"Pragma: no-cache",
EOL,
nullptr );
572 RequestDataMap::const_iterator it = pRequestData->find( req );
573 if ( it != pRequestData->end() )
575 if ( !(*it).second.aContentType.isEmpty() )
577 char *
pData = headers->data;
578 if ( strstr( pData,
"Content-Type:" ) == nullptr )
582 RTL_TEXTENCODING_UTF8 );
583 ne_buffer_concat( headers,
"Content-Type: ",
584 aType.getStr(),
EOL, nullptr );
588 if ( !(*it).second.aReferer.isEmpty() )
590 char *
pData = headers->data;
591 if ( strstr( pData,
"Referer:" ) == nullptr )
595 RTL_TEXTENCODING_UTF8 );
596 ne_buffer_concat( headers,
"Referer: ",
597 aReferer.getStr(),
EOL, nullptr );
603 = getRequestEnvironment().m_aRequestHeaders;
605 for (
const auto& rHeader : rHeaders )
609 RTL_TEXTENCODING_UTF8 );
612 RTL_TEXTENCODING_UTF8 );
613 ne_buffer_concat( headers, aHeader.getStr(),
": ",
614 aValue.getStr(),
EOL, nullptr );
633 bool NeonSession::m_bGlobalsInited =
false;
637 const OUString& inUri,
638 const uno::Sequence< beans::NamedValue >& rFlags,
643 , m_pHttpSession( nullptr )
645 , m_rProxyDecider( rProxyDecider )
651 SAL_INFO(
"ucb.ucp.webdav",
"NeonSession ctor - URL <" << inUri <<
">" );
669 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
676 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
687 if ( ne_sock_init() != 0 )
695 #if OSL_DEBUG_LEVEL > 0
699 ne_debug_init( stderr, NE_DBG_FLUSH
718 bCreateNewSession =
true;
733 bCreateNewSession =
true;
736 if (bCreateNewSession)
747 if ( !bCreateNewSession )
750 const sal_Int32 nConnectTimeoutMax = 180;
751 const sal_Int32 nConnectTimeoutMin = 2;
752 const sal_Int32 nReadTimeoutMax = 180;
753 const sal_Int32 nReadTimeoutMin = 20;
778 if (
m_aScheme.equalsIgnoreAsciiCase(
"https") )
798 RTL_TEXTENCODING_UTF8 ).getStr(),
819 uno::Reference< uno::XComponentContext > rContext =
m_xFactory->getComponentContext();
822 sal_Int32 nConnectTimeout = officecfg::Inet::Settings::ConnectTimeout::get( rContext );
824 std::max( nConnectTimeoutMin,
825 std::min( nConnectTimeout, nConnectTimeoutMax ) ) );
829 sal_Int32 nReadTimeout = officecfg::Inet::Settings::ReadTimeout::get( rContext );
831 std::max( nReadTimeoutMin,
832 std::min( nReadTimeout, nReadTimeoutMax ) ) );
838 const uno::Sequence< beans::NamedValue >& rFlags )
866 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
868 SAL_INFO(
"ucb.ucp.webdav",
"OPTIONS - relative URL <" << inPath <<
">" );
876 inPath, RTL_TEXTENCODING_UTF8 ).getStr());
879 theRetVal = ne_request_dispatch(req);
883 if (theRetVal == NE_OK && ne_get_status(req)->klass != 2) {
884 theRetVal = NE_ERROR;
887 if ( theRetVal == NE_OK )
889 void *cursor =
nullptr;
891 while ( ( cursor = ne_response_header_iterate(
892 req, cursor, &name, &value ) ) !=
nullptr )
894 OUString aHeaderName(OUString(name, strlen(name), RTL_TEXTENCODING_ASCII_US).toAsciiLowerCase());
895 OUString aHeaderValue(value, strlen(value), RTL_TEXTENCODING_ASCII_US);
898 SAL_INFO(
"ucb.ucp.webdav",
"OPTIONS - received header: " << aHeaderName <<
":" << aHeaderValue );
900 if ( aHeaderName ==
"allow" )
904 else if ( aHeaderName ==
"dav" )
915 sal_Int32 nFromIndex = 0;
916 sal_Int32 nNextIndex = 0;
917 while( ( nNextIndex = aHeaderValue.indexOf(
",", nFromIndex ) ) != -1 )
922 aHeaderValue.copy( nFromIndex, nNextIndex - nFromIndex ).toInt32();
938 nFromIndex = nNextIndex + 1;
941 if ( nFromIndex < aHeaderValue.getLength() )
943 sal_Int32 nClass = aHeaderValue.copy( nFromIndex ).toInt32();
975 ne_request_destroy(req);
982 const std::vector< OUString > & inPropNames,
983 std::vector< DAVResource > & ioResources,
987 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
989 #if defined SAL_LOG_INFO
991 SAL_INFO(
"ucb.ucp.webdav",
"PROPFIND - relative URL: <" << inPath <<
"> Depth: " << inDepth );
992 for(
const auto& rPropName : inPropNames)
994 SAL_INFO(
"ucb.ucp.webdav",
"PROPFIND - property requested: " << rPropName );
1001 int theRetVal = NE_OK;
1004 inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1014 const Depth inDepth,
1015 std::vector< DAVResourceInfo > & ioResInfo,
1018 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1019 SAL_INFO(
"ucb.ucp.webdav",
"PROPFIND - relative URL: <" << inPath <<
"> Depth: " << inDepth );
1023 int theRetVal = NE_OK;
1026 inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1031 #if defined SAL_LOG_INFO
1033 for (
const auto& rResInfo : ioResInfo )
1035 for (
const auto& rProp : rResInfo.properties )
1037 SAL_INFO(
"ucb.ucp.webdav",
"PROPFIND - returned property (name only): " << rProp );
1047 const std::vector< ProppatchValue > & inValues,
1050 SAL_INFO(
"ucb.ucp.webdav",
"PROPPATCH - relative URL <" << inPath <<
">" );
1074 int theRetVal = NE_OK;
1079 int nPropCount = inValues.size();
1080 std::unique_ptr<ne_proppatch_operation[]> pItems(
1081 new ne_proppatch_operation[ nPropCount + 1 ]);
1082 for ( n = 0; n < nPropCount; ++n )
1087 ne_propname *
pName =
new ne_propname;
1089 pItems[ n ].name = pName;
1093 pItems[ n ].type = ne_propset;
1095 OUString aStringValue;
1103 pItems[ n ].value =
nullptr;
1104 theRetVal = NE_ERROR;
1109 else if ( !( rValue.
value >>= aStringValue ) )
1114 uno::Sequence< ucb::Link > aLinks;
1115 if ( rValue.
value >>= aLinks )
1122 pItems[ n ].value =
nullptr;
1123 theRetVal = NE_ERROR;
1130 SAL_WARN(
"ucb.ucp.webdav",
"PROPPATCH - Unsupported type!" );
1132 pItems[ n ].value =
nullptr;
1133 theRetVal = NE_ERROR;
1140 RTL_TEXTENCODING_UTF8 ).getStr() );
1144 pItems[ n ].type = ne_propremove;
1145 pItems[ n ].value =
nullptr;
1149 if ( theRetVal == NE_OK )
1151 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1155 pItems[ n ].name =
nullptr;
1159 inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1163 for ( n = 0; n < nPropCount; ++n )
1165 free( const_cast<char *>(pItems[ n ].
name->name) );
1166 delete pItems[ n ].name;
1167 free( const_cast<char *>(pItems[ n ].
value) );
1174 const std::vector< OUString > & inHeaderNames,
1178 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1179 SAL_INFO(
"ucb.ucp.webdav",
"HEAD - relative URL <" << inPath <<
">" );
1183 int theRetVal = NE_OK;
1193 uno::Reference< io::XInputStream >
1197 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1198 SAL_INFO(
"ucb.ucp.webdav",
"GET - relative URL <" << inPath <<
">" );
1203 NeonRequestContext aCtx( xInputStream );
1206 inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1213 return xInputStream;
1217 uno::Reference< io::XOutputStream > & ioOutputStream,
1220 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1221 SAL_INFO(
"ucb.ucp.webdav",
"GET - relative URL <" << inPath <<
">" );
1225 NeonRequestContext aCtx( ioOutputStream );
1228 inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1236 uno::Reference< io::XInputStream >
1238 const std::vector< OUString > & inHeaderNames,
1242 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1243 SAL_INFO(
"ucb.ucp.webdav",
"GET - relative URL <" << inPath <<
">" );
1247 ioResource.
uri = inPath;
1251 NeonRequestContext aCtx( xInputStream, inHeaderNames, ioResource );
1254 inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1261 return xInputStream;
1265 const std::vector< OUString > & inHeaderNames,
1269 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1270 SAL_INFO(
"ucb.ucp.webdav",
"GET - relative URL <" << inPath <<
">" );
1274 ioResource.
uri = inPath;
1278 NeonRequestContext aCtx( xInputStream, inHeaderNames, ioResource );
1281 inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1289 uno::Reference< io::XOutputStream > & ioOutputStream,
1290 const std::vector< OUString > & inHeaderNames,
1294 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1295 SAL_INFO(
"ucb.ucp.webdav",
"GET - relative URL <" << inPath <<
">" );
1299 ioResource.
uri = inPath;
1302 NeonRequestContext aCtx( ioOutputStream, inHeaderNames, ioResource );
1305 inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1314 const uno::Reference< io::XInputStream > & inInputStream,
1317 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1318 SAL_INFO(
"ucb.ucp.webdav",
"PUT - relative URL <" << inPath <<
">" );
1320 uno::Sequence< sal_Int8 > aDataToSend;
1328 inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1329 reinterpret_cast< const char * >(
1330 aDataToSend.getConstArray() ),
1331 aDataToSend.getLength() );
1336 uno::Reference< io::XInputStream >
1338 const OUString & rContentType,
1339 const OUString & rReferer,
1340 const uno::Reference< io::XInputStream > & inInputStream,
1343 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1344 SAL_INFO(
"ucb.ucp.webdav",
"POST - relative URL <" << inPath <<
">" );
1346 uno::Sequence< sal_Int8 > aDataToSend;
1353 NeonRequestContext aCtx( xInputStream );
1356 inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1357 reinterpret_cast< const char * >(
1358 aDataToSend.getConstArray() ),
1366 return xInputStream;
1370 const OUString & rContentType,
1371 const OUString & rReferer,
1372 const uno::Reference< io::XInputStream > & inInputStream,
1373 uno::Reference< io::XOutputStream > & oOutputStream,
1376 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1377 SAL_INFO(
"ucb.ucp.webdav",
"POST - relative URL <" << inPath <<
">" );
1379 uno::Sequence< sal_Int8 > aDataToSend;
1385 NeonRequestContext aCtx( oOutputStream );
1388 inPath, RTL_TEXTENCODING_UTF8 ).getStr(),
1389 reinterpret_cast< const char * >(
1390 aDataToSend.getConstArray() ),
1402 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1403 SAL_INFO(
"ucb.ucp.webdav",
"MKCOL - relative URL <" << inPath <<
">" );
1409 inPath, RTL_TEXTENCODING_UTF8 ).getStr() );
1415 const OUString & inDestinationURL,
1419 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1420 SAL_INFO(
"ucb.ucp.webdav",
"COPY - inSourceURL: "<<inSourceURL<<
" inDestinationURL: "<<inDestinationURL);
1424 NeonUri theSourceUri( inSourceURL );
1425 NeonUri theDestinationUri( inDestinationURL );
1428 inOverWrite ? 1 : 0,
1432 RTL_TEXTENCODING_UTF8 ).getStr(),
1435 RTL_TEXTENCODING_UTF8 ).getStr() );
1441 const OUString & inDestinationURL,
1445 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1446 SAL_INFO(
"ucb.ucp.webdav",
"MOVE - inSourceURL: "<<inSourceURL<<
" inDestinationURL: "<<inDestinationURL);
1450 NeonUri theSourceUri( inSourceURL );
1451 NeonUri theDestinationUri( inDestinationURL );
1453 inOverWrite ? 1 : 0,
1456 RTL_TEXTENCODING_UTF8 ).getStr(),
1459 RTL_TEXTENCODING_UTF8 ).getStr() );
1467 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1468 SAL_INFO(
"ucb.ucp.webdav",
"DESTROY - relative URL <" << inPath <<
">" );
1474 inPath, RTL_TEXTENCODING_UTF8 ).getStr() );
1481 sal_Int32 lastChanceToSendRefreshRequest( TimeValue
const & rStart,
1485 osl_getSystemTime( &aEnd );
1489 sal_Int32 lastChanceToSendRefreshRequest = -1;
1490 if ( timeout != NE_TIMEOUT_INFINITE )
1492 sal_Int32 calltime = aEnd.Seconds - rStart.Seconds;
1493 if ( calltime <= timeout )
1495 lastChanceToSendRefreshRequest = rStart.Seconds + timeout;
1499 SAL_WARN(
"ucb.ucp.webdav",
"LOCK - no chance to refresh lock before timeout!" );
1502 return lastChanceToSendRefreshRequest;
1512 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1513 SAL_INFO(
"ucb.ucp.webdav",
"LOCK (create) - relative URL: <" << inPath <<
">" );
1532 NeonLock * theLock = ne_lock_create();
1537 RTL_TEXTENCODING_UTF8 ).getStr(),
1539 theLock->uri = aUri;
1542 switch( rLock.Depth )
1544 case ucb::LockDepth_ZERO:
1545 theLock->depth = NE_DEPTH_ZERO;
1547 case ucb::LockDepth_ONE:
1548 theLock->depth = NE_DEPTH_ONE;
1550 case ucb::LockDepth_INFINITY:
1551 theLock->depth = NE_DEPTH_INFINITE;
1558 switch ( rLock.Scope )
1560 case ucb::LockScope_EXCLUSIVE:
1561 theLock->scope = ne_lockscope_exclusive;
1563 case ucb::LockScope_SHARED:
1564 theLock->scope = ne_lockscope_shared;
1571 theLock->timeout =
static_cast<long>(rLock.Timeout);
1575 rLock.Owner >>= aValue;
1578 RTL_TEXTENCODING_UTF8 ).getStr() );
1579 TimeValue startCall;
1580 osl_getSystemTime( &startCall );
1584 if ( theRetVal == NE_OK )
1588 lastChanceToSendRefreshRequest(
1589 startCall, theLock->timeout ) );
1591 uno::Sequence< OUString > aTokens( 1 );
1592 aTokens[ 0 ] = OUString::createFromAscii( theLock->token );
1593 rLock.LockTokens = aTokens;
1596 <<
"> token: <" << theLock->token <<
"> timeout: " << theLock->timeout <<
" sec.");
1600 ne_lock_destroy( theLock );
1602 SAL_INFO(
"ucb.ucp.webdav",
"LOCK (create) - Obtaining lock for <"
1611 sal_Int32 & rlastChanceToSendRefreshRequest )
1613 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1615 #if defined SAL_LOG_INFO
1617 char *
p = ne_uri_unparse( &(pLock->uri) );
1618 SAL_INFO(
"ucb.ucp.webdav",
"LOCK (refresh) - relative URL: <" << p <<
"> token: <" << pLock->token <<
">" );
1625 TimeValue startCall;
1626 osl_getSystemTime( &startCall );
1631 long timeout = pLock->timeout;
1633 if (theRetVal == NE_OK)
1635 rlastChanceToSendRefreshRequest
1636 = lastChanceToSendRefreshRequest( startCall, pLock->timeout );
1638 SAL_INFO(
"ucb.ucp.webdav",
"LOCK (refresh) - Lock successfully refreshed." );
1639 pLock->timeout = timeout;
1644 #if defined SAL_LOG_WARN
1645 char *
p = ne_uri_unparse( &(pLock->uri) );
1646 SAL_WARN(
"ucb.ucp.webdav",
"LOCK (refresh) - not refreshed! Relative URL: <" << p <<
"> token: <" << pLock->token <<
">" );
1649 if (theRetVal == NE_AUTH)
1662 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1670 SAL_INFO(
"ucb.ucp.webdav",
"UNLOCK - relative URL: <" << inPath <<
"> token: <" << theLock->token <<
">" );
1675 if ( theRetVal == NE_OK )
1678 ne_lock_destroy( theLock );
1682 SAL_INFO(
"ucb.ucp.webdav",
"UNLOCK - Unlocking of <"
1691 osl::Guard< osl::Mutex > theGuard(
m_aMutex );
1693 #if defined SAL_LOG_INFO
1695 char *
p = ne_uri_unparse( &(pLock->uri) );
1696 SAL_INFO(
"ucb.ucp.webdav",
"UNLOCK (from store) - relative URL: <" << p <<
"> token: <" << pLock->token <<
">" );
1702 if (theRetVal == NE_OK)
1704 #if defined SAL_LOG_INFO
1706 char *
p = ne_uri_unparse( &(pLock->uri) );
1707 SAL_INFO(
"ucb.ucp.webdav",
"UNLOCK (from store) - relative URL: <" << p <<
"> token: <" << pLock->token <<
"> succeeded." );
1715 #if defined SAL_LOG_INFO
1717 char *
p = ne_uri_unparse( &(pLock->uri) );
1718 SAL_INFO(
"ucb.ucp.webdav",
"UNLOCK (from store) - relative URL: <" << p <<
"> token: <" << pLock->token <<
"> failed!" );
1722 if (theRetVal == NE_AUTH)
1733 SAL_INFO(
"ucb.ucp.webdav",
"neon commands cannot be aborted" );
1754 bool containsLocktoken(
const uno::Sequence< ucb::Lock > & rLocks,
1755 const char * token )
1757 return std::any_of(rLocks.begin(), rLocks.end(), [&token](
const ucb::Lock& rLock) {
1758 const uno::Sequence< OUString > & rTokens = rLock.LockTokens;
1759 return std::any_of(rTokens.begin(), rTokens.end(),
1760 [&token](
const OUString& rToken) {
return rToken.equalsAscii( token ); });
1778 std::vector< DAVResource > aResources;
1784 if ( aResources.empty() )
1787 for (
const auto& rProp : aResources[ 0 ].
properties )
1791 uno::Sequence< ucb::Lock > aLocks;
1792 if ( !( rProp.Value >>= aLocks ) )
1795 if ( !containsLocktoken( aLocks, theLock->token ) )
1808 SAL_WARN(
"ucb.ucp.webdav",
"Removing expired lock token for <" << inURL
1809 <<
"> token: " << theLock->token );
1812 ne_lock_destroy( theLock );
1823 const OUString & inPath,
1835 OUString aText(sErr, strlen(sErr), osl_getThreadTextEncoding());
1839 SAL_WARN(
"ucb.ucp.webdav",
"Neon returned NE_ERROR, http response status code was: " << code <<
" '" << aText <<
"'" );
1941 SAL_WARN(
"ucb.ucp.webdav",
"Name lookup failed" );
1957 SAL_WARN(
"ucb.ucp.webdav",
"DAVException::DAV_HTTP_AUTHPROXY" );
1963 SAL_WARN(
"ucb.ucp.webdav",
"DAVException::DAV_HTTP_CONNECT" );
1969 SAL_WARN(
"ucb.ucp.webdav",
"DAVException::DAV_HTTP_TIMEOUT" );
1975 SAL_WARN(
"ucb.ucp.webdav",
"The precondition failed" );
1988 SAL_INFO(
"ucb.ucp.webdav",
"DAVException::DAV_HTTP_REDIRECT: new URI: " << aUri.
GetURI() );
1994 SAL_WARN(
"ucb.ucp.webdav",
"Unknown Neon error code!" );
1997 OUString(sErr, strlen(sErr), osl_getThreadTextEncoding()) );
2004 void runResponseHeaderHandler(
void * userdata,
2005 const char * value )
2007 OUString aHeader(value, strlen(value), RTL_TEXTENCODING_ASCII_US);
2008 sal_Int32
nPos = aHeader.indexOf(
':' );
2013 OUString aHeaderName( aHeader.copy( 0, nPos ) );
2015 NeonRequestContext * pCtx
2016 =
static_cast< NeonRequestContext *
>( userdata );
2019 bool bIncludeIt = pCtx->pHeaderNames->empty();
2024 auto it = std::find_if(pCtx->pHeaderNames->cbegin(), pCtx->pHeaderNames->cend(),
2025 [&aHeaderName](
const OUString& rName) {
2027 return rName.equalsIgnoreAsciiCase( aHeaderName ); });
2029 if ( it != pCtx->pHeaderNames->end() )
2043 thePropertyValue.
Name = aHeaderName.toAsciiLowerCase();
2046 if ( nPos < aHeader.getLength() )
2047 thePropertyValue.
Value <<= aHeader.copy( nPos + 1 ).trim();
2050 pCtx->pResource->properties.push_back( thePropertyValue );
2057 ne_block_reader reader,
2062 ne_request * req = ne_request_create( sess,
"GET", uri );
2066 = ne_decompress_reader( req, ne_accept_2xx, reader, userdata );
2070 ret = ne_request_dispatch( req );
2075 void *cursor =
nullptr;
2076 const char *
name, *value;
2077 while ( ( cursor = ne_response_header_iterate(
2078 req, cursor, &name, &value ) ) !=
nullptr )
2082 SAL_INFO(
"ucb.ucp.webdav",
"GET - received header: " << name <<
": " << value );
2083 ne_snprintf(buffer,
sizeof buffer,
"%s: %s", name, value);
2084 runResponseHeaderHandler(userdata, buffer);
2088 if ( ret == NE_OK && ne_get_status( req )->klass != 2 )
2091 if ( dc !=
nullptr )
2092 ne_decompress_destroy(dc);
2094 ne_request_destroy( req );
2104 ne_request * req = ne_request_create( sess,
"GET", uri );
2109 ret = ne_request_dispatch( req );
2114 void *cursor =
nullptr;
2115 const char *
name, *value;
2116 while ( ( cursor = ne_response_header_iterate(
2117 req, cursor, &name, &value ) ) !=
nullptr )
2121 SAL_INFO(
"ucb.ucp.webdav",
"GET - received header: " << name <<
": " << value );
2122 ne_snprintf(buffer,
sizeof buffer,
"%s: %s", name, value);
2123 runResponseHeaderHandler(userdata, buffer);
2127 if ( ret == NE_OK && ne_get_status( req )->klass != 2 )
2130 ne_request_destroy( req );
2136 const char * buffer,
2139 ne_request * req = ne_request_create( sess,
"PUT", uri );
2147 ne_uri_parse( uri, &aUri );
2148 ne_lock_using_resource( req, aUri.path, 0 );
2149 ne_lock_using_parent( req, uri );
2151 ne_set_request_body_buffer( req, buffer, size );
2155 ret = ne_request_dispatch( req );
2158 if ( ret == NE_OK && ne_get_status( req )->klass != 2 )
2161 ne_request_destroy( req );
2167 const char * buffer,
2168 ne_block_reader reader,
2170 const OUString & rContentType,
2171 const OUString & rReferer )
2173 ne_request * req = ne_request_create( sess,
"POST", uri );
2179 if ( !rContentType.isEmpty() || !rReferer.isEmpty() )
2184 (*pData)[ req ] = RequestData( rContentType, rReferer );
2196 ne_add_response_body_reader( req, ne_accept_2xx, reader, userdata );
2198 ne_set_request_body_buffer( req, buffer, strlen( buffer ) );
2202 ret = ne_request_dispatch( req );
2208 if ( ret == NE_OK && ne_get_status( req )->klass != 2 )
2211 ne_request_destroy( req );
2216 RequestDataMap::iterator it = pData->find( req );
2217 if ( it != pData->end() )
2226 const uno::Reference< io::XInputStream > & xStream,
2227 uno::Sequence< sal_Int8 > & rData,
2228 bool bAppendTrailingZeroByte )
2232 uno::Reference< io::XSeekable > xSeekable( xStream, uno::UNO_QUERY );
2233 if ( xSeekable.is() )
2238 = sal::static_int_cast<sal_Int32>(xSeekable->getLength());
2240 = xStream->readBytes( rData, nSize );
2242 if ( nRead == nSize )
2244 if ( bAppendTrailingZeroByte )
2246 rData.realloc( nSize + 1 );
2252 catch ( io::NotConnectedException
const & )
2256 catch ( io::BufferSizeExceededException
const & )
2260 catch ( io::IOException
const & )
2269 uno::Sequence< sal_Int8 >
aBuffer;
2272 sal_Int32 nRead = xStream->readSomeBytes( aBuffer, 65536 );
2275 if ( rData.getLength() < ( nPos + nRead ) )
2276 rData.realloc( nPos + nRead );
2278 aBuffer.realloc( nRead );
2279 memcpy( static_cast<void*>( rData.getArray() + nPos ),
2280 static_cast<const void*>(aBuffer.getConstArray()),
2284 aBuffer.realloc( 0 );
2285 nRead = xStream->readSomeBytes( aBuffer, 65536 );
2288 if ( bAppendTrailingZeroByte )
2290 rData.realloc( nPos + 1 );
2295 catch ( io::NotConnectedException
const & )
2299 catch ( io::BufferSizeExceededException
const & )
2303 catch ( io::IOException
const & )
2317 if (hostName.equalsIgnoreAsciiCase( certHostName ) )
2320 if ( certHostName.startsWith(
"*" ) &&
2321 hostName.getLength() >= certHostName.getLength() )
2323 OUString cmpStr = certHostName.copy( 1 );
2325 if ( hostName.matchIgnoreAsciiCase(
2326 cmpStr, hostName.getLength() - cmpStr.getLength() ) )
2337 if ( !rURL.isEmpty() && rURL[ 0 ] !=
'/' )
2349 rURL, RTL_TEXTENCODING_UTF8 ).getStr() );
2351 ne_uri_free( &aUri );
2352 return aNeonUri.
GetURI();
int NeonAuth(const char *inAuthProtocol, const char *inRealm, int attempt, char *inoutUserName, char *inoutPassWord)
DAVRequestEnvironment m_aEnv
const sal_uInt16 SC_LOCKED
const OUString & GetUserInfo() const
const sal_uInt16 SC_BAD_REQUEST
const OUString & getHostName() const
std::unique_ptr< ContentProperties > pData
static void NeonSession_PreSendRequest(ne_request *req, void *userdata, ne_buffer *headers)
const sal_uInt16 SC_GATEWAY_TIMEOUT
std::vector< DAVRequestHeader > DAVRequestHeaders
virtual void LOCK(const OUString &inURL, css::ucb::Lock &inLock, const DAVRequestEnvironment &rEnv) override
virtual void PROPPATCH(const OUString &inPath, const std::vector< ProppatchValue > &inValues, const DAVRequestEnvironment &rEnv) override
static bool toXML(const css::uno::Sequence< css::ucb::Link > &rInData, OUString &rOutData)
static constexpr OUStringLiteral LOCKDISCOVERY
virtual void GET0(const OUString &inPath, const std::vector< OUString > &inHeaderNames, DAVResource &ioResource, const DAVRequestEnvironment &rEnv) override
NeonLock * findByUri(std::u16string_view rUri)
void setClass2(bool Class2=true)
const sal_uInt16 SC_REQUEST_ENTITY_TOO_LARGE
OUString makeAbsoluteURL(OUString const &rURL) const
void registerSession(HttpSession *pHttpSession)
virtual void abort() override
static sal_uInt16 makeStatusCode(const OUString &rStatusText)
virtual void OPTIONS(const OUString &inPath, DAVOptions &rOptions, const DAVRequestEnvironment &rEnv) override
void setClass1(bool Class1=true)
void removeLockDeferred(NeonLock *pLock)
static NeonLockStore m_aNeonLockStore
const ucbhelper::InternetProxyDecider & m_rProxyDecider
virtual int authenticate(const OUString &inRealm, const OUString &inHostName, OUString &inoutUserName, OUString &outPassWord, bool bCanUseSystemCredentials)=0
css::uno::Any const & rValue
const OUString & GetPath() const
sal_Int32 GetPort() const
const sal_uInt16 SC_INSUFFICIENT_STORAGE
const sal_uInt16 SC_FAILED_DEPENDENCY
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
const sal_uInt16 SC_REQUEST_TIMEOUT
virtual void UNLOCK(const OUString &inURL, const DAVRequestEnvironment &rEnv) override
virtual void DESTROY(const OUString &inPath, const DAVRequestEnvironment &rEnv) override
virtual css::uno::Reference< css::io::XInputStream > POST(const OUString &inPath, const OUString &rContentType, const OUString &rReferer, const css::uno::Reference< css::io::XInputStream > &inInputStream, const DAVRequestEnvironment &rEnv) override
const sal_uInt16 SC_REQUEST_URI_TOO_LONG
const sal_uInt16 SC_NOT_ACCEPTABLE
const sal_uInt16 SC_PAYMENT_REQUIRED
bool removeExpiredLocktoken(const OUString &inURL, const DAVRequestEnvironment &rEnv)
static bool m_bGlobalsInited
const sal_uInt16 SC_METHOD_NOT_ALLOWED
const sal_uInt16 SC_SERVICE_UNAVAILABLE
virtual void COPY(const OUString &inSourceURL, const OUString &inDestinationURL, const DAVRequestEnvironment &rEnv, bool inOverWrite) override
const sal_uInt16 SC_NOT_IMPLEMENTED
static int NeonSession_ResponseBlockWriter(void *inUserData, const char *inBuf, size_t inLen)
static bool getDataFromInputStream(const css::uno::Reference< css::io::XInputStream > &xStream, css::uno::Sequence< sal_Int8 > &rData, bool bAppendTrailingZeroByte)
osl::Mutex & getGlobalNeonMutex()
static int NeonSession_CertificationNotify(void *userdata, int, const ne_ssl_certificate *cert)
static int NeonSession_ResponseBlockReader(void *inUserData, const char *inBuf, size_t inLen)
virtual ~NeonSession() override
void PreSendRequest(ne_request *req, ne_buffer *headers)
void setAllowedMethods(const OUString &aAllowedMethods)
HttpSession * m_pHttpSession
static bool toXML(const css::uno::Any &rInData, OUString &rOutData)
virtual bool UsesProxy() override
const PropertyStruct aPropNames[]
const sal_uInt16 SC_UNSUPPORTED_MEDIA_TYPE
virtual void PROPFIND(const OUString &inPath, const Depth inDepth, const std::vector< OUString > &inPropNames, std::vector< DAVResource > &ioResources, const DAVRequestEnvironment &rEnv) override
const sal_uInt16 SC_BAD_GATEWAY
const OUString & GetHost() const
ucbhelper::InternetProxyServer getProxySettings() const
Reference< XComponentContext > getComponentContext(Reference< XMultiServiceFactory > const &factory)
static void createNeonPropName(const OUString &rFullName, NeonPropName &rName)
const sal_uInt16 SC_FORBIDDEN
const sal_uInt16 SC_REQUESTED_RANGE_NOT_SATISFIABLE
static bool isUCBDeadProperty(const NeonPropName &rName)
virtual void MKCOL(const OUString &inPath, const DAVRequestEnvironment &rEnv) override
static constexpr OUStringLiteral SOURCE
virtual bool CanUse(const OUString &inPath, const css::uno::Sequence< css::beans::NamedValue > &rFlags) override
bool isDomainMatch(const OUString &certHostName)
void addLock(NeonLock *pLock, rtl::Reference< NeonSession > const &xSession, sal_Int32 nLastChanceToSendRefreshRequest)
const sal_uInt16 SC_LENGTH_REQUIRED
std::unique_ptr< char[]> aBuffer
std::vector< DAVPropertyValue > properties
virtual void MOVE(const OUString &inSourceURL, const OUString &inDestinationURL, const DAVRequestEnvironment &rEnv, bool inOverWrite) override
static bool noKeepAlive(const uno::Sequence< beans::NamedValue > &rFlags)
std::unordered_map< ne_request *, RequestData, hashPtr, equalPtr > RequestDataMap
int CertificationNotify(const ne_ssl_certificate *cert)
static int NeonSession_NeonAuth(void *inUserData, const char *inRealm, int attempt, char *inoutUserName, char *inoutPassWord)
const sal_uInt16 SC_CONFLICT
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
#define SAL_INFO(area, stream)
const sal_uInt16 SC_UNPROCESSABLE_ENTITY
void removeLock(NeonLock *pLock)
void HandleError(int nError, const OUString &inPath, const DAVRequestEnvironment &rEnv)
void setLocked(bool locked=true)
Sequence< sal_Int8 > aSeq
const sal_uInt16 SC_NOT_FOUND
const OUString & GetScheme() const
const sal_uInt16 SC_PROXY_AUTHENTICATION_REQUIRED
virtual css::uno::Reference< css::io::XInputStream > GET(const OUString &inPath, const DAVRequestEnvironment &rEnv) override
const OUString & GetURI() const
#define SAL_WARN(area, stream)
const sal_uInt16 SC_PRECONDITION_FAILED
virtual void HEAD(const OUString &inPath, const std::vector< OUString > &inHeaderNames, DAVResource &ioResource, const DAVRequestEnvironment &rEnv) override
css::uno::Sequence< css::beans::NamedValue > m_aFlags
const sal_uInt16 SC_EXPECTATION_FAILED
ProppatchOperation operation
InternetProxyServer getProxy(const OUString &rProtocol, const OUString &rHost, sal_Int32 nPort) const
const sal_uInt16 SC_UNAUTHORIZED
rtl::Reference< DAVSessionFactory > m_xFactory
virtual void PUT(const OUString &inPath, const css::uno::Reference< css::io::XInputStream > &inInputStream, const DAVRequestEnvironment &rEnv) override
const sal_uInt16 SC_INTERNAL_SERVER_ERROR
const sal_uInt16 SC_HTTP_VERSION_NOT_SUPPORTED
void setClass3(bool Class3=true)
exports com.sun.star. uri
static OUString makeConnectionEndPointString(const OUString &rHostName, int nPort)