diff options
Diffstat (limited to 'ucb/source/ucp/webdav')
20 files changed, 2337 insertions, 1519 deletions
diff --git a/ucb/source/ucp/webdav/DAVException.hxx b/ucb/source/ucp/webdav/DAVException.hxx index 8e87ab2f2a36..cbbd64755942 100644 --- a/ucb/source/ucp/webdav/DAVException.hxx +++ b/ucb/source/ucp/webdav/DAVException.hxx @@ -108,17 +108,37 @@ class DAVException { public: enum ExceptionCode { - DAV_HTTP_ERROR = 0, // Generic error, mData = error message - DAV_HTTP_LOOKUP, // Name lookup failed, mData = server[:port] - DAV_HTTP_AUTH, // User authentication failed on server - DAV_HTTP_AUTHPROXY, // User authentication failed on proxy - DAV_HTTP_CONNECT, // Could not connect to server, mData = server[:port] + DAV_HTTP_ERROR = 0, // Generic error, + // mData = server error message, + // mStatusCode = HTTP status code + DAV_HTTP_LOOKUP, // Name lookup failed, + // mData = server[:port] + DAV_HTTP_AUTH, // User authentication failed on server, + // mData = server[:port] + DAV_HTTP_AUTHPROXY, // User authentication failed on proxy, + // mData = proxy server[:port] + DAV_HTTP_CONNECT, // Could not connect to server, + // mData = server[:port] DAV_HTTP_TIMEOUT, // Connection timed out + // mData = server[:port] DAV_HTTP_FAILED, // The precondition failed + // mData = server[:port] DAV_HTTP_RETRY, // Retry request - DAV_HTTP_REDIRECT, // See http_redirect.h, mData = new URL - DAV_SESSION_CREATE, // session creation error, mData = server[:port] - DAV_INVALID_ARG }; // mData = file URL + // mData = server[:port] + DAV_HTTP_REDIRECT, // Request was redirected, + // mData = new URL + DAV_SESSION_CREATE, // session creation error, + // mData = server[:port] + DAV_INVALID_ARG, // invalid argument + + DAV_LOCK_EXPIRED, // DAV lock expired + + DAV_NOT_LOCKED, // not locked + + DAV_LOCKED_SELF, // locked by this OOo session + + DAV_LOCKED // locked by third party + }; private: ExceptionCode mExceptionCode; diff --git a/ucb/source/ucp/webdav/DAVProperties.cxx b/ucb/source/ucp/webdav/DAVProperties.cxx index 2f11c2ee02c0..d2d434184ace 100644 --- a/ucb/source/ucp/webdav/DAVProperties.cxx +++ b/ucb/source/ucp/webdav/DAVProperties.cxx @@ -137,6 +137,26 @@ void DAVProperties::createUCBPropName( const char * nspace, rtl::OUString aName = rtl::OStringToOUString( name, RTL_TEXTENCODING_UTF8 ); + if ( !aNameSpace.getLength() ) + { + // Some servers send XML without proper namespaces. Assume "DAV:" + // in this case, if name is a well-known dav property name. + // Although this is not 100% correct, it solves many problems. + + if ( DAVProperties::RESOURCETYPE.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::SUPPORTEDLOCK.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::LOCKDISCOVERY.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::CREATIONDATE.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::DISPLAYNAME.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::GETCONTENTLANGUAGE.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::GETCONTENTLENGTH.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::GETCONTENTTYPE.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::GETETAG.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::GETLASTMODIFIED.matchIgnoreAsciiCase( aName, 4 ) || + DAVProperties::SOURCE.matchIgnoreAsciiCase( aName, 4 ) ) + aNameSpace = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DAV:" ) ); + } + // Note: Concatenating strings BEFORE comparing against known namespaces // is important. See RFC 2815 ( 23.4.2 Meaning of Qualified Names ). rFullName = aNameSpace; @@ -175,6 +195,8 @@ void DAVProperties::createUCBPropName( const char * nspace, // static bool DAVProperties::isUCBDeadProperty( const NeonPropName & rName ) { - return ( rtl_str_compareIgnoreAsciiCase( - rName.nspace, "http://ucb.openoffice.org/dav/props/" ) == 0 ); + return ( rName.nspace && + ( rtl_str_compareIgnoreAsciiCase( + rName.nspace, "http://ucb.openoffice.org/dav/props/" ) + == 0 ) ); } diff --git a/ucb/source/ucp/webdav/DAVResourceAccess.cxx b/ucb/source/ucp/webdav/DAVResourceAccess.cxx index 140b3dd3af94..00b42e24a5d9 100644 --- a/ucb/source/ucp/webdav/DAVResourceAccess.cxx +++ b/ucb/source/ucp/webdav/DAVResourceAccess.cxx @@ -67,6 +67,7 @@ int DAVAuthListener_Impl::authenticate( { uno::Reference< task::XInteractionHandler > xIH = m_xEnv->getInteractionHandler(); + if ( xIH.is() ) { // #102871# - Supply username and password from previous try. @@ -78,14 +79,10 @@ int DAVAuthListener_Impl::authenticate( outPassWord = m_aPrevPassword; rtl::Reference< ucbhelper::SimpleAuthenticationRequest > xRequest - = new ucbhelper::SimpleAuthenticationRequest( m_aURL, - inHostName, - inRealm, - inoutUserName, - outPassWord, - ::rtl::OUString(), - bAllowPersistentStoring, - bCanUseSystemCredentials ); + = new ucbhelper::SimpleAuthenticationRequest( + m_aURL, inHostName, inRealm, inoutUserName, + outPassWord, ::rtl::OUString(), + bAllowPersistentStoring, bCanUseSystemCredentials ); xIH->handle( xRequest.get() ); rtl::Reference< ucbhelper::InteractionContinuation > xSelection @@ -105,7 +102,8 @@ int DAVAuthListener_Impl::authenticate( sal_Bool bUseSystemCredentials = sal_False; if ( bCanUseSystemCredentials ) - bUseSystemCredentials = xSupp->getUseSystemCredentials(); + bUseSystemCredentials + = xSupp->getUseSystemCredentials(); if ( bUseSystemCredentials ) { @@ -178,6 +176,7 @@ DAVResourceAccess & DAVResourceAccess::operator=( return *this; } +#if 0 // currently not used, but please don't remove code //========================================================================= void DAVResourceAccess::OPTIONS( DAVCapabilities & rCapabilities, @@ -217,6 +216,7 @@ void DAVResourceAccess::OPTIONS( } while ( bRetry ); } +#endif //========================================================================= void DAVResourceAccess::PROPFIND( @@ -353,6 +353,7 @@ void DAVResourceAccess::HEAD( throw( DAVException ) { initialize(); + int errorCount = 0; bool bRetry; do @@ -409,7 +410,8 @@ uno::Reference< io::XInputStream > DAVResourceAccess::GET( xStream = m_xSession->GET( getRequestURI(), DAVRequestEnvironment( getRequestURI(), - new DAVAuthListener_Impl( xEnv, m_aURL ), + new DAVAuthListener_Impl( + xEnv, m_aURL ), aHeaders, xEnv ) ); } catch ( DAVException & e ) @@ -492,7 +494,8 @@ uno::Reference< io::XInputStream > DAVResourceAccess::GET( rResource, DAVRequestEnvironment( getRequestURI(), - new DAVAuthListener_Impl( xEnv, m_aURL ), + new DAVAuthListener_Impl( + xEnv, m_aURL ), aHeaders, xEnv ) ); } catch ( DAVException & e ) @@ -552,13 +555,15 @@ void DAVResourceAccess::GET( } //========================================================================= -void DAVResourceAccess::ABORT() +void DAVResourceAccess::abort() throw( DAVException ) { - // 17.11.09 (tkr): abort currently disabled caused by issue i106766 - // initialize(); - // m_xSession->ABORT(); + // 17.11.09 (tkr): abort currently disabled caused by issue i106766 + // initialize(); + // m_xSession->abort(); + OSL_TRACE( "Not implemented. -> #i106766#" ); } + //========================================================================= namespace { @@ -674,7 +679,8 @@ uno::Reference< io::XInputStream > DAVResourceAccess::POST( xSeekableStream, DAVRequestEnvironment( getRequestURI(), - new DAVAuthListener_Impl( xEnv, m_aURL ), + new DAVAuthListener_Impl( + xEnv, m_aURL ), aHeaders, xEnv ) ); } catch ( DAVException & e ) @@ -697,7 +703,6 @@ uno::Reference< io::XInputStream > DAVResourceAccess::POST( } //========================================================================= - void DAVResourceAccess::POST( const rtl::OUString & rContentType, const rtl::OUString & rReferer, @@ -765,6 +770,7 @@ void DAVResourceAccess::MKCOL( throw( DAVException ) { initialize(); + int errorCount = 0; bool bRetry; do @@ -804,6 +810,7 @@ void DAVResourceAccess::COPY( throw( DAVException ) { initialize(); + int errorCount = 0; bool bRetry; do @@ -845,6 +852,7 @@ void DAVResourceAccess::MOVE( throw( DAVException ) { initialize(); + int errorCount = 0; bool bRetry; do @@ -916,23 +924,124 @@ void DAVResourceAccess::DESTROY( } //========================================================================= -void DAVResourceAccess::LOCK ( - const ucb::Lock & /*rLock*/, - const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) - throw( DAVException ) +// set new lock. +void DAVResourceAccess::LOCK( + ucb::Lock & inLock, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ) { -// initialize(); - OSL_ENSURE( sal_False, "DAVResourceAccess::LOCK - NYI" ); + initialize(); + + int errorCount = 0; + bool bRetry; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( "LOCK" ), + aHeaders ); + + m_xSession->LOCK( getRequestURI(), + inLock, + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( xEnv, m_aURL ), + aHeaders, xEnv ) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); } //========================================================================= -void DAVResourceAccess::UNLOCK ( - const ucb::Lock & /*rLock*/, - const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ ) - throw( DAVException ) +// refresh existing lock. +sal_Int64 DAVResourceAccess::LOCK( + sal_Int64 nTimeout, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ) +{ + initialize(); + + sal_Int64 nNewTimeout = 0; + int errorCount = 0; + bool bRetry; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( "LOCK" ), + aHeaders ); + + nNewTimeout = m_xSession->LOCK( getRequestURI(), + nTimeout, + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( + xEnv, m_aURL ), + aHeaders, xEnv ) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); + + return nNewTimeout; +} + +//========================================================================= +void DAVResourceAccess::UNLOCK( + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ) { -// initialize(); - OSL_ENSURE( sal_False, "DAVResourceAccess::UNLOCK - NYI" ); + initialize(); + + int errorCount = 0; + bool bRetry; + do + { + bRetry = false; + try + { + DAVRequestHeaders aHeaders; + getUserRequestHeaders( xEnv, + getRequestURI(), + rtl::OUString::createFromAscii( "UNLOCK" ), + aHeaders ); + + m_xSession->UNLOCK( getRequestURI(), + DAVRequestEnvironment( + getRequestURI(), + new DAVAuthListener_Impl( xEnv, m_aURL ), + aHeaders, xEnv ) ); + } + catch ( DAVException & e ) + { + errorCount++; + bRetry = handleException( e, errorCount ); + if ( !bRetry ) + throw; + } + } + while ( bRetry ); } //========================================================================= @@ -1029,9 +1138,8 @@ void DAVResourceAccess::getUserRequestHeaders( "Value is not a string! Ignoring..." ); } - rRequestHeaders.push_back( DAVRequestHeader( - aRequestHeaders[ n ].Name, - aValue ) ); + rRequestHeaders.push_back( + DAVRequestHeader( aRequestHeaders[ n ].Name, aValue ) ); } } } @@ -1075,7 +1183,6 @@ void DAVResourceAccess::resetUri() } } - //========================================================================= sal_Bool DAVResourceAccess::handleException( DAVException & e, int errorCount ) throw ( DAVException ) @@ -1095,7 +1202,9 @@ sal_Bool DAVResourceAccess::handleException( DAVException & e, int errorCount ) // if we have a bad connection try again. Up to three times. case DAVException::DAV_HTTP_ERROR: // retry up to three times, if not a client-side error. - if ( ( e.getStatus() < 400 || e.getStatus() > 499 ) && errorCount < 3) + if ( e.getStatus() > 0 && + ( e.getStatus() < 400 || e.getStatus() > 499 ) && + errorCount < 3 ) { return sal_True; } diff --git a/ucb/source/ucp/webdav/DAVResourceAccess.hxx b/ucb/source/ucp/webdav/DAVResourceAccess.hxx index 2ab863dc0b24..b4f6eb2b5a9e 100644 --- a/ucb/source/ucp/webdav/DAVResourceAccess.hxx +++ b/ucb/source/ucp/webdav/DAVResourceAccess.hxx @@ -59,22 +59,22 @@ class DAVResourceAccess rtl::Reference< DAVSession > m_xSession; rtl::Reference< DAVSessionFactory > m_xSessionFactory; com::sun::star::uno::Reference< - com::sun::star::lang::XMultiServiceFactory > m_xSMgr; + com::sun::star::lang::XMultiServiceFactory > m_xSMgr; std::vector< NeonUri > m_aRedirectURIs; public: DAVResourceAccess() : m_xSessionFactory( 0 ) {} DAVResourceAccess( const com::sun::star::uno::Reference< - com::sun::star::lang::XMultiServiceFactory > & rSMgr, + com::sun::star::lang::XMultiServiceFactory > & rSMgr, rtl::Reference< - DAVSessionFactory > const & rSessionFactory, + DAVSessionFactory > const & rSessionFactory, const rtl::OUString & rURL ); DAVResourceAccess( const DAVResourceAccess & rOther ); DAVResourceAccess & operator=( const DAVResourceAccess & rOther ); void setURL( const rtl::OUString & rNewURL ) - throw( DAVException ); + throw ( DAVException ); void resetUri(); @@ -86,146 +86,156 @@ public: // DAV methods // +#if 0 // currently not used, but please don't remove code void OPTIONS( DAVCapabilities & rCapabilities, - const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv ) - throw( DAVException ); + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); +#endif // allprop & named void PROPFIND( const Depth nDepth, - const std::vector< rtl::OUString > & rPropertyNames, - std::vector< DAVResource > & rResources, - const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv ) - throw( DAVException ); + const std::vector< rtl::OUString > & rPropertyNames, + std::vector< DAVResource > & rResources, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); // propnames void PROPFIND( const Depth nDepth, - std::vector< DAVResourceInfo > & rResInfo, - const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv ) - throw( DAVException ); + std::vector< DAVResourceInfo > & rResInfo, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); void PROPPATCH( const std::vector< ProppatchValue > & rValues, - const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment >& xEnv ) - throw( DAVException ); + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw ( DAVException ); void HEAD( const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all' DAVResource & rResource, const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment >& xEnv ) - throw( DAVException ); + com::sun::star::ucb::XCommandEnvironment >& xEnv ) + throw ( DAVException ); com::sun::star::uno::Reference< com::sun::star::io::XInputStream > GET( const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv ) - throw( DAVException ); + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); void GET( com::sun::star::uno::Reference< - com::sun::star::io::XOutputStream > & rStream, + com::sun::star::io::XOutputStream > & rStream, const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv ) - throw( DAVException ); + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); com::sun::star::uno::Reference< com::sun::star::io::XInputStream > GET( const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all' DAVResource & rResource, const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv ) - throw( DAVException ); + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); void GET( com::sun::star::uno::Reference< - com::sun::star::io::XOutputStream > & rStream, + com::sun::star::io::XOutputStream > & rStream, const std::vector< rtl::OUString > & rHeaderNames, // empty == 'all' DAVResource & rResource, const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv ) - throw( DAVException ); + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); void PUT( const com::sun::star::uno::Reference< - com::sun::star::io::XInputStream > & rStream, - const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv ) - throw( DAVException ); + com::sun::star::io::XInputStream > & rStream, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); com::sun::star::uno::Reference< com::sun::star::io::XInputStream > POST( const rtl::OUString & rContentType, - const rtl::OUString & rReferer, - const com::sun::star::uno::Reference< - com::sun::star::io::XInputStream > & rInputStream, - const com::sun::star::uno::Reference< + const rtl::OUString & rReferer, + const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > & rInputStream, + const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment >& xEnv ) throw ( DAVException ); void POST( const rtl::OUString & rContentType, - const rtl::OUString & rReferer, - const com::sun::star::uno::Reference< - com::sun::star::io::XInputStream > & rInputStream, - com::sun::star::uno::Reference< - com::sun::star::io::XOutputStream > & rOutputStream, - const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment >& xEnv ) + const rtl::OUString & rReferer, + const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > & rInputStream, + com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > & rOutputStream, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv ) throw ( DAVException ); void MKCOL( const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv ) - throw( DAVException ); + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); void COPY( const ::rtl::OUString & rSourcePath, - const ::rtl::OUString & rDestinationURI, - sal_Bool bOverwrite, - const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv ) - throw( DAVException ); + const ::rtl::OUString & rDestinationURI, + sal_Bool bOverwrite, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); void MOVE( const ::rtl::OUString & rSourcePath, - const ::rtl::OUString & rDestinationURI, - sal_Bool bOverwrite, - const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv ) - throw( DAVException ); + const ::rtl::OUString & rDestinationURI, + sal_Bool bOverwrite, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); void DESTROY( const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv ) - throw( DAVException ); + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); + // set new lock. void - LOCK( const com::sun::star::ucb::Lock & rLock, - const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv ) - throw( DAVException ); + LOCK( com::sun::star::ucb::Lock & inLock, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( DAVException ); + + // refresh existing lock. + sal_Int64 + LOCK( sal_Int64 nTimeout, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); void - UNLOCK( const com::sun::star::ucb::Lock & rLock, - const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv ) - throw( DAVException ); + UNLOCK( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw ( DAVException ); void - ABORT() - throw( DAVException ); + abort() + throw ( DAVException ); // helper - static void getUserRequestHeaders( - const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv, - const rtl::OUString & rURI, - const rtl::OUString & rMethod, - DAVRequestHeaders & rRequestHeaders ); + static void + getUserRequestHeaders( + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment > & xEnv, + const rtl::OUString & rURI, + const rtl::OUString & rMethod, + DAVRequestHeaders & rRequestHeaders ); private: const rtl::OUString & getRequestURI() const; diff --git a/ucb/source/ucp/webdav/DAVSession.hxx b/ucb/source/ucp/webdav/DAVSession.hxx index b6de1c5b10ad..00b0b75e2a3c 100644 --- a/ucb/source/ucp/webdav/DAVSession.hxx +++ b/ucb/source/ucp/webdav/DAVSession.hxx @@ -42,7 +42,9 @@ #include "DAVTypes.hxx" #include "DAVRequestEnvironment.hxx" - +namespace com { namespace sun { namespace star { namespace ucb { + struct Lock; +} } } } namespace webdav_ucp { @@ -73,28 +75,28 @@ public: // DAV methods // - virtual void OPTIONS( const ::rtl::OUString & inPath, + virtual void OPTIONS( const ::rtl::OUString & inPath, DAVCapabilities & outCapabilities, const DAVRequestEnvironment & rEnv ) throw( DAVException ) = 0; // allprop & named - virtual void PROPFIND( const ::rtl::OUString & inPath, - const Depth inDepth, + virtual void PROPFIND( const ::rtl::OUString & inPath, + const Depth inDepth, const std::vector< ::rtl::OUString > & inPropertyNames, - std::vector< DAVResource > & ioResources, + std::vector< DAVResource > & ioResources, const DAVRequestEnvironment & rEnv ) throw( DAVException ) = 0; // propnames - virtual void PROPFIND( const ::rtl::OUString & inPath, - const Depth inDepth, + virtual void PROPFIND( const ::rtl::OUString & inPath, + const Depth inDepth, std::vector< DAVResourceInfo > & ioResInfo, const DAVRequestEnvironment & rEnv ) throw( DAVException ) = 0; - virtual void PROPPATCH( const ::rtl::OUString & inPath, - const std::vector< ProppatchValue > & inValues, + virtual void PROPPATCH( const ::rtl::OUString & inPath, + const std::vector< ProppatchValue > & inValues, const DAVRequestEnvironment & rEnv ) throw( DAVException ) = 0; @@ -105,87 +107,95 @@ public: throw( DAVException ) = 0; virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > - GET( const ::rtl::OUString & inPath, - const DAVRequestEnvironment & rEnv ) + GET( const ::rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) throw( DAVException ) = 0; - virtual void GET( const ::rtl::OUString & inPath, - com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& o, - const DAVRequestEnvironment & rEnv ) + virtual void GET( const ::rtl::OUString & inPath, + com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream >& o, + const DAVRequestEnvironment & rEnv ) throw( DAVException ) = 0; virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > - GET( const ::rtl::OUString & inPath, - const std::vector< ::rtl::OUString > & inHeaderNames, - DAVResource & ioResource, - const DAVRequestEnvironment & rEnv ) + GET( const ::rtl::OUString & inPath, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + const DAVRequestEnvironment & rEnv ) throw( DAVException ) = 0; - virtual void GET( const ::rtl::OUString & inPath, - com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& o, - const std::vector< ::rtl::OUString > & inHeaderNames, - DAVResource & ioResource, - const DAVRequestEnvironment & rEnv ) + virtual void + GET( const ::rtl::OUString & inPath, + com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& o, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + const DAVRequestEnvironment & rEnv ) throw( DAVException ) = 0; - virtual void PUT( const ::rtl::OUString & inPath, - const com::sun::star::uno::Reference< - com::sun::star::io::XInputStream >& s, - const DAVRequestEnvironment & rEnv ) - throw( DAVException ) = 0; - - virtual void ABORT() + virtual void PUT( const ::rtl::OUString & inPath, + const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream >& s, + const DAVRequestEnvironment & rEnv ) throw( DAVException ) = 0; virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > - POST( const rtl::OUString & inPath, - const rtl::OUString & rContentType, - const rtl::OUString & rReferer, - const com::sun::star::uno::Reference< - com::sun::star::io::XInputStream > & inInputStream, - const DAVRequestEnvironment & rEnv ) + POST( const rtl::OUString & inPath, + const rtl::OUString & rContentType, + const rtl::OUString & rReferer, + const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > & inInputStream, + const DAVRequestEnvironment & rEnv ) throw ( DAVException ) = 0; virtual void POST( const rtl::OUString & inPath, const rtl::OUString & rContentType, const rtl::OUString & rReferer, const com::sun::star::uno::Reference< - com::sun::star::io::XInputStream > & inInputStream, + com::sun::star::io::XInputStream > & inInputStream, com::sun::star::uno::Reference< - com::sun::star::io::XOutputStream > & oOutputStream, + com::sun::star::io::XOutputStream > & oOutputStream, const DAVRequestEnvironment & rEnv ) throw ( DAVException ) = 0; - virtual void MKCOL( const ::rtl::OUString & inPath, - const DAVRequestEnvironment & rEnv ) + virtual void MKCOL( const ::rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) throw( DAVException ) = 0; - virtual void COPY( const ::rtl::OUString & inSource, - const ::rtl::OUString & inDestination, - const DAVRequestEnvironment & rEnv, - sal_Bool inOverwrite = false ) + virtual void COPY( const ::rtl::OUString & inSource, + const ::rtl::OUString & inDestination, + const DAVRequestEnvironment & rEnv, + sal_Bool inOverwrite = false ) throw( DAVException ) = 0; - virtual void MOVE( const ::rtl::OUString & inSource, - const ::rtl::OUString & inDestination, - const DAVRequestEnvironment & rEnv, - sal_Bool inOverwrite = false ) + virtual void MOVE( const ::rtl::OUString & inSource, + const ::rtl::OUString & inDestination, + const DAVRequestEnvironment & rEnv, + sal_Bool inOverwrite = false ) throw( DAVException ) = 0; - virtual void DESTROY( const ::rtl::OUString & inPath, - const DAVRequestEnvironment & rEnv ) + virtual void DESTROY( const ::rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) throw( DAVException ) = 0; - // Note: Uncomment the following if locking support is required - /* - virtual void LOCK ( const Lock & inLock, - const DAVRequestEnvironment & rEnv ) - throw( DAVException ) = 0; + // set new lock. + virtual void LOCK( const ::rtl::OUString & inPath, + com::sun::star::ucb::Lock & inLock, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) = 0; - virtual void UNLOCK ( const Lock & inLock, - const DAVRequestEnvironment & rEnv ) + // refresh existing lock. + virtual sal_Int64 LOCK( const ::rtl::OUString & inPath, + sal_Int64 nTimeout, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) = 0; + + virtual void UNLOCK( const ::rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) = 0; + + virtual void abort() throw( DAVException ) = 0; - */ + protected: rtl::Reference< DAVSessionFactory > m_xFactory; @@ -210,4 +220,3 @@ private: } // namespace webdav_ucp #endif // _DAVSESSION_HXX_ - diff --git a/ucb/source/ucp/webdav/LinkSequence.cxx b/ucb/source/ucp/webdav/LinkSequence.cxx index c9865cb5b8c2..fad89d375975 100644 --- a/ucb/source/ucp/webdav/LinkSequence.cxx +++ b/ucb/source/ucp/webdav/LinkSequence.cxx @@ -64,12 +64,11 @@ struct LinkSequenceParseContext extern "C" int LinkSequence_startelement_callback( void *, int parent, - const char *nspace, + const char * /*nspace*/, const char *name, const char ** ) { - if ( ( name != 0 ) && - ( ( nspace == 0 ) || ( strcmp( nspace, "" ) == 0 ) ) ) + if ( name != 0 ) { switch ( parent ) { @@ -192,7 +191,7 @@ bool LinkSequence::createFromXML( const rtl::OString & rInData, rOutData[ nCount - 1 ] = *aCtx.pLink; } - nStart = nEnd + TOKEN_LENGTH + 1; + nStart = nEnd + TOKEN_LENGTH; nEnd = rInData.indexOf( "</link>", nStart ); } @@ -215,11 +214,11 @@ bool LinkSequence::toXML( const uno::Sequence< ucb::Link > & rInData, for ( sal_Int32 n = 0; n < nCount; ++n ) { - rOutData += aPre; - rOutData += rInData[ n ].Source; - rOutData += aMid; - rOutData += rInData[ n ].Destination; - rOutData += aEnd; + rOutData += aPre; + rOutData += rInData[ n ].Source; + rOutData += aMid; + rOutData += rInData[ n ].Destination; + rOutData += aEnd; } return true; } diff --git a/ucb/source/ucp/webdav/LockEntrySequence.cxx b/ucb/source/ucp/webdav/LockEntrySequence.cxx index 353ff6f875d7..50600e0ad0a1 100644 --- a/ucb/source/ucp/webdav/LockEntrySequence.cxx +++ b/ucb/source/ucp/webdav/LockEntrySequence.cxx @@ -64,12 +64,11 @@ struct LockEntrySequenceParseContext extern "C" int LockEntrySequence_startelement_callback( void *, int parent, - const char *nspace, + const char * /*nspace*/, const char *name, const char ** ) { - if ( ( name != 0 ) && - ( ( nspace == 0 ) || ( strcmp( nspace, "" ) == 0 ) ) ) + if ( name != 0 ) { switch ( parent ) { @@ -83,6 +82,31 @@ extern "C" int LockEntrySequence_startelement_callback( return STATE_LOCKSCOPE; else if ( strcmp( name, "locktype" ) == 0 ) return STATE_LOCKTYPE; + +#define IIS_BUGS_WORKAROUND + +#ifdef IIS_BUGS_WORKAROUND + /* IIS (6) returns XML violating RFC 4918 + for DAV:supportedlock property value. + + <lockentry> + <write></write> + <shared></shared> + </lockentry> + <lockentry> + <write></write> + <exclusive></exclusive> + </lockentry> + + Bother... + */ + else if ( strcmp( name, "exclusive" ) == 0 ) + return STATE_EXCLUSIVE; + else if ( strcmp( name, "shared" ) == 0 ) + return STATE_SHARED; + else if ( strcmp( name, "write" ) == 0 ) + return STATE_WRITE; +#endif break; case STATE_LOCKSCOPE: @@ -165,7 +189,7 @@ extern "C" int LockEntrySequence_endelement_callback( // static bool LockEntrySequence::createFromXML( const rtl::OString & rInData, uno::Sequence< - ucb::LockEntry > & rOutData ) + ucb::LockEntry > & rOutData ) { const sal_Int32 TOKEN_LENGTH = 12; // </lockentry> bool success = true; @@ -191,8 +215,8 @@ bool LockEntrySequence::createFromXML( const rtl::OString & rInData, &aCtx ); ne_xml_parse( parser, - rInData.getStr() + nStart, - nEnd - nStart + TOKEN_LENGTH ); + rInData.getStr() + nStart, + nEnd - nStart + TOKEN_LENGTH ); #if NEON_VERSION >= 0x0250 success = !ne_xml_failed( parser ); @@ -214,7 +238,7 @@ bool LockEntrySequence::createFromXML( const rtl::OString & rInData, rOutData[ nCount - 1 ] = *aCtx.pEntry; } - nStart = nEnd + TOKEN_LENGTH + 1; + nStart = nEnd + TOKEN_LENGTH; nEnd = rInData.indexOf( "</lockentry>", nStart ); } diff --git a/ucb/source/ucp/webdav/LockSequence.cxx b/ucb/source/ucp/webdav/LockSequence.cxx index f34ede38d40e..e55de62e5552 100644 --- a/ucb/source/ucp/webdav/LockSequence.cxx +++ b/ucb/source/ucp/webdav/LockSequence.cxx @@ -74,12 +74,11 @@ struct LockSequenceParseContext extern "C" int LockSequence_startelement_callback( void *, int parent, - const char *nspace, + const char * /*nspace*/, const char *name, const char ** ) { - if ( ( name != 0 ) && - ( ( nspace == 0 ) || ( strcmp( nspace, "" ) == 0 ) ) ) + if ( name != 0 ) { switch ( parent ) { @@ -347,7 +346,7 @@ bool LockSequence::createFromXML( const rtl::OString & rInData, rOutData[ nCount - 1 ] = *aCtx.pLock; } - nStart = nEnd + TOKEN_LENGTH + 1; + nStart = nEnd + TOKEN_LENGTH; nEnd = rInData.indexOf( "</activelock>", nStart ); } diff --git a/ucb/source/ucp/webdav/NeonLockStore.cxx b/ucb/source/ucp/webdav/NeonLockStore.cxx new file mode 100644 index 000000000000..9d151bc2ba30 --- /dev/null +++ b/ucb/source/ucp/webdav/NeonLockStore.cxx @@ -0,0 +1,248 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: $ + * $Revision: $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_ucb.hxx" + +#include <ne_locks.h> +#include <ne_uri.h> +#include "rtl/ustring.hxx" +#include "osl/time.h" +#include "osl/thread.hxx" +#include "NeonSession.hxx" +#include "NeonLockStore.hxx" + +using namespace webdav_ucp; + +namespace webdav_ucp { + +class TickerThread : public osl::Thread +{ + bool m_bFinish; + NeonLockStore & m_rLockStore; + +public: + + TickerThread( NeonLockStore & rLockStore ) + : osl::Thread(), m_bFinish( false ), m_rLockStore( rLockStore ) {} + + void finish() { m_bFinish = true; } + +protected: + + virtual void SAL_CALL run(); +}; + +} // namespace webdav_ucp + +// ------------------------------------------------------------------- +void TickerThread::run() +{ + OSL_TRACE( "TickerThread: start." ); + + // we have to go through the loop more often to be able to finish ~quickly + const int nNth = 25; + + int nCount = nNth; + while ( !m_bFinish ) + { + if ( nCount-- <= 0 ) + { + m_rLockStore.refreshLocks(); + nCount = nNth; + } + + TimeValue aTV; + aTV.Seconds = 0; + aTV.Nanosec = 1000000000 / nNth; + wait( aTV ); + } + + OSL_TRACE( "TickerThread: stop." ); +} + +// ------------------------------------------------------------------- +NeonLockStore::NeonLockStore() + : m_pNeonLockStore( ne_lockstore_create() ), + m_pTickerThread( 0 ) +{ + OSL_ENSURE( m_pNeonLockStore, "Unable to create neon lock store!" ); +} + +// ------------------------------------------------------------------- +NeonLockStore::~NeonLockStore() +{ + stopTicker(); + + // release active locks, if any. + OSL_ENSURE( m_aLockInfoMap.size() == 0, + "NeonLockStore::~NeonLockStore - Releasing active locks!" ); + + LockInfoMap::const_iterator it( m_aLockInfoMap.begin() ); + const LockInfoMap::const_iterator end( m_aLockInfoMap.end() ); + while ( it != end ) + { + NeonLock * pLock = (*it).first; + (*it).second.xSession->UNLOCK( pLock ); + + ne_lockstore_remove( m_pNeonLockStore, pLock ); + ne_lock_destroy( pLock ); + + ++it; + } + + ne_lockstore_destroy( m_pNeonLockStore ); +} + +// ------------------------------------------------------------------- +void NeonLockStore::startTicker() +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pTickerThread ) + { + m_pTickerThread = new TickerThread( *this ); + m_pTickerThread->create(); + } +} + +// ------------------------------------------------------------------- +void NeonLockStore::stopTicker() +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( m_pTickerThread ) + { + m_pTickerThread->finish(); + m_pTickerThread->join(); + delete m_pTickerThread; + m_pTickerThread = 0; + } +} + +// ------------------------------------------------------------------- +void NeonLockStore::registerSession( HttpSession * pHttpSession ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + ne_lockstore_register( m_pNeonLockStore, pHttpSession ); +} + +// ------------------------------------------------------------------- +NeonLock * NeonLockStore::findByUri( rtl::OUString const & rUri ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + ne_uri aUri; + ne_uri_parse( rtl::OUStringToOString( + rUri, RTL_TEXTENCODING_UTF8 ).getStr(), &aUri ); + return ne_lockstore_findbyuri( m_pNeonLockStore, &aUri ); +} + +// ------------------------------------------------------------------- +void NeonLockStore::addLock( NeonLock * pLock, + rtl::Reference< NeonSession > const & xSession, + sal_Int32 nLastChanceToSendRefreshRequest ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + ne_lockstore_add( m_pNeonLockStore, pLock ); + m_aLockInfoMap[ pLock ] + = LockInfo( xSession, nLastChanceToSendRefreshRequest ); + + startTicker(); +} + +// ------------------------------------------------------------------- +void NeonLockStore::updateLock( NeonLock * pLock, + sal_Int32 nLastChanceToSendRefreshRequest ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + LockInfoMap::iterator it( m_aLockInfoMap.find( pLock ) ); + OSL_ENSURE( it != m_aLockInfoMap.end(), + "NeonLockStore::updateLock: lock not found!" ); + + if ( it != m_aLockInfoMap.end() ) + { + (*it).second.nLastChanceToSendRefreshRequest + = nLastChanceToSendRefreshRequest; + } +} + +// ------------------------------------------------------------------- +void NeonLockStore::removeLock( NeonLock * pLock ) +{ + osl::MutexGuard aGuard( m_aMutex ); + + m_aLockInfoMap.erase( pLock ); + ne_lockstore_remove( m_pNeonLockStore, pLock ); + + if ( m_aLockInfoMap.size() == 0 ) + stopTicker(); +} + +// ------------------------------------------------------------------- +void NeonLockStore::refreshLocks() +{ + osl::MutexGuard aGuard( m_aMutex ); + + LockInfoMap::iterator it( m_aLockInfoMap.begin() ); + const LockInfoMap::const_iterator end( m_aLockInfoMap.end() ); + while ( it != end ) + { + LockInfo & rInfo = (*it).second; + if ( rInfo.nLastChanceToSendRefreshRequest != -1 ) + { + // 30 seconds or less remaining until lock expires? + TimeValue t1; + osl_getSystemTime( &t1 ); + if ( rInfo.nLastChanceToSendRefreshRequest - 30 + <= sal_Int32( t1.Seconds ) ) + { + // refresh the lock. + sal_Int32 nlastChanceToSendRefreshRequest = -1; + if ( rInfo.xSession->LOCK( + (*it).first, + /* out param */ nlastChanceToSendRefreshRequest ) ) + { + rInfo.nLastChanceToSendRefreshRequest + = nlastChanceToSendRefreshRequest; + } + else + { + // refresh failed. stop auto-refresh. + rInfo.nLastChanceToSendRefreshRequest = -1; + } + } + } + ++it; + } +} diff --git a/ucb/source/ucp/webdav/NeonLockStore.hxx b/ucb/source/ucp/webdav/NeonLockStore.hxx new file mode 100644 index 000000000000..b00361d55eff --- /dev/null +++ b/ucb/source/ucp/webdav/NeonLockStore.hxx @@ -0,0 +1,105 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: $ + * $Revision: $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef INCLUDED_NEONLOCKSTORE_HXX +#define INCLUDED_NEONLOCKSTORE_HXX + +#include <map> +#include "ne_locks.h" +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" +#include "NeonTypes.hxx" + +namespace webdav_ucp +{ + +class TickerThread; +class NeonSession; + +struct ltptr +{ + bool operator()( const NeonLock * p1, const NeonLock * p2 ) const + { + return p1 < p2; + } +}; + +typedef struct _LockInfo +{ + rtl::Reference< NeonSession > xSession; + sal_Int32 nLastChanceToSendRefreshRequest; + + _LockInfo() + : nLastChanceToSendRefreshRequest( -1 ) {} + + _LockInfo( rtl::Reference< NeonSession > const & _xSession, + sal_Int32 _nLastChanceToSendRefreshRequest ) + : xSession( _xSession ), + nLastChanceToSendRefreshRequest( _nLastChanceToSendRefreshRequest ) {} + +} LockInfo; + +typedef std::map< NeonLock *, LockInfo, ltptr > LockInfoMap; + +class NeonLockStore +{ + osl::Mutex m_aMutex; + ne_lock_store * m_pNeonLockStore; + TickerThread * m_pTickerThread; + LockInfoMap m_aLockInfoMap; + +public: + NeonLockStore(); + ~NeonLockStore(); + + void registerSession( HttpSession * pHttpSession ); + + NeonLock * findByUri( rtl::OUString const & rUri ); + + void addLock( NeonLock * pLock, + rtl::Reference< NeonSession > const & xSession, + // time in seconds since Jan 1 1970 + // -1: infinite lock, no refresh + sal_Int32 nLastChanceToSendRefreshRequest ); + + void updateLock( NeonLock * pLock, + sal_Int32 nLastChanceToSendRefreshRequest ); + + void removeLock( NeonLock * pLock ); + + void refreshLocks(); + +private: + void startTicker(); + void stopTicker(); +}; + +} // namespace webdav_ucp + +#endif // INCLUDED_NEONLOCKSTORE_HXX diff --git a/ucb/source/ucp/webdav/NeonPropFindRequest.cxx b/ucb/source/ucp/webdav/NeonPropFindRequest.cxx index 6171d3fa0bfc..2a1703336bdf 100644 --- a/ucb/source/ucp/webdav/NeonPropFindRequest.cxx +++ b/ucb/source/ucp/webdav/NeonPropFindRequest.cxx @@ -30,14 +30,14 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_ucb.hxx" -#include <osl/diagnose.h> + +#include "osl/diagnose.h" +#include "rtl/strbuf.hxx" #include "NeonTypes.hxx" #include "DAVException.hxx" #include "DAVProperties.hxx" #include "NeonPropFindRequest.hxx" -#ifndef _LINKSEQUENCE_HXX_ #include "LinkSequence.hxx" -#endif #include "LockSequence.hxx" #include "LockEntrySequence.hxx" #include "UCBDeadPropertyValue.hxx" @@ -49,6 +49,40 @@ using namespace std; using namespace webdav_ucp; // ------------------------------------------------------------------- +namespace +{ + // strip "DAV:" namespace from XML snippets to avoid + // parser error (undeclared namespace) later on. + rtl::OString stripDavNamespace( const rtl::OString & in ) + { + const rtl::OString inXML( in.toAsciiLowerCase() ); + + rtl::OStringBuffer buf; + sal_Int32 start = 0; + sal_Int32 end = inXML.indexOf( "dav:" ); + while ( end != -1 ) + { + if ( inXML[ end - 1 ] == '<' || + inXML[ end - 1 ] == '/' ) + { + // copy from original buffer - preserve case. + buf.append( in.copy( start, end - start ) ); + } + else + { + // copy from original buffer - preserve case. + buf.append( in.copy( start, end - start + 4 ) ); + } + start = end + 4; + end = inXML.indexOf( "dav:", start ); + } + buf.append( inXML.copy( start ) ); + + return rtl::OString( buf.makeStringAndClear() ); + } +} + +// ------------------------------------------------------------------- extern "C" int NPFR_propfind_iter( void* userdata, const NeonPropName* pname, const char* value, @@ -57,9 +91,9 @@ extern "C" int NPFR_propfind_iter( void* userdata, /* HTTP Response Status Classes: - - 1: Informational - Request received, continuing process + - 1: Informational - Request received, continuing process - - 2: Success - The action was successfully received, + - 2: Success - The action was successfully received, understood, and accepted - 3: Redirection - Further action must be taken in order to @@ -79,18 +113,22 @@ extern "C" int NPFR_propfind_iter( void* userdata, DAVPropertyValue thePropertyValue; thePropertyValue.IsCaseSensitive = true; + OSL_ENSURE( pname->nspace, "NPFR_propfind_iter - No namespace!" ); + DAVProperties::createUCBPropName( pname->nspace, - pname->name, - thePropertyValue.Name ); + pname->name, + thePropertyValue.Name ); bool bHasValue = false; if ( DAVProperties::isUCBDeadProperty( *pname ) ) { // DAV dead property added by WebDAV UCP? if ( UCBDeadPropertyValue::createFromXML( - value, thePropertyValue.Value ) ) + value, thePropertyValue.Value ) ) + { OSL_ENSURE( thePropertyValue.Value.hasValue(), - "NeonPropFindRequest::propfind_iter - No value!" ); + "NPFR_propfind_iter - No value!" ); bHasValue = true; + } } if ( !bHasValue ) @@ -102,13 +140,9 @@ extern "C" int NPFR_propfind_iter( void* userdata, aValue = aValue.trim(); // #107358# remove leading/trailing spaces if ( aValue.getLength() ) { - aValue = aValue.toAsciiLowerCase(); - if ( - ( aValue.compareTo( - RTL_CONSTASCII_STRINGPARAM( "<collection" ) ) == 0 ) || - ( aValue.compareTo( - RTL_CONSTASCII_STRINGPARAM( "<dav:collection" ) ) == 0 ) - ) + aValue = stripDavNamespace( aValue ).toAsciiLowerCase(); + if ( aValue.compareTo( + RTL_CONSTASCII_STRINGPARAM( "<collection" ) ) == 0 ) { thePropertyValue.Value <<= OUString::createFromAscii( "collection" ); @@ -125,20 +159,23 @@ extern "C" int NPFR_propfind_iter( void* userdata, pname->name, "supportedlock" ) == 0 ) { Sequence< LockEntry > aEntries; - LockEntrySequence::createFromXML( value, aEntries ); + LockEntrySequence::createFromXML( + stripDavNamespace( value ), aEntries ); thePropertyValue.Value <<= aEntries; } else if ( rtl_str_compareIgnoreAsciiCase( pname->name, "lockdiscovery" ) == 0 ) { Sequence< Lock > aLocks; - LockSequence::createFromXML( value, aLocks ); + LockSequence::createFromXML( + stripDavNamespace( value ), aLocks ); thePropertyValue.Value <<= aLocks; } else if ( rtl_str_compareIgnoreAsciiCase( pname->name, "source" ) == 0 ) { Sequence< Link > aLinks; - LinkSequence::createFromXML( value, aLinks ); + LinkSequence::createFromXML( + stripDavNamespace( value ), aLinks ); thePropertyValue.Value <<= aLinks; } else @@ -168,10 +205,10 @@ extern "C" void NPFR_propfind_results( void* userdata, #if NEON_VERSION >= 0x0260 DAVResource theResource( - OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) ); + OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) ); #else DAVResource theResource( - OStringToOUString( href, RTL_TEXTENCODING_UTF8 ) ); + OStringToOUString( href, RTL_TEXTENCODING_UTF8 ) ); #endif ne_propset_iterate( set, NPFR_propfind_iter, &theResource ); @@ -210,10 +247,10 @@ extern "C" void NPFR_propnames_results( void* userdata, // Create entry for the resource. #if NEON_VERSION >= 0x0260 DAVResourceInfo theResource( - OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) ); + OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) ); #else DAVResourceInfo theResource( - OStringToOUString( href, RTL_TEXTENCODING_UTF8 ) ); + OStringToOUString( href, RTL_TEXTENCODING_UTF8 ) ); #endif // Fill entry. @@ -247,7 +284,7 @@ NeonPropFindRequest::NeonPropFindRequest( HttpSession* inSession, { // Split fullname into namespace and name! DAVProperties::createNeonPropName( - inPropNames[ theIndex ], thePropNames[ theIndex ] ); + inPropNames[ theIndex ], thePropNames[ theIndex ] ); } thePropNames[ theIndex ].nspace = NULL; thePropNames[ theIndex ].name = NULL; @@ -288,7 +325,7 @@ NeonPropFindRequest::NeonPropFindRequest( HttpSession* inSession, NeonPropFindRequest::NeonPropFindRequest( HttpSession* inSession, const char* inPath, - const Depth inDepth, + const Depth inDepth, std::vector< DAVResourceInfo > & ioResInfo, int & nError ) { diff --git a/ucb/source/ucp/webdav/NeonSession.cxx b/ucb/source/ucp/webdav/NeonSession.cxx index 25126f619540..78f351f88f77 100644 --- a/ucb/source/ucp/webdav/NeonSession.cxx +++ b/ucb/source/ucp/webdav/NeonSession.cxx @@ -1,5 +1,4 @@ /************************************************************************* - * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2008 by Sun Microsystems, Inc. @@ -34,12 +33,14 @@ #include <hash_map> #include <vector> #include <string.h> +#include "osl/diagnose.h" +#include "osl/time.h" #include <rtl/string.h> #include <ne_socket.h> #include <ne_auth.h> #include <ne_redirect.h> -#include <ne_locks.h> #include <ne_ssl.h> +#include <ne_compress.h> #include "libxml/parser.h" #include "rtl/ustrbuf.hxx" #include "comphelper/sequence.hxx" @@ -62,6 +63,7 @@ #include <com/sun/star/security/CertificateContainer.hpp> #include <com/sun/star/security/XCertificateContainer.hpp> #include <com/sun/star/task/XMasterPasswordHandling.hpp> +#include <com/sun/star/ucb/Lock.hpp> #include <com/sun/star/xml/crypto/XSEInitializer.hpp> using namespace com::sun::star; @@ -119,10 +121,6 @@ typedef std::hash_map RequestDataMap; // ------------------------------------------------------------------- -// static members! -bool NeonSession::m_bGlobalsInited = false; -osl::Mutex NeonSession::m_aGlobalMutex; -// ------------------------------------------------------------------- // Helper fuction // ------------------------------------------------------------------- static sal_uInt16 makeStatusCode( const rtl::OUString & rStatusText ) @@ -197,14 +195,14 @@ extern "C" void NeonSession_ResponseBlockReader(void * inUserData, const char * inBuf, size_t inLen ) { - // neon calls this function with (inLen == 0)... + // neon sometimes calls this function with (inLen == 0)... if ( inLen > 0 ) { NeonRequestContext * pCtx = static_cast< NeonRequestContext * >( inUserData ); rtl::Reference< NeonInputStream > xInputStream( - pCtx->xInputStream); + pCtx->xInputStream ); if ( xInputStream.is() ) xInputStream->AddToStream( inBuf, inLen ); @@ -327,10 +325,11 @@ extern "C" int NeonSession_NeonAuth( void * inUserData, bool bCanUseSystemCreds = false; #ifdef NE_FEATURE_SSPI - bCanUseSystemCreds = (attempt == 0) && // avoid endless loops - ne_has_support( NE_FEATURE_SSPI ) && // Windows-only feature. - ( ( ne_strcasecmp( inAuthProtocol, "NTLM" ) == 0 ) || - ( ne_strcasecmp( inAuthProtocol, "Negotiate" ) == 0 ) ); + bCanUseSystemCreds + = (attempt == 0) && // avoid endless loops + ne_has_support( NE_FEATURE_SSPI ) && // Windows-only feature. + ( ( ne_strcasecmp( inAuthProtocol, "NTLM" ) == 0 ) || + ( ne_strcasecmp( inAuthProtocol, "Negotiate" ) == 0 ) ); #endif // #i97003# (tkr): Ask XMasterPasswordHandling if we should store the @@ -342,7 +341,7 @@ extern "C" int NeonSession_NeonAuth( void * inUserData, uno::Reference< task::XMasterPasswordHandling >( theSession->getMSF()->createInstance( rtl::OUString::createFromAscii( - "com.sun.star.task.PasswordContainer" )), + "com.sun.star.task.PasswordContainer" ) ), uno::UNO_QUERY ); } catch ( uno::Exception const & ) @@ -406,7 +405,7 @@ namespace { } return sPart; } -} +} // namespace // ------------------------------------------------------------------- extern "C" int NeonSession_CertificationNotify( void *userdata, @@ -445,7 +444,7 @@ extern "C" int NeonSession_CertificationNotify( void *userdata, pSession->getHostName(), cert_subject ) ); if ( certificateContainer != security::CertificateContainerStatus_NOCERT ) - return + return certificateContainer == security::CertificateContainerStatus_TRUSTED ? 0 : 1; @@ -476,7 +475,7 @@ extern "C" int NeonSession_CertificationNotify( void *userdata, rtl::OString sEECertB64( eeCertB64 ); - uno::Reference< com::sun::star::security::XCertificate > xEECert( + uno::Reference< security::XCertificate > xEECert( xSecurityEnv->createCertificateFromAscii( rtl::OStringToOUString( sEECertB64, RTL_TEXTENCODING_ASCII_US ) ) ); @@ -617,36 +616,41 @@ extern "C" void NeonSession_PreSendRequest( ne_request * req, } } - const DAVRequestHeaders & rHeaders - = pSession->getRequestEnvironment().m_aRequestHeaders; + const DAVRequestHeaders & rHeaders + = pSession->getRequestEnvironment().m_aRequestHeaders; - DAVRequestHeaders::const_iterator it1( rHeaders.begin() ); - const DAVRequestHeaders::const_iterator end1( rHeaders.end() ); + DAVRequestHeaders::const_iterator it1( rHeaders.begin() ); + const DAVRequestHeaders::const_iterator end1( rHeaders.end() ); - while ( it1 != end1 ) - { - rtl::OString aHeader - = rtl::OUStringToOString( (*it1).first, - RTL_TEXTENCODING_UTF8 ); - rtl::OString aValue - = rtl::OUStringToOString( (*it1).second, - RTL_TEXTENCODING_UTF8 ); - ne_buffer_concat( headers, aHeader.getStr(), ": ", - aValue.getStr(), EOL, NULL ); - - ++it1; + while ( it1 != end1 ) + { + rtl::OString aHeader + = rtl::OUStringToOString( (*it1).first, + RTL_TEXTENCODING_UTF8 ); + rtl::OString aValue + = rtl::OUStringToOString( (*it1).second, + RTL_TEXTENCODING_UTF8 ); + ne_buffer_concat( headers, aHeader.getStr(), ": ", + aValue.getStr(), EOL, NULL ); + + ++it1; + } } } -} // namespace +// ------------------------------------------------------------------- +// static members! +bool NeonSession::m_bGlobalsInited = false; +osl::Mutex NeonSession::m_aGlobalMutex; +NeonLockStore NeonSession::m_aNeonLockStore; // ------------------------------------------------------------------- // Constructor // ------------------------------------------------------------------- NeonSession::NeonSession( - const rtl::Reference< DAVSessionFactory > & rSessionFactory, - const rtl::OUString& inUri, - const ucbhelper::InternetProxyDecider & rProxyDecider ) + const rtl::Reference< DAVSessionFactory > & rSessionFactory, + const rtl::OUString& inUri, + const ucbhelper::InternetProxyDecider & rProxyDecider ) throw ( DAVException ) : DAVSession( rSessionFactory ), m_pHttpSession( 0 ), @@ -657,8 +661,6 @@ NeonSession::NeonSession( m_aScheme = theUri.GetScheme(); m_aHostName = theUri.GetHost(); m_nPort = theUri.GetPort(); - -// Init(); } // ------------------------------------------------------------------- @@ -670,17 +672,17 @@ NeonSession::~NeonSession( ) { ne_session_destroy( m_pHttpSession ); m_pHttpSession = 0; - // Note: Uncomment the following if locking support is required - /* - if ( mNeonLockSession != NULL ) - { - ne_lock_unregister( mNeonLockSession ); - mNeonLockSession = NULL; - } - */ } + delete static_cast< RequestDataMap * >( m_pRequestData ); +} - delete static_cast<RequestDataMap*>(m_pRequestData); +// ------------------------------------------------------------------- +void NeonSession::Init( const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + m_aEnv = rEnv; + Init(); } // ------------------------------------------------------------------- @@ -693,7 +695,7 @@ void NeonSession::Init() if ( m_pHttpSession == 0 ) { - // Ensure that Neon sockets are initialize + // Ensure that Neon sockets are initialized // --> tkr #151111# crashed if copy and pasted pictures from the internet // ne_sock_init() was executed by two threads at the same time. @@ -705,9 +707,23 @@ void NeonSession::Init() throw DAVException( DAVException::DAV_SESSION_CREATE, NeonUri::makeConnectionEndPointString( m_aHostName, m_nPort ) ); + // #122205# - libxml2 needs to be initialized once if used by // multithreaded programs like OOo. xmlInitParser(); +#if 0 + // for more debug flags see ne_utils.h; NE_DEBUGGING must be defined + // while compiling neon in order to actually activate neon debug + // output. + ne_debug_init( stderr, NE_DBG_FLUSH + | NE_DBG_HTTP + // | NE_DBG_HTTPBODY + // | NE_DBG_HTTPAUTH + // | NE_DBG_XML + // | NE_DBG_XMLPARSE + // | NE_DBG_LOCKS + ); +#endif m_bGlobalsInited = true; } @@ -747,30 +763,29 @@ void NeonSession::Init() // to the session m_pHttpSession = ne_session_create( - rtl::OUStringToOString( m_aScheme, - RTL_TEXTENCODING_UTF8 ).getStr(), - /* theUri.GetUserInfo(), - @@@ for FTP via HTTP proxy, but not supported by Neon */ - rtl::OUStringToOString( m_aHostName, - RTL_TEXTENCODING_UTF8 ).getStr(), - m_nPort ); + rtl::OUStringToOString( m_aScheme, + RTL_TEXTENCODING_UTF8 ).getStr(), + /* theUri.GetUserInfo(), + @@@ for FTP via HTTP proxy, but not supported by Neon */ + rtl::OUStringToOString( m_aHostName, + RTL_TEXTENCODING_UTF8 ).getStr(), + m_nPort ); if ( m_pHttpSession == 0 ) throw DAVException( DAVException::DAV_SESSION_CREATE, NeonUri::makeConnectionEndPointString( m_aHostName, m_nPort ) ); - if (m_aScheme.equalsIgnoreAsciiCase( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "https" ) ) ) ) - { - - // Get all trusted certificates from key store - - + // Register the session with the lock store + m_aNeonLockStore.registerSession( m_pHttpSession ); + if ( m_aScheme.equalsIgnoreAsciiCase( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "https" ) ) ) ) + { // Set a failure callback for certificate check - ne_ssl_set_verify( m_pHttpSession, NeonSession_CertificationNotify, this); - } + ne_ssl_set_verify( + m_pHttpSession, NeonSession_CertificationNotify, this); + } // Add hooks (i.e. for adding additional headers to the request) @@ -815,27 +830,20 @@ void NeonSession::Init() if ( m_aProxyName.getLength() ) { ne_session_proxy( m_pHttpSession, - rtl::OUStringToOString( m_aProxyName, - RTL_TEXTENCODING_UTF8 ) - .getStr(), + rtl::OUStringToOString( + m_aProxyName, + RTL_TEXTENCODING_UTF8 ).getStr(), m_nProxyPort ); } - // Note: Uncomment the following if locking support is required - /* - mNeonLockSession = ne_lock_register( m_pHttpSession ); - - if ( mNeonLockSession == NULL ) - throw DAVException( DAVException::DAV_SESSION_CREATE, - theUri::makeConnectionEndPointString() ); - */ - // Register for redirects. ne_redirect_register( m_pHttpSession ); // authentication callbacks. - ne_add_server_auth( m_pHttpSession, NE_AUTH_ALL, NeonSession_NeonAuth, this ); - ne_add_proxy_auth ( m_pHttpSession, NE_AUTH_ALL, NeonSession_NeonAuth, this ); + ne_add_server_auth( + m_pHttpSession, NE_AUTH_ALL, NeonSession_NeonAuth, this ); + ne_add_proxy_auth( + m_pHttpSession, NE_AUTH_ALL, NeonSession_NeonAuth, this ); } } @@ -870,15 +878,13 @@ sal_Bool NeonSession::UsesProxy() // OPTIONS // ------------------------------------------------------------------- void NeonSession::OPTIONS( const rtl::OUString & inPath, - DAVCapabilities & outCapabilities, + DAVCapabilities & outCapabilities, const DAVRequestEnvironment & rEnv ) throw( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); HttpServerCapabilities servercaps; memset( &servercaps, 0, sizeof( servercaps ) ); @@ -887,7 +893,8 @@ void NeonSession::OPTIONS( const rtl::OUString & inPath, rtl::OUStringToOString( inPath, RTL_TEXTENCODING_UTF8 ), &servercaps ); - HandleError( theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); outCapabilities.class1 = !!servercaps.dav_class1; outCapabilities.class2 = !!servercaps.dav_class2; @@ -897,60 +904,58 @@ void NeonSession::OPTIONS( const rtl::OUString & inPath, // ------------------------------------------------------------------- // PROPFIND - allprop & named // ------------------------------------------------------------------- -void NeonSession::PROPFIND( const rtl::OUString & inPath, - const Depth inDepth, +void NeonSession::PROPFIND( const rtl::OUString & inPath, + const Depth inDepth, const std::vector< rtl::OUString > & inPropNames, - std::vector< DAVResource > & ioResources, + std::vector< DAVResource > & ioResources, const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); int theRetVal = NE_OK; NeonPropFindRequest theRequest( m_pHttpSession, rtl::OUStringToOString( inPath, RTL_TEXTENCODING_UTF8 ), - inDepth, - inPropNames, - ioResources, - theRetVal ); - HandleError( theRetVal ); + inDepth, + inPropNames, + ioResources, + theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- // PROPFIND - propnames // ------------------------------------------------------------------- -void NeonSession::PROPFIND( const rtl::OUString & inPath, - const Depth inDepth, - std::vector< DAVResourceInfo >& ioResInfo, +void NeonSession::PROPFIND( const rtl::OUString & inPath, + const Depth inDepth, + std::vector< DAVResourceInfo > & ioResInfo, const DAVRequestEnvironment & rEnv ) throw( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); int theRetVal = NE_OK; NeonPropFindRequest theRequest( m_pHttpSession, rtl::OUStringToOString( inPath, RTL_TEXTENCODING_UTF8 ), - inDepth, - ioResInfo, - theRetVal ); - HandleError( theRetVal ); + inDepth, + ioResInfo, + theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- // PROPPATCH // ------------------------------------------------------------------- -void NeonSession::PROPPATCH( const rtl::OUString & inPath, - const std::vector< ProppatchValue > & inValues, +void NeonSession::PROPPATCH( const rtl::OUString & inPath, + const std::vector< ProppatchValue > & inValues, const DAVRequestEnvironment & rEnv ) throw( DAVException ) { @@ -974,9 +979,10 @@ void NeonSession::PROPPATCH( const rtl::OUString & inPath, executable w ( #ifndef WIN32 ) All dead properties are of course writable. - */ + */ int theRetVal = NE_OK; + int n; // for the "for" loop // Generate the list of properties we want to set. @@ -1000,8 +1006,8 @@ void NeonSession::PROPPATCH( const rtl::OUString & inPath, if ( DAVProperties::isUCBDeadProperty( *pName ) ) { // DAV dead property added by WebDAV UCP? - if ( !UCBDeadPropertyValue::toXML( - rValue.value, aStringValue ) ) + if ( !UCBDeadPropertyValue::toXML( rValue.value, + aStringValue ) ) { // Error! pItems[ n ].value = 0; @@ -1015,7 +1021,7 @@ void NeonSession::PROPPATCH( const rtl::OUString & inPath, // complex properties... if ( rValue.name == DAVProperties::SOURCE ) { - uno::Sequence< ::com::sun::star::ucb::Link > aLinks; + uno::Sequence< ucb::Link > aLinks; if ( rValue.value >>= aLinks ) { LinkSequence::toXML( aLinks, aStringValue ); @@ -1055,9 +1061,7 @@ void NeonSession::PROPPATCH( const rtl::OUString & inPath, { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); pItems[ n ].name = 0; @@ -1076,7 +1080,7 @@ void NeonSession::PROPPATCH( const rtl::OUString & inPath, delete [] pItems; - HandleError( theRetVal ); + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- @@ -1090,9 +1094,7 @@ void NeonSession::HEAD( const ::rtl::OUString & inPath, { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); int theRetVal = NE_OK; NeonHeadRequest theRequest( m_pHttpSession, @@ -1100,7 +1102,8 @@ void NeonSession::HEAD( const ::rtl::OUString & inPath, inHeaderNames, ioResource, theRetVal ); - HandleError( theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- @@ -1108,14 +1111,12 @@ void NeonSession::HEAD( const ::rtl::OUString & inPath, // ------------------------------------------------------------------- uno::Reference< io::XInputStream > NeonSession::GET( const rtl::OUString & inPath, - const DAVRequestEnvironment & rEnv ) + const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); rtl::Reference< NeonInputStream > xInputStream( new NeonInputStream ); NeonRequestContext aCtx( xInputStream ); @@ -1125,23 +1126,23 @@ NeonSession::GET( const rtl::OUString & inPath, NeonSession_ResponseBlockReader, false, &aCtx ); - HandleError( theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); + return uno::Reference< io::XInputStream >( xInputStream.get() ); } // ------------------------------------------------------------------- // GET // ------------------------------------------------------------------- -void NeonSession::GET( const rtl::OUString & inPath, +void NeonSession::GET( const rtl::OUString & inPath, uno::Reference< io::XOutputStream > & ioOutputStream, const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); NeonRequestContext aCtx( ioOutputStream ); int theRetVal = GET( m_pHttpSession, @@ -1150,7 +1151,8 @@ void NeonSession::GET( const rtl::OUString & inPath, NeonSession_ResponseBlockWriter, false, &aCtx ); - HandleError( theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- @@ -1158,16 +1160,14 @@ void NeonSession::GET( const rtl::OUString & inPath, // ------------------------------------------------------------------- uno::Reference< io::XInputStream > NeonSession::GET( const rtl::OUString & inPath, - const std::vector< ::rtl::OUString > & inHeaderNames, - DAVResource & ioResource, - const DAVRequestEnvironment & rEnv ) + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); ioResource.uri = inPath; ioResource.properties.clear(); @@ -1180,7 +1180,9 @@ NeonSession::GET( const rtl::OUString & inPath, NeonSession_ResponseBlockReader, true, &aCtx ); - HandleError( theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); + return uno::Reference< io::XInputStream >( xInputStream.get() ); } @@ -1188,17 +1190,15 @@ NeonSession::GET( const rtl::OUString & inPath, // GET // ------------------------------------------------------------------- void NeonSession::GET( const rtl::OUString & inPath, - uno::Reference< io::XOutputStream > & ioOutputStream, - const std::vector< ::rtl::OUString > & inHeaderNames, - DAVResource & ioResource, - const DAVRequestEnvironment & rEnv ) + uno::Reference< io::XOutputStream > & ioOutputStream, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); ioResource.uri = inPath; ioResource.properties.clear(); @@ -1210,27 +1210,26 @@ void NeonSession::GET( const rtl::OUString & inPath, NeonSession_ResponseBlockWriter, true, &aCtx ); - HandleError( theRetVal ); + + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- // PUT // ------------------------------------------------------------------- -void NeonSession::PUT( const rtl::OUString & inPath, +void NeonSession::PUT( const rtl::OUString & inPath, const uno::Reference< io::XInputStream > & inInputStream, const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; - uno::Sequence< sal_Int8 > aDataToSend; if ( !getDataFromInputStream( inInputStream, aDataToSend, false ) ) throw DAVException( DAVException::DAV_INVALID_ARG ); + Init( rEnv ); + int theRetVal = PUT( m_pHttpSession, rtl::OUStringToOString( inPath, RTL_TEXTENCODING_UTF8 ), @@ -1238,7 +1237,7 @@ void NeonSession::PUT( const rtl::OUString & inPath, aDataToSend.getConstArray() ), aDataToSend.getLength() ); - HandleError( theRetVal ); + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- @@ -1246,10 +1245,10 @@ void NeonSession::PUT( const rtl::OUString & inPath, // ------------------------------------------------------------------- uno::Reference< io::XInputStream > NeonSession::POST( const rtl::OUString & inPath, - const rtl::OUString & rContentType, - const rtl::OUString & rReferer, - const uno::Reference< io::XInputStream > & inInputStream, - const DAVRequestEnvironment & rEnv ) + const rtl::OUString & rContentType, + const rtl::OUString & rReferer, + const uno::Reference< io::XInputStream > & inInputStream, + const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); @@ -1258,15 +1257,13 @@ NeonSession::POST( const rtl::OUString & inPath, if ( !getDataFromInputStream( inInputStream, aDataToSend, true ) ) throw DAVException( DAVException::DAV_INVALID_ARG ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); rtl::Reference< NeonInputStream > xInputStream( new NeonInputStream ); NeonRequestContext aCtx( xInputStream ); int theRetVal = POST( m_pHttpSession, rtl::OUStringToOString( - inPath, RTL_TEXTENCODING_UTF8 ), + inPath, RTL_TEXTENCODING_UTF8 ), reinterpret_cast< const char * >( aDataToSend.getConstArray() ), NeonSession_ResponseBlockReader, @@ -1274,7 +1271,8 @@ NeonSession::POST( const rtl::OUString & inPath, rContentType, rReferer ); - HandleError( theRetVal ); + HandleError( theRetVal, inPath, rEnv ); + return uno::Reference< io::XInputStream >( xInputStream.get() ); } @@ -1295,9 +1293,7 @@ void NeonSession::POST( const rtl::OUString & inPath, if ( !getDataFromInputStream( inInputStream, aDataToSend, true ) ) throw DAVException( DAVException::DAV_INVALID_ARG ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); NeonRequestContext aCtx( oOutputStream ); int theRetVal = POST( m_pHttpSession, @@ -1310,20 +1306,7 @@ void NeonSession::POST( const rtl::OUString & inPath, rContentType, rReferer ); - HandleError( theRetVal ); -} - -// ------------------------------------------------------------------- -// ABORT -// ------------------------------------------------------------------- -void NeonSession::ABORT() - throw ( DAVException ) -{ - // 11.11.09 (tkr): The following code lines causing crashes if closing a ongoing connection. It turned out that this existing solution doesn't work in multi-threading environments. - // So I disabled them in 3.2. . Issue #73893# should fix it in OOo 3.3. - - //if (NULL !=m_pHttpSession) - // ne_close_connection(m_pHttpSession); + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- @@ -1335,30 +1318,27 @@ void NeonSession::MKCOL( const rtl::OUString & inPath, { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); int theRetVal = ne_mkcol( m_pHttpSession, rtl::OUStringToOString( - inPath, RTL_TEXTENCODING_UTF8 ) ); - HandleError( theRetVal ); + inPath, RTL_TEXTENCODING_UTF8 ) ); + + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- // COPY // ------------------------------------------------------------------- -void NeonSession::COPY( const rtl::OUString & inSourceURL, - const rtl::OUString & inDestinationURL, +void NeonSession::COPY( const rtl::OUString & inSourceURL, + const rtl::OUString & inDestinationURL, const DAVRequestEnvironment & rEnv, - sal_Bool inOverWrite ) + sal_Bool inOverWrite ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); NeonUri theSourceUri( inSourceURL ); NeonUri theDestinationUri( inDestinationURL ); @@ -1367,12 +1347,13 @@ void NeonSession::COPY( const rtl::OUString & inSourceURL, inOverWrite ? 1 : 0, NE_DEPTH_INFINITE, rtl::OUStringToOString( - theSourceUri.GetPath(), - RTL_TEXTENCODING_UTF8 ), + theSourceUri.GetPath(), + RTL_TEXTENCODING_UTF8 ), rtl::OUStringToOString( - theDestinationUri.GetPath(), - RTL_TEXTENCODING_UTF8 ) ); - HandleError( theRetVal ); + theDestinationUri.GetPath(), + RTL_TEXTENCODING_UTF8 ) ); + + HandleError( theRetVal, inSourceURL, rEnv ); } // ------------------------------------------------------------------- @@ -1386,21 +1367,20 @@ void NeonSession::MOVE( const rtl::OUString & inSourceURL, { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); NeonUri theSourceUri( inSourceURL ); NeonUri theDestinationUri( inDestinationURL ); int theRetVal = ne_move( m_pHttpSession, inOverWrite ? 1 : 0, rtl::OUStringToOString( - theSourceUri.GetPath(), - RTL_TEXTENCODING_UTF8 ), + theSourceUri.GetPath(), + RTL_TEXTENCODING_UTF8 ), rtl::OUStringToOString( - theDestinationUri.GetPath(), - RTL_TEXTENCODING_UTF8 ) ); - HandleError( theRetVal ); + theDestinationUri.GetPath(), + RTL_TEXTENCODING_UTF8 ) ); + + HandleError( theRetVal, inSourceURL, rEnv ); } // ------------------------------------------------------------------- @@ -1412,53 +1392,282 @@ void NeonSession::DESTROY( const rtl::OUString & inPath, { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); - - m_aEnv = rEnv; + Init( rEnv ); int theRetVal = ne_delete( m_pHttpSession, rtl::OUStringToOString( - inPath, RTL_TEXTENCODING_UTF8 ) ); - HandleError( theRetVal ); + inPath, RTL_TEXTENCODING_UTF8 ) ); + + HandleError( theRetVal, inPath, rEnv ); } // ------------------------------------------------------------------- -// LOCK +namespace +{ + sal_Int32 lastChanceToSendRefreshRequest( TimeValue const & rStart, + int timeout ) + { + TimeValue aEnd; + osl_getSystemTime( &aEnd ); + + // Try to estimate a safe absolute time for sending the + // lock refresh request. + sal_Int32 lastChanceToSendRefreshRequest = -1; + if ( timeout != NE_TIMEOUT_INFINITE ) + { + sal_Int32 calltime = aEnd.Seconds - rStart.Seconds; + if ( calltime <= timeout ) + { + lastChanceToSendRefreshRequest + = aEnd.Seconds + timeout - calltime; + } + else + { + OSL_TRACE( "No chance to refresh lock before timeout!" ); + } + } + return lastChanceToSendRefreshRequest; + } + +} // namespace + +// ------------------------------------------------------------------- +// LOCK (set new lock) // ------------------------------------------------------------------- -// Note: Uncomment the following if locking support is required -/* -void NeonSession::LOCK( const Lock & inLock, +void NeonSession::LOCK( const ::rtl::OUString & inPath, + ucb::Lock & rLock, const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); + Init( rEnv ); - m_aEnv = rEnv; + /* Create a depth zero, exclusive write lock, with default timeout + * (allowing a server to pick a default). token, owner and uri are + * unset. */ + NeonLock * theLock = ne_lock_create(); + + // Set the lock uri + ne_uri aUri; + ne_uri_parse( rtl::OUStringToOString( makeAbsoluteURL( inPath ), + RTL_TEXTENCODING_UTF8 ).getStr(), + &aUri ); + theLock->uri = aUri; + + // Set the lock depth + switch( rLock.Depth ) + { + case ucb::LockDepth_ZERO: + theLock->depth = NE_DEPTH_ZERO; + break; + case ucb::LockDepth_ONE: + theLock->depth = NE_DEPTH_ONE; + break; + case ucb::LockDepth_INFINITY: + theLock->depth = NE_DEPTH_INFINITE; + break; + default: + throw DAVException( DAVException::DAV_INVALID_ARG ); + } + + // Set the lock scope + switch ( rLock.Scope ) + { + case ucb::LockScope_EXCLUSIVE: + theLock->scope = ne_lockscope_exclusive; + break; + case ucb::LockScope_SHARED: + theLock->scope = ne_lockscope_shared; + break; + default: + throw DAVException( DAVException::DAV_INVALID_ARG ); + } + + // Set the lock timeout + theLock->timeout = (long)rLock.Timeout; + + // Set the lock owner + rtl::OUString aValue; + rLock.Owner >>= aValue; + theLock->owner = + ne_strdup( rtl::OUStringToOString( aValue, + RTL_TEXTENCODING_UTF8 ).getStr() ); + TimeValue startCall; + osl_getSystemTime( &startCall ); + + int theRetVal = ne_lock( m_pHttpSession, theLock ); + + if ( theRetVal == NE_OK ) + { + m_aNeonLockStore.addLock( theLock, + this, + lastChanceToSendRefreshRequest( + startCall, theLock->timeout ) ); + + uno::Sequence< rtl::OUString > aTokens( 1 ); + aTokens[ 0 ] = rtl::OUString::createFromAscii( theLock->token ); + rLock.LockTokens = aTokens; + + OSL_TRACE( "NeonSession::LOCK: created lock for %s. token: %s", + rtl::OUStringToOString( makeAbsoluteURL( inPath ), + RTL_TEXTENCODING_UTF8 ).getStr(), + theLock->token ); + } + else + { + ne_lock_destroy( theLock ); + + OSL_TRACE( "NeonSession::LOCK: obtaining lock for %s failed!", + rtl::OUStringToOString( makeAbsoluteURL( inPath ), + RTL_TEXTENCODING_UTF8 ).getStr() ); + } + + HandleError( theRetVal, inPath, rEnv ); +} + +// ------------------------------------------------------------------- +// LOCK (refresh existing lock) +// ------------------------------------------------------------------- +sal_Int64 NeonSession::LOCK( const ::rtl::OUString & inPath, + sal_Int64 nTimeout, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + + // Try to get the neon lock from lock store + NeonLock * theLock + = m_aNeonLockStore.findByUri( makeAbsoluteURL( inPath ) ); + if ( !theLock ) + throw DAVException( DAVException::DAV_NOT_LOCKED ); + + Init( rEnv ); + + // refresh existing lock. + theLock->timeout = static_cast< long >( nTimeout ); - Lockit( inLock, true ); + TimeValue startCall; + osl_getSystemTime( &startCall ); + + int theRetVal = ne_lock_refresh( m_pHttpSession, theLock ); + + if ( theRetVal == NE_OK ) + { + m_aNeonLockStore.updateLock( theLock, + lastChanceToSendRefreshRequest( + startCall, theLock->timeout ) ); + } + + HandleError( theRetVal, inPath, rEnv ); + + return theLock->timeout; +} + +// ------------------------------------------------------------------- +// LOCK (refresh existing lock) +// ------------------------------------------------------------------- +bool NeonSession::LOCK( NeonLock * pLock, + sal_Int32 & rlastChanceToSendRefreshRequest ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); + +#if OSL_DEBUG_LEVEL > 0 + char * p = ne_uri_unparse( &(pLock->uri) ); + OSL_TRACE( "NeonSession::LOCK: Refreshing lock for %s.", p ); + ne_free( p ); +#endif + + // refresh existing lock. + + TimeValue startCall; + osl_getSystemTime( &startCall ); + + if ( ne_lock_refresh( m_pHttpSession, pLock ) == NE_OK ) + { + rlastChanceToSendRefreshRequest + = lastChanceToSendRefreshRequest( startCall, pLock->timeout ); + + OSL_TRACE( "Lock successfully refreshed." ); + return true; + } + else + { + OSL_TRACE( "Lock not refreshed!" ); + return false; + } } -*/ // ------------------------------------------------------------------- // UNLOCK // ------------------------------------------------------------------- -// Note: Uncomment the following if locking support is required -/* -void NeonSession::UNLOCK( const Lock & inLock, +void NeonSession::UNLOCK( const ::rtl::OUString & inPath, const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Init(); + // get the neon lock from lock store + NeonLock * theLock + = m_aNeonLockStore.findByUri( makeAbsoluteURL( inPath ) ); + if ( !theLock ) + throw DAVException( DAVException::DAV_NOT_LOCKED ); - m_aEnv = rEnv; + Init( rEnv ); + + int theRetVal = ne_unlock( m_pHttpSession, theLock ); + + if ( theRetVal == NE_OK ) + { + m_aNeonLockStore.removeLock( theLock ); + ne_lock_destroy( theLock ); + } + else + { + OSL_TRACE( "NeonSession::UNLOCK: unlocking of %s failed.", + rtl::OUStringToOString( makeAbsoluteURL( inPath ), + RTL_TEXTENCODING_UTF8 ).getStr() ); + } + + HandleError( theRetVal, inPath, rEnv ); +} + +// ------------------------------------------------------------------- +// UNLOCK +// ------------------------------------------------------------------- +bool NeonSession::UNLOCK( NeonLock * pLock ) +{ + osl::Guard< osl::Mutex > theGuard( m_aMutex ); - Lockit( inLock, false ); +#if OSL_DEBUG_LEVEL > 0 + char * p = ne_uri_unparse( &(pLock->uri) ); + OSL_TRACE( "NeonSession::UNLOCK: Unlocking %s.", p ); + ne_free( p ); +#endif + + if ( ne_unlock( m_pHttpSession, pLock ) == NE_OK ) + { + OSL_TRACE( "UNLOCK succeeded." ); + return true; + } + else + { + OSL_TRACE( "UNLOCK failed!" ); + return false; + } +} + +// ------------------------------------------------------------------- +void NeonSession::abort() + throw ( DAVException ) +{ + // 11.11.09 (tkr): The following code lines causing crashes if + // closing a ongoing connection. It turned out that this existing + // solution doesn't work in multi-threading environments. + // So I disabled them in 3.2. . Issue #73893# should fix it in OOo 3.3. + //if ( m_pHttpSession ) + // ne_close_connection( m_pHttpSession ); } -*/ // ------------------------------------------------------------------- const ucbhelper::InternetProxyServer & NeonSession::getProxySettings() const @@ -1479,10 +1688,98 @@ const ucbhelper::InternetProxyServer & NeonSession::getProxySettings() const } // ------------------------------------------------------------------- +namespace { + +bool containsLocktoken( const uno::Sequence< ucb::Lock > & rLocks, + const char * token ) +{ + for ( sal_Int32 n = 0; n < rLocks.getLength(); ++n ) + { + const uno::Sequence< rtl::OUString > & rTokens + = rLocks[ n ].LockTokens; + for ( sal_Int32 m = 0; m < rTokens.getLength(); ++m ) + { + if ( rTokens[ m ].equalsAscii( token ) ) + return true; + } + } + return false; +} + +} // namespace + +// ------------------------------------------------------------------- +bool NeonSession::removeExpiredLocktoken( const rtl::OUString & inURL, + const DAVRequestEnvironment & rEnv ) +{ + NeonLock * theLock = m_aNeonLockStore.findByUri( inURL ); + if ( !theLock ) + return false; + + // do a lockdiscovery to check whether this lock is still valid. + try + { + // @@@ Alternative: use ne_lock_discover() => less overhead + + std::vector< DAVResource > aResources; + std::vector< rtl::OUString > aPropNames; + aPropNames.push_back( DAVProperties::LOCKDISCOVERY ); + + PROPFIND( rEnv.m_aRequestURI, DAVZERO, aPropNames, aResources, rEnv ); + + if ( aResources.size() == 0 ) + return false; + + std::vector< DAVPropertyValue >::const_iterator it + = aResources[ 0 ].properties.begin(); + std::vector< DAVPropertyValue >::const_iterator end + = aResources[ 0 ].properties.end(); + + while ( it != end ) + { + if ( (*it).Name.equals( DAVProperties::LOCKDISCOVERY ) ) + { + uno::Sequence< ucb::Lock > aLocks; + if ( !( (*it).Value >>= aLocks ) ) + return false; + + if ( !containsLocktoken( aLocks, theLock->token ) ) + { + // expired! + break; + } + + // still valid. + return false; + } + ++it; + } + + // No lockdiscovery prop in propfind result / locktoken not found + // in propfind result -> not locked + OSL_TRACE( "NeonSession::removeExpiredLocktoken: Removing " + " expired lock token for %s. token: %s", + rtl::OUStringToOString( inURL, + RTL_TEXTENCODING_UTF8 ).getStr(), + theLock->token ); + + m_aNeonLockStore.removeLock( theLock ); + ne_lock_destroy( theLock ); + return true; + } + catch ( DAVException const & ) + { + } + return false; +} + +// ------------------------------------------------------------------- // HandleError // Common Error Handler // ------------------------------------------------------------------- -void NeonSession::HandleError( int nError ) +void NeonSession::HandleError( int nError, + const rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) throw ( DAVException ) { m_aEnv = DAVRequestEnvironment(); @@ -1491,60 +1788,84 @@ void NeonSession::HandleError( int nError ) switch ( nError ) { case NE_OK: - // Cleanup. return; case NE_ERROR: // Generic error { rtl::OUString aText = rtl::OUString::createFromAscii( - ne_get_error( m_pHttpSession ) ); - throw DAVException( DAVException::DAV_HTTP_ERROR, - aText, - makeStatusCode( aText ) ); - } + ne_get_error( m_pHttpSession ) ); + + sal_uInt16 code = makeStatusCode( aText ); + + if ( code == SC_LOCKED ) + { + if ( m_aNeonLockStore.findByUri( + makeAbsoluteURL( inPath ) ) == 0 ) + { + // locked by 3rd party + throw DAVException( DAVException::DAV_LOCKED ); + } + else + { + // locked by ourself + throw DAVException( DAVException::DAV_LOCKED_SELF ); + } + } + + // Special handling for 400 and 412 status codes, which may indicate + // that a lock previously obtained by us has been released meanwhile + // by the server. Unfortunately, RFC is not clear at this point, + // thus server implementations behave different... + else if ( code == SC_BAD_REQUEST || code == SC_PRECONDITION_FAILED ) + { + if ( removeExpiredLocktoken( makeAbsoluteURL( inPath ), rEnv ) ) + throw DAVException( DAVException::DAV_LOCK_EXPIRED ); + } + throw DAVException( DAVException::DAV_HTTP_ERROR, aText, code ); + } case NE_LOOKUP: // Name lookup failed. throw DAVException( DAVException::DAV_HTTP_LOOKUP, NeonUri::makeConnectionEndPointString( - m_aHostName, m_nPort ) ); + m_aHostName, m_nPort ) ); case NE_AUTH: // User authentication failed on server throw DAVException( DAVException::DAV_HTTP_AUTH, NeonUri::makeConnectionEndPointString( - m_aHostName, m_nPort ) ); + m_aHostName, m_nPort ) ); case NE_PROXYAUTH: // User authentication failed on proxy throw DAVException( DAVException::DAV_HTTP_AUTHPROXY, NeonUri::makeConnectionEndPointString( - m_aProxyName, m_nProxyPort ) ); + m_aProxyName, m_nProxyPort ) ); case NE_CONNECT: // Could not connect to server throw DAVException( DAVException::DAV_HTTP_CONNECT, NeonUri::makeConnectionEndPointString( - m_aHostName, m_nPort ) ); + m_aHostName, m_nPort ) ); case NE_TIMEOUT: // Connection timed out throw DAVException( DAVException::DAV_HTTP_TIMEOUT, NeonUri::makeConnectionEndPointString( - m_aHostName, m_nPort ) ); + m_aHostName, m_nPort ) ); case NE_FAILED: // The precondition failed throw DAVException( DAVException::DAV_HTTP_FAILED, NeonUri::makeConnectionEndPointString( - m_aHostName, m_nPort ) ); + m_aHostName, m_nPort ) ); case NE_RETRY: // Retry request (ne_end_request ONLY) throw DAVException( DAVException::DAV_HTTP_RETRY, NeonUri::makeConnectionEndPointString( - m_aHostName, m_nPort ) ); + m_aHostName, m_nPort ) ); case NE_REDIRECT: { NeonUri aUri( ne_redirect_location( m_pHttpSession ) ); throw DAVException( - DAVException::DAV_HTTP_REDIRECT, aUri.GetURI() ); + DAVException::DAV_HTTP_REDIRECT, aUri.GetURI() ); } - default: + default: { OSL_TRACE( "NeonSession::HandleError : Unknown Neon error code!" ); throw DAVException( DAVException::DAV_HTTP_ERROR, @@ -1554,78 +1875,6 @@ void NeonSession::HandleError( int nError ) } } -// Note: Uncomment the following if locking support is required -/* -void NeonSession::Lockit( const Lock & inLock, bool inLockit ) - throw ( DAVException ) -{ - osl::Guard< osl::Mutex > theGuard( m_aMutex ); - - // Create the neon lock - NeonLock * theLock = new NeonLock; - int theRetVal; - - // Set the lock uri - NeonUri theUri( inLock.uri ); - theLock->uri = const_cast< char * > - ( rtl::OUStringToOString( - theUri.GetPath(), RTL_TEXTENCODING_UTF8 ).getStr() ); - - if ( inLockit ) - { - // Set the lock depth - switch( inLock.depth ) - { - case DAVZERO: - case DAVINFINITY: - theLock->depth = int ( inLock.depth ); - break; - default: - throw DAVException( DAVException::DAV_INVALID_ARG ); - break; - } - - // Set the lock scope - switch ( inLock.scope ) - { - case EXCLUSIVE: - theLock->scope = ne_lockscope_exclusive; - break; - case SHARED: - theLock->scope = ne_lockscope_shared; - break; - default: - throw DAVException( DAVException::DAV_INVALID_ARG ); - break; - } - - // Set the lock owner - const char * theOwner = rtl::OUStringToOString( inLock.owner, - RTL_TEXTENCODING_UTF8 ); - theLock->owner = const_cast< char * > ( theOwner ); - - // Set the lock timeout - // Note: Neon ignores the timeout - //theLock->timeout = inLock.timeout; - - theRetVal = ne_lock( m_pHttpSession, theLock ); - } - else - { - - // Set the lock token - rtl::OUString theToken = inLock.locktoken.getConstArray()[ 0 ]; - theLock->token = const_cast< char * > - ( rtl::OUStringToOString( - theToken, RTL_TEXTENCODING_UTF8 ).getStr() ); - - theRetVal = ne_unlock( m_pHttpSession, theLock ); - } - - HandleError( theRetVal ); -} -*/ - // ------------------------------------------------------------------- namespace { @@ -1702,22 +1951,23 @@ int NeonSession::GET( ne_session * sess, #if NEON_VERSION < 0x0250 if ( getheaders ) - ne_add_response_header_catcher( req, runResponseHeaderHandler, userdata ); + ne_add_response_header_catcher( + req, runResponseHeaderHandler, userdata ); #endif - ne_add_response_body_reader( req, ne_accept_2xx, reader, userdata ); + ne_decompress * dc + = ne_decompress_reader( req, ne_accept_2xx, reader, userdata ); ret = ne_request_dispatch( req ); #if NEON_VERSION >= 0x0250 if ( getheaders ) { - while ((cursor = ne_response_header_iterate(req, cursor, &name, &value)) - != NULL) + while ( ( cursor = ne_response_header_iterate( + req, cursor, &name, &value ) ) != NULL ) { char buffer[8192]; ne_snprintf(buffer, sizeof buffer, "%s: %s", name, value); - runResponseHeaderHandler(userdata, buffer); } } @@ -1725,6 +1975,9 @@ int NeonSession::GET( ne_session * sess, if ( ret == NE_OK && ne_get_status( req )->klass != 2 ) ret = NE_ERROR; + if ( dc != 0 ) + ne_decompress_destroy(dc); + ne_request_destroy( req ); return ret; } @@ -1812,10 +2065,11 @@ int NeonSession::POST( ne_session * sess, // ------------------------------------------------------------------- // static -bool NeonSession::getDataFromInputStream( - const uno::Reference< io::XInputStream > & xStream, - uno::Sequence< sal_Int8 > & rData, - bool bAppendTrailingZeroByte ) +bool +NeonSession::getDataFromInputStream( + const uno::Reference< io::XInputStream > & xStream, + uno::Sequence< sal_Int8 > & rData, + bool bAppendTrailingZeroByte ) { if ( xStream.is() ) { @@ -1898,32 +2152,56 @@ bool NeonSession::getDataFromInputStream( } return false; } -// ------------------------------------------------------------------- -//static - -NeonSession::Map NeonSession::certMap; // --------------------------------------------------------------------- sal_Bool -NeonSession::isDomainMatch( rtl::OUString certHostName) +NeonSession::isDomainMatch( rtl::OUString certHostName ) { rtl::OUString hostName = getHostName(); - if (hostName.equalsIgnoreAsciiCase( certHostName )) + if (hostName.equalsIgnoreAsciiCase( certHostName ) ) return sal_True; - - - if ( 0 == certHostName.indexOf( rtl::OUString::createFromAscii( "*" ) ) && hostName.getLength() >= certHostName.getLength() ) + if ( 0 == certHostName.indexOf( rtl::OUString::createFromAscii( "*" ) ) && + hostName.getLength() >= certHostName.getLength() ) { rtl::OUString cmpStr = certHostName.copy( 1 ); - if ( hostName.matchIgnoreAsciiCase( cmpStr, hostName.getLength( ) - cmpStr.getLength()) ) + if ( hostName.matchIgnoreAsciiCase( + cmpStr, hostName.getLength() - cmpStr.getLength() ) ) return sal_True; - } - return sal_False; } - +// --------------------------------------------------------------------- +rtl::OUString NeonSession::makeAbsoluteURL( rtl::OUString const & rURL ) const +{ + try + { + // Is URL relative or already absolute? + if ( rURL[ 0 ] != sal_Unicode( '/' ) ) + { + // absolute. + return rtl::OUString( rURL ); + } + else + { + ne_uri aUri; + memset( &aUri, 0, sizeof( aUri ) ); + + ne_fill_server_uri( m_pHttpSession, &aUri ); + aUri.path + = ne_strdup( rtl::OUStringToOString( + rURL, RTL_TEXTENCODING_UTF8 ).getStr() ); + NeonUri aNeonUri( &aUri ); + ne_uri_free( &aUri ); + return aNeonUri.GetURI(); + } + } + catch ( DAVException const & ) + { + } + // error. + return rtl::OUString(); +} diff --git a/ucb/source/ucp/webdav/NeonSession.hxx b/ucb/source/ucp/webdav/NeonSession.hxx index 263169ae452a..bb6bbbb8d3c3 100644 --- a/ucb/source/ucp/webdav/NeonSession.hxx +++ b/ucb/source/ucp/webdav/NeonSession.hxx @@ -35,10 +35,9 @@ #include <osl/mutex.hxx> #include "DAVSession.hxx" #include "NeonTypes.hxx" +#include "NeonLockStore.hxx" #include <com/sun/star/lang/XMultiServiceFactory.hpp> -using namespace com::sun::star; - namespace ucbhelper { class ProxyDecider; } namespace webdav_ucp @@ -51,236 +50,249 @@ namespace webdav_ucp class NeonSession : public DAVSession { - private: - osl::Mutex m_aMutex; - static osl::Mutex m_aGlobalMutex; - rtl::OUString m_aScheme; - rtl::OUString m_aHostName; - rtl::OUString m_aProxyName; - sal_Int32 m_nPort; - sal_Int32 m_nProxyPort; - HttpSession * m_pHttpSession; - void * m_pRequestData; - const ucbhelper::InternetProxyDecider & m_rProxyDecider; - - // @@@ This should really be per-request data. But Neon currently - // (0.23.5) has no interface for passing per-request user data. - // Theoretically, a NeonSession instance could handle multiple requests - // at a time --currently it doesn't. Thus this is not an issue at the - // moment. - DAVRequestEnvironment m_aEnv; - - // Note: Uncomment the following if locking support is required - // NeonLockSession * mNeonLockSession; - - static bool m_bGlobalsInited; - - protected: - virtual ~NeonSession(); - - public: - NeonSession( const rtl::Reference< DAVSessionFactory > & rSessionFactory, - const rtl::OUString& inUri, - const ucbhelper::InternetProxyDecider & rProxyDecider ) - throw ( DAVException ); - - // DAVSession methods - virtual sal_Bool CanUse( const ::rtl::OUString & inUri ); - - virtual sal_Bool UsesProxy(); - - const DAVRequestEnvironment & getRequestEnvironment() const - { return m_aEnv; } - - virtual void - OPTIONS( const ::rtl::OUString & inPath, - DAVCapabilities & outCapabilities, - const DAVRequestEnvironment & rEnv ) - throw ( DAVException ); - - // allprop & named - virtual void - PROPFIND( const ::rtl::OUString & inPath, - const Depth inDepth, - const std::vector< ::rtl::OUString > & inPropNames, - std::vector< DAVResource > & ioResources, - const DAVRequestEnvironment & rEnv ) - throw ( DAVException ); - - // propnames - virtual void - PROPFIND( const ::rtl::OUString & inPath, - const Depth inDepth, - std::vector< DAVResourceInfo >& ioResInfo, - const DAVRequestEnvironment & rEnv ) - throw ( DAVException ); - - virtual void - PROPPATCH( const ::rtl::OUString & inPath, - const std::vector< ProppatchValue > & inValues, - const DAVRequestEnvironment & rEnv ) - throw( DAVException ); - - virtual void - HEAD( const ::rtl::OUString & inPath, - const std::vector< ::rtl::OUString > & inHeaderNames, - DAVResource & ioResource, - const DAVRequestEnvironment & rEnv ) - throw( DAVException ); - - virtual com::sun::star::uno::Reference< - com::sun::star::io::XInputStream > - GET( const ::rtl::OUString & inPath, - const DAVRequestEnvironment & rEnv ) - throw ( DAVException ); - - virtual void - GET( const ::rtl::OUString & inPath, - com::sun::star::uno::Reference< - com::sun::star::io::XOutputStream > & ioOutputStream, - const DAVRequestEnvironment & rEnv ) - throw ( DAVException ); - - virtual com::sun::star::uno::Reference< - com::sun::star::io::XInputStream > - GET( const ::rtl::OUString & inPath, - const std::vector< ::rtl::OUString > & inHeaderNames, - DAVResource & ioResource, +private: + osl::Mutex m_aMutex; + rtl::OUString m_aScheme; + rtl::OUString m_aHostName; + rtl::OUString m_aProxyName; + sal_Int32 m_nPort; + sal_Int32 m_nProxyPort; + HttpSession * m_pHttpSession; + void * m_pRequestData; + const ucbhelper::InternetProxyDecider & m_rProxyDecider; + + // @@@ This should really be per-request data. But Neon currently + // (0.23.5) has no interface for passing per-request user data. + // Theoretically, a NeonSession instance could handle multiple requests + // at a time --currently it doesn't. Thus this is not an issue at the + // moment. + DAVRequestEnvironment m_aEnv; + + static bool m_bGlobalsInited; + static osl::Mutex m_aGlobalMutex; + static NeonLockStore m_aNeonLockStore; + +protected: + virtual ~NeonSession(); + +public: + NeonSession( const rtl::Reference< DAVSessionFactory > & rSessionFactory, + const rtl::OUString& inUri, + const ucbhelper::InternetProxyDecider & rProxyDecider ) + throw ( DAVException ); + + // DAVSession methods + virtual sal_Bool CanUse( const ::rtl::OUString & inUri ); + + virtual sal_Bool UsesProxy(); + + const DAVRequestEnvironment & getRequestEnvironment() const + { return m_aEnv; } + + virtual void + OPTIONS( const ::rtl::OUString & inPath, + DAVCapabilities & outCapabilities, const DAVRequestEnvironment & rEnv ) - throw ( DAVException ); - - virtual void - GET( const ::rtl::OUString & inPath, - com::sun::star::uno::Reference< - com::sun::star::io::XOutputStream > & ioOutputStream, - const std::vector< ::rtl::OUString > & inHeaderNames, - DAVResource & ioResource, - const DAVRequestEnvironment & rEnv ) - throw ( DAVException ); - - virtual void - PUT( const ::rtl::OUString & inPath, - const com::sun::star::uno::Reference< - com::sun::star::io::XInputStream > & inInputStream, - const DAVRequestEnvironment & rEnv ) - throw ( DAVException ); - - virtual com::sun::star::uno::Reference< - com::sun::star::io::XInputStream > - POST( const rtl::OUString & inPath, - const rtl::OUString & rContentType, - const rtl::OUString & rReferer, - const com::sun::star::uno::Reference< - com::sun::star::io::XInputStream > & inInputStream, + throw ( DAVException ); + + // allprop & named + virtual void + PROPFIND( const ::rtl::OUString & inPath, + const Depth inDepth, + const std::vector< ::rtl::OUString > & inPropNames, + std::vector< DAVResource > & ioResources, const DAVRequestEnvironment & rEnv ) - throw ( DAVException ); + throw ( DAVException ); - virtual void - POST( const rtl::OUString & inPath, - const rtl::OUString & rContentType, - const rtl::OUString & rReferer, - const com::sun::star::uno::Reference< - com::sun::star::io::XInputStream > & inInputStream, - com::sun::star::uno::Reference< - com::sun::star::io::XOutputStream > & oOutputStream, + // propnames + virtual void + PROPFIND( const ::rtl::OUString & inPath, + const Depth inDepth, + std::vector< DAVResourceInfo >& ioResInfo, const DAVRequestEnvironment & rEnv ) - throw ( DAVException ); + throw ( DAVException ); - virtual void - MKCOL( const ::rtl::OUString & inPath, + virtual void + PROPPATCH( const ::rtl::OUString & inPath, + const std::vector< ProppatchValue > & inValues, const DAVRequestEnvironment & rEnv ) - throw ( DAVException ); - - virtual void - COPY( const ::rtl::OUString & inSourceURL, - const ::rtl::OUString & inDestinationURL, - const DAVRequestEnvironment & rEnv, - sal_Bool inOverWrite ) - throw ( DAVException ); - - virtual void - MOVE( const ::rtl::OUString & inSourceURL, - const ::rtl::OUString & inDestinationURL, - const DAVRequestEnvironment & rEnv, - sal_Bool inOverWrite ) - throw ( DAVException ); - - virtual void DESTROY( const ::rtl::OUString & inPath, - const DAVRequestEnvironment & rEnv ) - throw ( DAVException ); - - virtual void ABORT() - throw ( DAVException ); - - // Note: Uncomment the following if locking support is required - /* - virtual void LOCK (const Lock & inLock, - const DAVRequestEnvironment & rEnv ) - throw ( DAVException ); - - virtual void UNLOCK (const Lock & inLock, - const DAVRequestEnvironment & rEnv ) - throw ( DAVException ); - */ - - // helpers - const rtl::OUString & getHostName() const { return m_aHostName; } - - const ::uno::Reference< ::lang::XMultiServiceFactory > getMSF() { return m_xFactory->getServiceFactory(); } - - const void * getRequestData() const { return m_pRequestData; } - - sal_Bool isDomainMatch( rtl::OUString certHostName ); - - private: - // Initialise "Neon sockets" - void Init( void ) - throw ( DAVException ); - - void HandleError( int nError ) - throw ( DAVException ); - - const ucbhelper::InternetProxyServer & getProxySettings() const; - - // Note: Uncomment the following if locking support is required - // void Lockit( const Lock & inLock, bool inLockit ) - // throw ( DAVException ); - - // low level GET implementation, used by public GET implementations - static int GET( ne_session * sess, - const char * uri, - ne_block_reader reader, - bool getheaders, - void * userdata ); - - // Buffer-based PUT implementation. Neon only has file descriptor- - // based API. - static int PUT( ne_session * sess, - const char * uri, - const char * buffer, - size_t size ); - - // Buffer-based POST implementation. Neon only has file descriptor- - // based API. - int POST( ne_session * sess, - const char * uri, - const char * buffer, - ne_block_reader reader, - void * userdata, - const rtl::OUString & rContentType, - const rtl::OUString & rReferer ); - - // Helper: XInputStream -> Sequence< sal_Int8 > - static bool getDataFromInputStream( - const com::sun::star::uno::Reference< - com::sun::star::io::XInputStream > & xStream, - com::sun::star::uno::Sequence< sal_Int8 > & rData, - bool bAppendTrailingZeroByte ); - - typedef std::map< ::rtl::OUString, ::rtl::OUString > Map; - static Map certMap; + throw ( DAVException ); + + virtual void + HEAD( const ::rtl::OUString & inPath, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > + GET( const ::rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual void + GET( const ::rtl::OUString & inPath, + com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > & ioOutputStream, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > + GET( const ::rtl::OUString & inPath, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual void + GET( const ::rtl::OUString & inPath, + com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > & ioOutputStream, + const std::vector< ::rtl::OUString > & inHeaderNames, + DAVResource & ioResource, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual void + PUT( const ::rtl::OUString & inPath, + const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > & inInputStream, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual com::sun::star::uno::Reference< com::sun::star::io::XInputStream > + POST( const rtl::OUString & inPath, + const rtl::OUString & rContentType, + const rtl::OUString & rReferer, + const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > & inInputStream, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual void + POST( const rtl::OUString & inPath, + const rtl::OUString & rContentType, + const rtl::OUString & rReferer, + const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > & inInputStream, + com::sun::star::uno::Reference< + com::sun::star::io::XOutputStream > & oOutputStream, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual void + MKCOL( const ::rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual void + COPY( const ::rtl::OUString & inSourceURL, + const ::rtl::OUString & inDestinationURL, + const DAVRequestEnvironment & rEnv, + sal_Bool inOverWrite ) + throw ( DAVException ); + + virtual void + MOVE( const ::rtl::OUString & inSourceURL, + const ::rtl::OUString & inDestinationURL, + const DAVRequestEnvironment & rEnv, + sal_Bool inOverWrite ) + throw ( DAVException ); + + virtual void DESTROY( const ::rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + // set new lock. + virtual void LOCK( const ::rtl::OUString & inURL, + com::sun::star::ucb::Lock & inLock, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + // refresh existing lock. + virtual sal_Int64 LOCK( const ::rtl::OUString & inURL, + sal_Int64 nTimeout, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + virtual void UNLOCK( const ::rtl::OUString & inURL, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + // helpers + virtual void abort() + throw ( DAVException ); + + const rtl::OUString & getHostName() const { return m_aHostName; } + + const ::uno::Reference< ::lang::XMultiServiceFactory > getMSF() + { return m_xFactory->getServiceFactory(); } + + const void * getRequestData() const { return m_pRequestData; } + + sal_Bool isDomainMatch( rtl::OUString certHostName ); + +private: + friend class NeonLockStore; + + void Init( void ) + throw ( DAVException ); + + void Init( const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + // ret: true => retry request. + void HandleError( int nError, + const rtl::OUString & inPath, + const DAVRequestEnvironment & rEnv ) + throw ( DAVException ); + + const ucbhelper::InternetProxyServer & getProxySettings() const; + + bool removeExpiredLocktoken( const rtl::OUString & inURL, + const DAVRequestEnvironment & rEnv ); + + // refresh lock, called by NeonLockStore::refreshLocks + bool LOCK( NeonLock * pLock, + sal_Int32 & rlastChanceToSendRefreshRequest ); + + // unlock, called by NeonLockStore::~NeonLockStore + bool UNLOCK( NeonLock * pLock ); + + // low level GET implementation, used by public GET implementations + static int GET( ne_session * sess, + const char * uri, + ne_block_reader reader, + bool getheaders, + void * userdata ); + + // Buffer-based PUT implementation. Neon only has file descriptor- + // based API. + static int PUT( ne_session * sess, + const char * uri, + const char * buffer, + size_t size ); + + // Buffer-based POST implementation. Neon only has file descriptor- + // based API. + int POST( ne_session * sess, + const char * uri, + const char * buffer, + ne_block_reader reader, + void * userdata, + const rtl::OUString & rContentType, + const rtl::OUString & rReferer ); + + // Helper: XInputStream -> Sequence< sal_Int8 > + static bool getDataFromInputStream( + const com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > & xStream, + com::sun::star::uno::Sequence< sal_Int8 > & rData, + bool bAppendTrailingZeroByte ); + + rtl::OUString makeAbsoluteURL( rtl::OUString const & rURL ) const; }; -} // namespace_ucp +} // namespace webdav_ucp #endif // _NEONSESSION_HXX_ diff --git a/ucb/source/ucp/webdav/NeonTypes.hxx b/ucb/source/ucp/webdav/NeonTypes.hxx index 2e97af4c963b..939e25d3812d 100644 --- a/ucb/source/ucp/webdav/NeonTypes.hxx +++ b/ucb/source/ucp/webdav/NeonTypes.hxx @@ -35,6 +35,7 @@ #include <ne_utils.h> #include <ne_basic.h> #include <ne_props.h> +#include <ne_locks.h> typedef ne_session HttpSession; typedef ne_status HttpStatus; @@ -43,4 +44,6 @@ typedef ne_server_capabilities HttpServerCapabilities; typedef ne_propname NeonPropName; typedef ne_prop_result_set NeonPropFindResultSet; +typedef struct ne_lock NeonLock; + #endif // _NEONTYPES_HXX_ diff --git a/ucb/source/ucp/webdav/NeonUri.cxx b/ucb/source/ucp/webdav/NeonUri.cxx index 5c49179f6b20..97fdeb40bcc7 100644 --- a/ucb/source/ucp/webdav/NeonUri.cxx +++ b/ucb/source/ucp/webdav/NeonUri.cxx @@ -42,11 +42,6 @@ using namespace webdav_ucp; - char *scheme; - char *host, *userinfo; - unsigned int port; - char *path, *query, *fragment; - # if defined __SUNPRO_CC // FIXME: not sure whether initializing a ne_uri statically is supposed to work // the string fields of ne_uri are char*, not const char* diff --git a/ucb/source/ucp/webdav/UCBDeadPropertyValue.cxx b/ucb/source/ucp/webdav/UCBDeadPropertyValue.cxx index cd03d5b76a9d..532a6f745b77 100644 --- a/ucb/source/ucp/webdav/UCBDeadPropertyValue.cxx +++ b/ucb/source/ucp/webdav/UCBDeadPropertyValue.cxx @@ -89,12 +89,11 @@ const rtl::OUString UCBDeadPropertyValue::aXMLEnd extern "C" int UCBDeadPropertyValue_startelement_callback( void *, int parent, - const char *nspace, + const char * /*nspace*/, const char *name, const char ** ) { - if ( ( name != 0 ) && - ( ( nspace == 0 ) || ( strcmp( nspace, "" ) == 0 ) ) ) + if ( name != 0 ) { switch ( parent ) { @@ -187,7 +186,7 @@ static rtl::OUString encodeValue( const rtl::OUString & rValue ) // PROPPATCH: // - Encoded property value: x<z // - UCBDeadPropertyValue::toXML result: - // <ucbprop><type>string</type><value>x<z</value></ucbprop> + // <ucbprop><type>string</type><value>x<z</value></ucbprop> // PROPFIND: // - parser replaces < by > ==> error (not well formed) @@ -361,7 +360,7 @@ bool UCBDeadPropertyValue::supportsType( const uno::Type & rType ) ////////////////////////////////////////////////////////////////////////// // static bool UCBDeadPropertyValue::createFromXML( const rtl::OString & rInData, - uno::Any & rOutData ) + uno::Any & rOutData ) { bool success = false; @@ -450,7 +449,7 @@ bool UCBDeadPropertyValue::createFromXML( const rtl::OString & rInData, ////////////////////////////////////////////////////////////////////////// // static bool UCBDeadPropertyValue::toXML( const uno::Any & rInData, - rtl::OUString & rOutData ) + rtl::OUString & rOutData ) { // <ucbprop><type>the_type</type><value>the_value</value></ucbprop> @@ -541,7 +540,7 @@ bool UCBDeadPropertyValue::toXML( const uno::Any & rInData, // Encode value! It must not contain XML reserved chars! aStringValue = encodeValue( aStringValue ); - rOutData = aXMLPre; + rOutData = aXMLPre; rOutData += aStringType; rOutData += aXMLMid; rOutData += aStringValue; diff --git a/ucb/source/ucp/webdav/makefile.mk b/ucb/source/ucp/webdav/makefile.mk index c8891723cd2c..848cecd882c4 100644 --- a/ucb/source/ucp/webdav/makefile.mk +++ b/ucb/source/ucp/webdav/makefile.mk @@ -1,7 +1,7 @@ #************************************************************************* # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# +# # Copyright 2008 by Sun Microsystems, Inc. # # OpenOffice.org - a multi-platform office productivity suite @@ -87,25 +87,26 @@ CFLAGS+= $(OPENSSL_CFLAGS) # --- General ----------------------------------------------------- SLOFILES=\ - $(SLO)$/webdavservices.obj \ - $(SLO)$/webdavprovider.obj \ - $(SLO)$/webdavcontent.obj \ - $(SLO)$/webdavcontentcaps.obj \ - $(SLO)$/webdavresultset.obj \ - $(SLO)$/webdavdatasupplier.obj \ - $(SLO)$/ContentProperties.obj \ - $(SLO)$/DAVProperties.obj \ - $(SLO)$/DAVSessionFactory.obj \ - $(SLO)$/DAVResourceAccess.obj \ - $(SLO)$/NeonUri.obj \ - $(SLO)$/NeonInputStream.obj \ - $(SLO)$/NeonPropFindRequest.obj \ - $(SLO)$/NeonHeadRequest.obj \ - $(SLO)$/NeonSession.obj \ - $(SLO)$/DateTimeHelper.obj \ - $(SLO)$/LinkSequence.obj \ - $(SLO)$/LockSequence.obj \ - $(SLO)$/LockEntrySequence.obj \ + $(SLO)$/webdavservices.obj \ + $(SLO)$/webdavprovider.obj \ + $(SLO)$/webdavcontent.obj \ + $(SLO)$/webdavcontentcaps.obj \ + $(SLO)$/webdavresultset.obj \ + $(SLO)$/webdavdatasupplier.obj \ + $(SLO)$/ContentProperties.obj \ + $(SLO)$/DAVProperties.obj \ + $(SLO)$/DAVSessionFactory.obj \ + $(SLO)$/DAVResourceAccess.obj \ + $(SLO)$/NeonUri.obj \ + $(SLO)$/NeonInputStream.obj \ + $(SLO)$/NeonPropFindRequest.obj \ + $(SLO)$/NeonHeadRequest.obj \ + $(SLO)$/NeonSession.obj \ + $(SLO)$/NeonLockStore.obj \ + $(SLO)$/DateTimeHelper.obj \ + $(SLO)$/LinkSequence.obj \ + $(SLO)$/LockSequence.obj \ + $(SLO)$/LockEntrySequence.obj \ $(SLO)$/UCBDeadPropertyValue.obj LIB1TARGET=$(SLB)$/_$(TARGET).lib @@ -119,17 +120,15 @@ SHL1IMPLIB=i$(TARGET) SHL1VERSIONMAP=exports.map SHL1STDLIBS=\ - $(CPPUHELPERLIB) \ - $(CPPULIB) \ - $(SALLIB) \ - $(SALHELPERLIB) \ - $(UCBHELPERLIB) \ - $(COMPHELPERLIB) \ - $(NEON3RDLIB) \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(SALHELPERLIB) \ + $(UCBHELPERLIB) \ + $(COMPHELPERLIB) \ + $(NEON3RDLIB) \ $(LIBXML2LIB) - - .IF "$(GUI)"=="WNT" SHL1STDLIBS+= $(WSOCK32LIB) .IF "$(WINDOWS_VISTA_PSDK)" != "" @@ -150,8 +149,6 @@ SHL1STDLIBS+= $(OPENSSLLIBST) .ENDIF .ENDIF # WNT - - SHL1DEF=$(MISC)$/$(SHL1TARGET).def SHL1LIBS=$(LIB1TARGET) @@ -165,4 +162,3 @@ DEF1NAME=$(SHL1TARGET) # --- Targets ---------------------------------------------------------- .INCLUDE: target.mk - diff --git a/ucb/source/ucp/webdav/webdavcontent.cxx b/ucb/source/ucp/webdav/webdavcontent.cxx index afe2f2d3a7a8..def33876eb43 100644 --- a/ucb/source/ucp/webdav/webdavcontent.cxx +++ b/ucb/source/ucp/webdav/webdavcontent.cxx @@ -36,13 +36,16 @@ ************************************************************************** *************************************************************************/ -#include <osl/diagnose.h> +#include <osl/diagnose.h> #include "osl/doublecheckedlocking.h" #include <rtl/uri.hxx> #include <rtl/ustrbuf.hxx> -#include "com/sun/star/task/XPasswordContainer.hpp" -#include "com/sun/star/task/NoMasterException.hpp" +#include <ucbhelper/contentidentifier.hxx> +#include <ucbhelper/propertyvalueset.hxx> +#include <ucbhelper/simpleinteractionrequest.hxx> +#include <ucbhelper/cancelcommandexecution.hxx> + #include <com/sun/star/beans/PropertyAttribute.hpp> #include <com/sun/star/beans/PropertySetInfoChange.hpp> #include <com/sun/star/beans/PropertySetInfoChangeEvent.hpp> @@ -50,39 +53,37 @@ #include <com/sun/star/io/XActiveDataSink.hpp> #include <com/sun/star/io/XOutputStream.hpp> #include <com/sun/star/lang/IllegalAccessException.hpp> -#include "com/sun/star/ucb/AuthenticationRequest.hpp" +#include <com/sun/star/task/PasswordContainerInteractionHandler.hpp> +#include <com/sun/star/ucb/CommandEnvironment.hpp> #include <com/sun/star/ucb/CommandFailedException.hpp> #include <com/sun/star/ucb/ContentInfoAttribute.hpp> #include <com/sun/star/ucb/InsertCommandArgument.hpp> -#ifndef _COM_SUN_STAR_UCB_INTERACTIVEBADTRANSFRERURLEXCEPTION_HPP_ #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp> -#endif #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp> +#include "com/sun/star/ucb/InteractiveLockingLockedException.hpp" +#include "com/sun/star/ucb/InteractiveLockingLockExpiredException.hpp" +#include "com/sun/star/ucb/InteractiveLockingNotLockedException.hpp" #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp> -#ifndef _COM_SUN_STAR_UCB_INTERACTIVENETWORKGENBERALEXCEPTION_HPP_ #include <com/sun/star/ucb/InteractiveNetworkGeneralException.hpp> -#endif #include <com/sun/star/ucb/InteractiveNetworkReadException.hpp> #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp> #include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp> +#include <com/sun/star/ucb/MissingInputStreamException.hpp> +#include <com/sun/star/ucb/MissingPropertiesException.hpp> #include <com/sun/star/ucb/NameClash.hpp> #include <com/sun/star/ucb/NameClashException.hpp> #include <com/sun/star/ucb/OpenCommandArgument2.hpp> #include <com/sun/star/ucb/OpenMode.hpp> #include <com/sun/star/ucb/PostCommandArgument2.hpp> #include <com/sun/star/ucb/TransferInfo.hpp> -#include <com/sun/star/ucb/XCommandInfo.hpp> -#include <com/sun/star/ucb/XPersistentPropertySet.hpp> -#include <com/sun/star/ucb/MissingInputStreamException.hpp> -#include <com/sun/star/ucb/MissingPropertiesException.hpp> #include <com/sun/star/ucb/UnsupportedCommandException.hpp> #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp> #include <com/sun/star/ucb/UnsupportedNameClashException.hpp> #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp> -#include <ucbhelper/contentidentifier.hxx> -#include <ucbhelper/propertyvalueset.hxx> -#include <ucbhelper/simpleinteractionrequest.hxx> -#include <ucbhelper/cancelcommandexecution.hxx> +#include <com/sun/star/ucb/XCommandInfo.hpp> +#include <com/sun/star/ucb/XPersistentPropertySet.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + #include "webdavcontent.hxx" #include "webdavprovider.hxx" #include "webdavresultset.hxx" @@ -96,250 +97,6 @@ using namespace webdav_ucp; //========================================================================= //========================================================================= // -// CommandEnvironment_Impl Implementation. -// -//========================================================================= -//========================================================================= - -class CommandEnvironment_Impl : public cppu::OWeakObject, - public ucb::XCommandEnvironment, - public task::XInteractionHandler -{ -public: - - CommandEnvironment_Impl( - const uno::Reference< lang::XMultiServiceFactory >& xSMgr ) - : m_xSMgr( xSMgr ) - { - } - - // XInterface - XINTERFACE_DECL() - - // XCommandEnvironment - virtual uno::Reference< task::XInteractionHandler > SAL_CALL - getInteractionHandler( ) - throw (uno::RuntimeException) - { - return this; - } - - virtual uno::Reference< ucb::XProgressHandler > SAL_CALL - getProgressHandler( ) - throw (uno::RuntimeException) - { - return 0; - } - - // XInteractionHandler - virtual void SAL_CALL - handle( const uno::Reference< task::XInteractionRequest >& Request ) - throw (uno::RuntimeException); - -private: - - void - handleAuthenticationRequest( - ucb::AuthenticationRequest const&, - uno::Sequence< uno::Reference< task::XInteractionContinuation > > const&) - SAL_THROW((uno::RuntimeException)) - { - } - - uno::Reference< lang::XMultiServiceFactory > m_xSMgr; -}; - -//========================================================================= -void SAL_CALL CommandEnvironment_Impl::acquire() - throw() -{ - OWeakObject::acquire(); -} - -//========================================================================= -void SAL_CALL CommandEnvironment_Impl::release() - throw() -{ - OWeakObject::release(); -} - -//========================================================================= -uno::Any SAL_CALL CommandEnvironment_Impl::queryInterface( - const uno::Type & rType ) - throw( uno::RuntimeException ) -{ - uno::Any aRet = cppu::queryInterface( - rType, - static_cast< ucb::XCommandEnvironment * >( this ), - static_cast< task::XInteractionHandler * >( this ) ); - return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); -} - -//========================================================================= -void SAL_CALL CommandEnvironment_Impl::handle( - const uno::Reference< task::XInteractionRequest >& rIRequest ) - throw (uno::RuntimeException) -{ - if (!rIRequest.is()) - return; - - uno::Any aAnyRequest(rIRequest->getRequest()); - - ucb::AuthenticationRequest rRequest; - if (!(aAnyRequest >>= rRequest)) - return; - - uno::Sequence< uno::Reference< task::XInteractionContinuation > > - rContinuations = rIRequest->getContinuations(); - - // get continuations - uno::Reference< task::XInteractionRetry > xRetry; - uno::Reference< task::XInteractionAbort > xAbort; - uno::Reference< ucb::XInteractionSupplyAuthentication > - xSupplyAuthentication; - - for (sal_Int32 i = 0; i < rContinuations.getLength(); ++i) { - xRetry = uno::Reference< task::XInteractionRetry >( - rContinuations[i], uno::UNO_QUERY ); - if( xRetry.is() ) - continue; - - xAbort = uno::Reference< task::XInteractionAbort >( - rContinuations[i], uno::UNO_QUERY ); - if (xAbort.is()) - continue; - - xSupplyAuthentication - = uno::Reference< ucb::XInteractionSupplyAuthentication >( - rContinuations[i], uno::UNO_QUERY ); - if( xSupplyAuthentication.is() ) - continue; - } - - bool bRemember; - bool bRememberPersistent; - if (xSupplyAuthentication.is()) - { - ucb::RememberAuthentication eDefault; - uno::Sequence< ucb::RememberAuthentication > aModes( - xSupplyAuthentication->getRememberPasswordModes(eDefault)); - bRemember = eDefault != ucb::RememberAuthentication_NO; - bRememberPersistent = false; - for (sal_Int32 i = 0; i < aModes.getLength(); ++i) - if (aModes[i] == ucb::RememberAuthentication_PERSISTENT) - { - bRememberPersistent = true; - break; - } - } - else - { - bRemember = false; - bRememberPersistent = false; - } - - uno::Reference< task::XPasswordContainer > xContainer; - try - { - xContainer - = uno::Reference< task::XPasswordContainer >( - m_xSMgr->createInstance( - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.task.PasswordContainer"))), - uno::UNO_QUERY); - } - catch (uno::Exception const &) - { - } - - // xContainer works with userName passwdSequences pairs: - if (xContainer.is() && rRequest.HasUserName && rRequest.HasPassword ) - { - try - { - if (rRequest.UserName.getLength() == 0) - { - task::UrlRecord - aRec(xContainer->find(rRequest.ServerName, this)); - if (aRec.UserList.getLength() != 0) - { - if (xSupplyAuthentication->canSetUserName()) - xSupplyAuthentication-> - setUserName(aRec.UserList[0].UserName.getStr()); - if (xSupplyAuthentication->canSetPassword()) - { - OSL_ENSURE(aRec.UserList[0].Passwords.getLength() != 0, - "empty password list"); - xSupplyAuthentication-> - setPassword(aRec.UserList[0].Passwords[0].getStr()); - } - if (aRec.UserList[0].Passwords.getLength() > 1) - { - if (rRequest.HasRealm) - { - if (xSupplyAuthentication->canSetRealm()) - xSupplyAuthentication-> - setRealm(aRec.UserList[0].Passwords[1]. - getStr()); - } - else if (xSupplyAuthentication->canSetAccount()) - xSupplyAuthentication-> - setAccount(aRec.UserList[0].Passwords[1]. - getStr()); - } - xSupplyAuthentication->select(); - return; - } - } - else - { - task::UrlRecord - aRec(xContainer->findForName(rRequest.ServerName, - rRequest.UserName, - this)); - if (aRec.UserList.getLength() != 0) - { - OSL_ENSURE(aRec.UserList[0].Passwords.getLength() != 0, - "empty password list"); - if (!rRequest.HasPassword - || rRequest.Password != aRec.UserList[0].Passwords[0]) - { - if (xSupplyAuthentication->canSetUserName()) - xSupplyAuthentication-> - setUserName(aRec.UserList[0].UserName.getStr()); - if (xSupplyAuthentication->canSetPassword()) - xSupplyAuthentication-> - setPassword(aRec.UserList[0].Passwords[0]. - getStr()); - if (aRec.UserList[0].Passwords.getLength() > 1) - { - if (rRequest.HasRealm) - { - if (xSupplyAuthentication->canSetRealm()) - xSupplyAuthentication-> - setRealm(aRec.UserList[0].Passwords[1]. - getStr()); - } - else if (xSupplyAuthentication->canSetAccount()) - xSupplyAuthentication-> - setAccount(aRec.UserList[0].Passwords[1]. - getStr()); - } - xSupplyAuthentication->select(); - return; - } - } - } - } - catch (task::NoMasterException const &) - {} // user did not enter master password - } - return; -} - -//========================================================================= -//========================================================================= -// // Content Implementation. // //========================================================================= @@ -446,9 +203,28 @@ uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) { try { - return isFolder( new CommandEnvironment_Impl(m_xSMgr) ) - ? aRet - : uno::Any(); + uno::Reference< beans::XPropertySet > const xProps( + m_xSMgr, uno::UNO_QUERY_THROW ); + uno::Reference< uno::XComponentContext > xCtx; + xCtx.set( xProps->getPropertyValue( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ), + uno::UNO_QUERY_THROW ); + + uno::Reference< task::XInteractionHandler > xIH( + task::PasswordContainerInteractionHandler::create( xCtx ) ); + + // Supply a command env to isFolder() that contains an interaction + // handler that uses the password container service to obtain + // credentials without displaying a password gui. + + uno::Reference< ucb::XCommandEnvironment > xCmdEnv( + ucb::CommandEnvironment::create( + xCtx, + xIH, + uno::Reference< ucb::XProgressHandler >() ) ); + + return isFolder( xCmdEnv ) ? aRet : uno::Any(); } catch ( uno::RuntimeException const & ) { @@ -630,17 +406,22 @@ uno::Any SAL_CALL Content::execute( ucb::CommandAbortedException, uno::RuntimeException ) { + OSL_TRACE( ">>>>> Content::execute: start: command: %s, env: %s", + rtl::OUStringToOString( aCommand.Name, + RTL_TEXTENCODING_UTF8 ).getStr(), + Environment.is() ? "present" : "missing" ); + uno::Any aRet; if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) ) { - ////////////////////////////////////////////////////////////////// - // getPropertyValues - ////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////// + // getPropertyValues + ////////////////////////////////////////////////////////////////// uno::Sequence< beans::Property > Properties; - if ( !( aCommand.Argument >>= Properties ) ) + if ( !( aCommand.Argument >>= Properties ) ) { ucbhelper::cancelCommandExecution( uno::makeAny( lang::IllegalArgumentException( @@ -652,17 +433,17 @@ uno::Any SAL_CALL Content::execute( // Unreachable } - aRet <<= getPropertyValues( Properties, Environment ); + aRet <<= getPropertyValues( Properties, Environment ); } else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) ) { - ////////////////////////////////////////////////////////////////// - // setPropertyValues - ////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////// + // setPropertyValues + ////////////////////////////////////////////////////////////////// uno::Sequence< beans::PropertyValue > aProperties; - if ( !( aCommand.Argument >>= aProperties ) ) + if ( !( aCommand.Argument >>= aProperties ) ) { ucbhelper::cancelCommandExecution( uno::makeAny( lang::IllegalArgumentException( @@ -674,7 +455,7 @@ uno::Any SAL_CALL Content::execute( // Unreachable } - if ( !aProperties.getLength() ) + if ( !aProperties.getLength() ) { ucbhelper::cancelCommandExecution( uno::makeAny( lang::IllegalArgumentException( @@ -713,8 +494,8 @@ uno::Any SAL_CALL Content::execute( RTL_CONSTASCII_STRINGPARAM( "open" ) ) ) { ////////////////////////////////////////////////////////////////// - // open - ////////////////////////////////////////////////////////////////// + // open + ////////////////////////////////////////////////////////////////// ucb::OpenCommandArgument2 aOpenCommand; if ( !( aCommand.Argument >>= aOpenCommand ) ) @@ -735,11 +516,11 @@ uno::Any SAL_CALL Content::execute( RTL_CONSTASCII_STRINGPARAM( "insert" ) ) ) { ////////////////////////////////////////////////////////////////// - // insert - ////////////////////////////////////////////////////////////////// + // insert + ////////////////////////////////////////////////////////////////// ucb::InsertCommandArgument arg; - if ( !( aCommand.Argument >>= arg ) ) + if ( !( aCommand.Argument >>= arg ) ) { ucbhelper::cancelCommandExecution( uno::makeAny( lang::IllegalArgumentException( @@ -751,23 +532,23 @@ uno::Any SAL_CALL Content::execute( // Unreachable } - insert( arg.Data, arg.ReplaceExisting, Environment ); + insert( arg.Data, arg.ReplaceExisting, Environment ); } else if ( aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "delete" ) ) ) { - ////////////////////////////////////////////////////////////////// - // delete - ////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////// + // delete + ////////////////////////////////////////////////////////////////// - sal_Bool bDeletePhysical = sal_False; - aCommand.Argument >>= bDeletePhysical; + sal_Bool bDeletePhysical = sal_False; + aCommand.Argument >>= bDeletePhysical; // KSO: Ignore parameter and destroy the content, if you don't support // putting objects into trashcan. ( Since we do not have a trash can // service yet (src603), you actually have no other choice. ) // if ( bDeletePhysical ) -// { +// { try { std::auto_ptr< DAVResourceAccess > xResAccess; @@ -823,7 +604,7 @@ uno::Any SAL_CALL Content::execute( { ////////////////////////////////////////////////////////////////// // post - ////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////// ucb::PostCommandArgument2 aArg; if ( !( aCommand.Argument >>= aArg ) ) @@ -840,20 +621,67 @@ uno::Any SAL_CALL Content::execute( post( aArg, Environment ); } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "lock" ) ) && + supportsExclusiveWriteLock( Environment ) ) + { + ////////////////////////////////////////////////////////////////// + // lock + ////////////////////////////////////////////////////////////////// + + lock( Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "unlock" ) ) && + supportsExclusiveWriteLock( Environment ) ) + { + ////////////////////////////////////////////////////////////////// + // unlock + ////////////////////////////////////////////////////////////////// + + unlock( Environment ); + } + else if ( aCommand.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "createNewContent" ) ) && + isFolder( Environment ) ) + { + ////////////////////////////////////////////////////////////////// + // createNewContent + ////////////////////////////////////////////////////////////////// + + ucb::ContentInfo aArg; + if ( !( aCommand.Argument >>= aArg ) ) + { + ucbhelper::cancelCommandExecution( + uno::makeAny( lang::IllegalArgumentException( + rtl::OUString::createFromAscii( + "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + + aRet = uno::makeAny( createNewContent( aArg ) ); + } else { - ////////////////////////////////////////////////////////////////// - // Unsupported command - ////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////// + // Unsupported command + ////////////////////////////////////////////////////////////////// ucbhelper::cancelCommandExecution( uno::makeAny( ucb::UnsupportedCommandException( - rtl::OUString(), - static_cast< cppu::OWeakObject * >( this ) ) ), + aCommand.Name, + static_cast< cppu::OWeakObject * >( this ) ) ), Environment ); // Unreachable } + OSL_TRACE( "<<<<< Content::execute: end: command: %s", + rtl::OUStringToOString( aCommand.Name, + RTL_TEXTENCODING_UTF8 ).getStr() ); + return aRet; } @@ -863,19 +691,22 @@ void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ ) throw( uno::RuntimeException ) { try + { + std::auto_ptr< DAVResourceAccess > xResAccess; { - std::auto_ptr< DAVResourceAccess > xResAccess; - { - osl::MutexGuard aGuard( m_aMutex ); - xResAccess.reset( - new DAVResourceAccess( *m_xResAccess.get() ) ); - } - xResAccess->ABORT(); + osl::MutexGuard aGuard( m_aMutex ); + xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); } - catch ( DAVException const & /*e*/ ) + xResAccess->abort(); { - // ABORT command failed! + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); } + } + catch ( DAVException const & ) + { + // abort failed! + } } //========================================================================= @@ -893,8 +724,8 @@ void SAL_CALL Content::addProperty( const rtl::OUString& Name, lang::IllegalArgumentException, uno::RuntimeException ) { -// if ( m_bTransient ) -// @@@ ??? +// if ( m_bTransient ) +// @@@ ??? if ( !Name.getLength() ) throw lang::IllegalArgumentException(); @@ -902,8 +733,8 @@ void SAL_CALL Content::addProperty( const rtl::OUString& Name, // Check property type. if ( !UCBDeadPropertyValue::supportsType( DefaultValue.getValueType() ) ) { - OSL_ENSURE( sal_False, "Content::addProperty - " - "Unsupported property type!" ); + OSL_ENSURE( sal_False, + "Content::addProperty - Unsupported property type!" ); throw beans::IllegalTypeException(); } @@ -950,10 +781,10 @@ void SAL_CALL Content::addProperty( const rtl::OUString& Name, // Notify propertyset info change listeners. beans::PropertySetInfoChangeEvent evt( - static_cast< cppu::OWeakObject * >( this ), - Name, - -1, // No handle available - beans::PropertySetInfoChange::PROPERTY_INSERTED ); + static_cast< cppu::OWeakObject * >( this ), + Name, + -1, // No handle available + beans::PropertySetInfoChange::PROPERTY_INSERTED ); notifyPropertySetInfoChange( evt ); } catch ( DAVException const & e ) @@ -1029,7 +860,7 @@ void SAL_CALL Content::removeProperty( const rtl::OUString& Name ) { beans::Property aProp = getPropertySetInfo( xEnv, sal_False /* don't cache data */ ) - ->getPropertyByName( Name ); + ->getPropertyByName( Name ); if ( !( aProp.Attributes & beans::PropertyAttribute::REMOVEABLE ) ) { @@ -1039,7 +870,7 @@ void SAL_CALL Content::removeProperty( const rtl::OUString& Name ) } catch ( beans::UnknownPropertyException const & ) { -// OSL_ENSURE( sal_False, "removeProperty - Unknown property!" ); + //OSL_ENSURE( sal_False, "removeProperty - Unknown property!" ); throw; } #endif @@ -1270,7 +1101,7 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues( const rtl::Reference< ::ucbhelper::ContentProviderImplHelper >& rProvider, const rtl::OUString& rContentId ) { - // Note: Empty sequence means "get values of all supported properties". + // Note: Empty sequence means "get values of all supported properties". rtl::Reference< ::ucbhelper::PropertyValueSet > xRow = new ::ucbhelper::PropertyValueSet( rSMgr ); @@ -1279,10 +1110,10 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues( if ( nCount ) { uno::Reference< beans::XPropertySet > xAdditionalPropSet; - sal_Bool bTriedToGetAdditonalPropSet = sal_False; + sal_Bool bTriedToGetAdditonalPropSet = sal_False; const beans::Property* pProps = rProperties.getConstArray(); - for ( sal_Int32 n = 0; n < nCount; ++n ) + for ( sal_Int32 n = 0; n < nCount; ++n ) { const beans::Property& rProp = pProps[ n ]; @@ -1338,9 +1169,9 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues( // Append all local Additional Properties. uno::Reference< beans::XPropertySet > xSet( - rProvider->getAdditionalPropertySet( rContentId, sal_False ), - uno::UNO_QUERY ); - xRow->appendPropertySet( xSet ); + rProvider->getAdditionalPropertySet( rContentId, sal_False ), + uno::UNO_QUERY ); + xRow->appendPropertySet( xSet ); } return uno::Reference< sdbc::XRow >( xRow.get() ); @@ -1357,8 +1188,8 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues( std::auto_ptr< DAVResourceAccess > xResAccess; rtl::OUString aEscapedTitle; bool bHasAll = false; - uno::Reference< lang::XMultiServiceFactory > xSMgr; - uno::Reference< ucb::XContentIdentifier > xIdentifier; + uno::Reference< lang::XMultiServiceFactory > xSMgr; + uno::Reference< ucb::XContentIdentifier > xIdentifier; rtl::Reference< ::ucbhelper::ContentProviderImplHelper > xProvider; { @@ -1400,15 +1231,19 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues( if ( DAV == rType ) { - // cache lookup... getResourceType may fill the props cache via PROPFIND! + // cache lookup... getResourceType may fill the props cache via + // PROPFIND! if ( m_xCachedProps.get() ) { - xCachedProps.reset( new ContentProperties( *m_xCachedProps.get() ) ); + xCachedProps.reset( + new ContentProperties( *m_xCachedProps.get() ) ); std::vector< rtl::OUString > aMissingProps; - if ( xCachedProps->containsAllNames( rProperties, aMissingProps ) ) + if ( xCachedProps->containsAllNames( + rProperties, aMissingProps ) ) { - // All properties are already in cache! No server access needed. + // All properties are already in cache! No server access + // needed. bHasAll = true; } @@ -1421,7 +1256,8 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues( // Only DAV resources support PROPFIND std::vector< rtl::OUString > aPropNames; - uno::Sequence< beans::Property > aProperties( rProperties.getLength() ); + uno::Sequence< beans::Property > aProperties( + rProperties.getLength() ); if ( m_aFailedPropNames.size() > 0 ) { @@ -1474,7 +1310,8 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues( { if ( xProps.get()) xProps->addProperties( - aPropNames, ContentProperties( resources[ 0 ] )); + aPropNames, + ContentProperties( resources[ 0 ] )); else xProps.reset( new ContentProperties( resources[ 0 ] ) ); @@ -1483,7 +1320,7 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues( catch ( DAVException const & e ) { bNetworkAccessAllowed - = shouldAccessNetworkAfterException( e ); + = shouldAccessNetworkAfterException( e ); if ( !bNetworkAccessAllowed ) { @@ -1523,16 +1360,16 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues( if ( xProps.get() ) xProps->addProperties( - aMissingProps, - ContentProperties( resource ) ); + aMissingProps, + ContentProperties( resource ) ); else xProps.reset ( new ContentProperties( resource ) ); if ( m_eResourceType == NON_DAV ) xProps->addProperties( aMissingProps, ContentProperties( - aEscapedTitle, - false ) ); + aEscapedTitle, + false ) ); } catch ( DAVException const & e ) { @@ -1548,15 +1385,15 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues( } } } + // might trigger HTTP redirect. - // Therefore, title must be upadated here. + // Therefore, title must be updated here. NeonUri aUri( xResAccess->getURL() ); aEscapedTitle = aUri.GetPathBaseName(); if ( UNKNOWN == rType ) { - xProps.reset( - new ContentProperties( aEscapedTitle ) ); + xProps.reset( new ContentProperties( aEscapedTitle ) ); } // For DAV resources we only know the Title, for non-DAV @@ -1565,31 +1402,29 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues( { //xProps.reset( // new ContentProperties( aEscapedTitle ) ); - xProps->addProperty( rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "Title" )), - uno::makeAny( aEscapedTitle), true); + xProps->addProperty( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + uno::makeAny( aEscapedTitle ), + true ); } else { if ( !xProps.get() ) - xProps.reset( - new ContentProperties( aEscapedTitle, false ) ); + xProps.reset( new ContentProperties( aEscapedTitle, false ) ); else - xProps->addProperty( rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "Title" )), - uno::makeAny( aEscapedTitle), true); - - xProps->addProperty( rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "IsFolder" )), - uno::makeAny( false), true); - xProps->addProperty( rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "IsDocument" )), - uno::makeAny( true), true); + xProps->addProperty( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ), + uno::makeAny( aEscapedTitle ), + true ); + xProps->addProperty( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ), + uno::makeAny( false ), + true ); + xProps->addProperty( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ), + uno::makeAny( true ), + true ); } } else @@ -1601,16 +1436,35 @@ uno::Reference< sdbc::XRow > Content::getPropertyValues( m_bCollection ) ); } - // Add BaseURI property, if requested. - if ( !xProps->contains( - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BaseURI" ) ) ) ) + sal_Int32 nCount = rProperties.getLength(); + for ( sal_Int32 n = 0; n < nCount; ++n ) { - xProps->addProperty( rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "BaseURI" ) ), - uno::makeAny( - getBaseURI( xResAccess ) ), - true ); + const rtl::OUString rName = rProperties[ n ].Name; + if ( rName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "BaseURI" ) ) ) + { + // Add BaseURI property, if requested. + xProps->addProperty( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BaseURI" ) ), + uno::makeAny( getBaseURI( xResAccess ) ), + true ); + } + else if ( rName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) + { + // Add CreatableContentsInfo property, if requested. + sal_Bool bFolder = sal_False; + xProps->getValue( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ) ) + >>= bFolder; + xProps->addProperty( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "CreatableContentsInfo" ) ), + uno::makeAny( bFolder + ? queryCreatableContentsInfo() + : uno::Sequence< ucb::ContentInfo >() ), + true ); + } } uno::Reference< sdbc::XRow > xResultRow @@ -1663,7 +1517,7 @@ uno::Sequence< uno::Any > Content::setPropertyValues( beans::PropertyChangeEvent aEvent; aEvent.Source = static_cast< cppu::OWeakObject * >( this ); - aEvent.Further = sal_False; + aEvent.Further = sal_False; // aEvent.PropertyName = aEvent.PropertyHandle = -1; // aEvent.OldValue = @@ -1724,7 +1578,7 @@ uno::Sequence< uno::Any > Content::setPropertyValues( static_cast< cppu::OWeakObject * >( this ) ); } else if ( rName.equalsAsciiL( - RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) + RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) { // Read-only property! aRet[ n ] <<= lang::IllegalAccessException( @@ -1843,6 +1697,15 @@ uno::Sequence< uno::Any > Content::setPropertyValues( "Property is read-only!" ), static_cast< cppu::OWeakObject * >( this ) ); } + if ( rName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) ) + { + // Read-only property! + aRet[ n ] <<= lang::IllegalAccessException( + rtl::OUString::createFromAscii( + "Property is read-only!" ), + static_cast< cppu::OWeakObject * >( this ) ); + } else { if ( getResourceType( xEnv, xResAccess ) == DAV ) @@ -2035,7 +1898,7 @@ uno::Sequence< uno::Any > Content::setPropertyValues( aEvent.OldValue = uno::makeAny( aOldTitle ); aEvent.NewValue = uno::makeAny( aNewTitle ); - m_aEscapedTitle = NeonUri::escapeSegment( aNewTitle ); + m_aEscapedTitle = NeonUri::escapeSegment( aNewTitle ); aChanges.getArray()[ nChanged ] = aEvent; nChanged++; @@ -2043,8 +1906,8 @@ uno::Sequence< uno::Any > Content::setPropertyValues( if ( nChanged > 0 ) { - aChanges.realloc( nChanged ); - notifyPropertiesChange( aChanges ); + aChanges.realloc( nChanged ); + notifyPropertiesChange( aChanges ); } { @@ -2150,7 +2013,8 @@ uno::Any Content::open( // cache headers. if ( !m_xCachedProps.get()) - m_xCachedProps.reset( new ContentProperties( aResource ) ); + m_xCachedProps.reset( + new ContentProperties( aResource ) ); else m_xCachedProps->addProperties( aResource ); @@ -2195,9 +2059,11 @@ uno::Any Content::open( // cache headers. if ( !m_xCachedProps.get()) - m_xCachedProps.reset( new ContentProperties( aResource ) ); + m_xCachedProps.reset( + new ContentProperties( aResource ) ); else - m_xCachedProps->addProperties( aResource.properties ); + m_xCachedProps->addProperties( + aResource.properties ); m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); @@ -2407,17 +2273,17 @@ void Content::insert( { /* [RFC 2616] - HTTP - The PUT method requests that the enclosed entity be stored under the - supplied Request-URI. If the Request-URI refers to an already - existing resource, the enclosed entity SHOULD be considered as a - modified version of the one residing on the origin server. + The PUT method requests that the enclosed entity be stored under the + supplied Request-URI. If the Request-URI refers to an already + existing resource, the enclosed entity SHOULD be considered as a + modified version of the one residing on the origin server. */ /* [RFC 2518] - WebDAV - MKCOL creates a new collection resource at the location specified by - the Request-URI. If the resource identified by the Request-URI is - non-null then the MKCOL MUST fail. + MKCOL creates a new collection resource at the location specified by + the Request-URI. If the resource identified by the Request-URI is + non-null then the MKCOL MUST fail. */ // ==> Complain on PUT, continue on MKCOL. @@ -2887,6 +2753,99 @@ void Content::destroy( sal_Bool bDeletePhysical ) } //========================================================================= +bool Content::supportsExclusiveWriteLock( + const uno::Reference< ucb::XCommandEnvironment >& Environment ) +{ + if ( getResourceType( Environment ) == DAV ) + { + if ( m_xCachedProps.get() ) + { + uno::Sequence< ucb::LockEntry > aSupportedLocks; + if ( m_xCachedProps->getValue( DAVProperties::SUPPORTEDLOCK ) + >>= aSupportedLocks ) + { + for ( sal_Int32 n = 0; n < aSupportedLocks.getLength(); ++n ) + { + if ( aSupportedLocks[ n ].Scope + == ucb::LockScope_EXCLUSIVE && + aSupportedLocks[ n ].Type + == ucb::LockType_WRITE ) + return true; + } + } + } + } + return false; +} + +//========================================================================= +void Content::lock( + const uno::Reference< ucb::XCommandEnvironment >& Environment ) + throw( uno::Exception ) +{ + try + { + std::auto_ptr< DAVResourceAccess > xResAccess; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); + } + + uno::Any aOwnerAny; + aOwnerAny + <<= rtl::OUString::createFromAscii( "http://ucb.openoffice.org" ); + + ucb::Lock aLock( + ucb::LockScope_EXCLUSIVE, + ucb::LockType_WRITE, + ucb::LockDepth_ZERO, + aOwnerAny, + 180, // lock timeout in secs + //-1, // infinite lock + uno::Sequence< ::rtl::OUString >() ); + + xResAccess->LOCK( aLock, Environment ); + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); + } + } + catch ( DAVException const & e ) + { + cancelCommandExecution( e, Environment, sal_False ); + // Unreachable + } +} + +//========================================================================= +void Content::unlock( + const uno::Reference< ucb::XCommandEnvironment >& Environment ) + throw( uno::Exception ) +{ + try + { + std::auto_ptr< DAVResourceAccess > xResAccess; + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); + } + + xResAccess->UNLOCK( Environment ); + + { + osl::Guard< osl::Mutex > aGuard( m_aMutex ); + m_xResAccess.reset( new DAVResourceAccess( *xResAccess.get() ) ); + } + } + catch ( DAVException const & e ) + { + cancelCommandExecution( e, Environment, sal_False ); + // Unreachable + } +} + +//========================================================================= sal_Bool Content::exchangeIdentity( const uno::Reference< ucb::XContentIdentifier >& xNewId ) { @@ -2936,9 +2895,9 @@ sal_Bool Content::exchangeIdentity( 0, aOldURL.getLength(), xNewId->getContentIdentifier() ); - uno::Reference< ucb::XContentIdentifier > - xNewChildId - = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewChildURL ); + uno::Reference< ucb::XContentIdentifier > xNewChildId + = new ::ucbhelper::ContentIdentifier( + m_xSMgr, aNewChildURL ); if ( !xChild->exchangeIdentity( xNewChildId ) ) return sal_False; @@ -3010,7 +2969,6 @@ uno::Any Content::MapDAVException( const DAVException & e, sal_Bool bWrite ) aArgs ); return aException; } - default: break; } @@ -3022,14 +2980,14 @@ uno::Any Content::MapDAVException( const DAVException & e, sal_Bool bWrite ) if ( bWrite ) aException <<= ucb::InteractiveNetworkWriteException( - rtl::OUString(), + e.getData(), static_cast< cppu::OWeakObject * >( this ), task::InteractionClassification_ERROR, e.getData() ); else aException <<= ucb::InteractiveNetworkReadException( - rtl::OUString(), + e.getData(), static_cast< cppu::OWeakObject * >( this ), task::InteractionClassification_ERROR, e.getData() ); @@ -3046,12 +3004,12 @@ uno::Any Content::MapDAVException( const DAVException & e, sal_Bool bWrite ) break; // @@@ No matching InteractiveNetwork*Exception -// case DAVException::DAV_HTTP_AUTH: -// break; +// case DAVException::DAV_HTTP_AUTH: +// break; // @@@ No matching InteractiveNetwork*Exception -// case DAVException::DAV_HTTP_AUTHPROXY: -// break; +// case DAVException::DAV_HTTP_AUTHPROXY: +// break; case DAVException::DAV_HTTP_CONNECT: aException <<= @@ -3063,16 +3021,16 @@ uno::Any Content::MapDAVException( const DAVException & e, sal_Bool bWrite ) break; // @@@ No matching InteractiveNetwork*Exception -// case DAVException::DAV_HTTP_TIMEOUT: -// break; +// case DAVException::DAV_HTTP_TIMEOUT: +// break; // @@@ No matching InteractiveNetwork*Exception -// case DAVException::DAV_HTTP_REDIRECT: -// break; +// case DAVException::DAV_HTTP_REDIRECT: +// break; // @@@ No matching InteractiveNetwork*Exception -// case DAVException::DAV_SESSION_CREATE: -// break; +// case DAVException::DAV_SESSION_CREATE: +// break; case DAVException::DAV_INVALID_ARG: aException <<= @@ -3082,6 +3040,62 @@ uno::Any Content::MapDAVException( const DAVException & e, sal_Bool bWrite ) -1 ); break; + case DAVException::DAV_LOCKED: +#if 1 + aException <<= + ucb::InteractiveLockingLockedException( + rtl::OUString::createFromAscii( "Locked!" ), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + m_xIdentifier->getContentIdentifier(), + sal_True ); +#else + { + uno::Sequence< uno::Any > aArgs( 1 ); + aArgs[ 0 ] <<= beans::PropertyValue( + rtl::OUString::createFromAscii("Uri"), -1, + uno::makeAny(m_xIdentifier->getContentIdentifier()), + beans::PropertyState_DIRECT_VALUE); + + aException <<= + ucb::InteractiveAugmentedIOException( + rtl::OUString::createFromAscii( "Locked!" ), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + ucb::IOErrorCode_LOCKING_VIOLATION, + aArgs ); + } +#endif + break; + + case DAVException::DAV_LOCKED_SELF: + aException <<= + ucb::InteractiveLockingLockedException( + rtl::OUString::createFromAscii( "Locked (self)!" ), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + m_xIdentifier->getContentIdentifier(), + sal_True ); + break; + + case DAVException::DAV_NOT_LOCKED: + aException <<= + ucb::InteractiveLockingNotLockedException( + rtl::OUString::createFromAscii( "Not locked!" ), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + m_xIdentifier->getContentIdentifier() ); + break; + + case DAVException::DAV_LOCK_EXPIRED: + aException <<= + ucb::InteractiveLockingLockExpiredException( + rtl::OUString::createFromAscii( "Lock expired!" ), + static_cast< cppu::OWeakObject * >( this ), + task::InteractionClassification_ERROR, + m_xIdentifier->getContentIdentifier() ); + break; + default: aException <<= ucb::InteractiveNetworkGeneralException( @@ -3120,7 +3134,8 @@ void Content::cancelCommandExecution( } //========================================================================= -const rtl::OUString Content::getBaseURI( const std::auto_ptr< DAVResourceAccess > & rResAccess ) +const rtl::OUString +Content::getBaseURI( const std::auto_ptr< DAVResourceAccess > & rResAccess ) { osl::Guard< osl::Mutex > aGuard( m_aMutex ); @@ -3181,11 +3196,17 @@ const Content::ResourceType & Content::getResourceType( // this is a DAV resource. std::vector< DAVResource > resources; std::vector< rtl::OUString > aPropNames; - uno::Sequence< beans::Property > aProperties( 4 ); - aProperties[ 0 ].Name = rtl::OUString::createFromAscii( "IsFolder" ); - aProperties[ 1 ].Name = rtl::OUString::createFromAscii( "IsDocument" ); - aProperties[ 2 ].Name = rtl::OUString::createFromAscii( "IsReadOnly" ); - aProperties[ 3 ].Name = rtl::OUString::createFromAscii( "MediaType" ); + uno::Sequence< beans::Property > aProperties( 5 ); + aProperties[ 0 ].Name + = rtl::OUString::createFromAscii( "IsFolder" ); + aProperties[ 1 ].Name + = rtl::OUString::createFromAscii( "IsDocument" ); + aProperties[ 2 ].Name + = rtl::OUString::createFromAscii( "IsReadOnly" ); + aProperties[ 3 ].Name + = rtl::OUString::createFromAscii( "MediaType" ); + aProperties[ 4 ].Name + = DAVProperties::SUPPORTEDLOCK; ContentProperties::UCBNamesToDAVNames( aProperties, aPropNames ); @@ -3195,16 +3216,19 @@ const Content::ResourceType & Content::getResourceType( if ( resources.size() == 1 ) { - m_xCachedProps.reset( new ContentProperties( resources[ 0 ] ) ); - m_xCachedProps->containsAllNames( aProperties, m_aFailedPropNames ); + m_xCachedProps.reset( + new ContentProperties( resources[ 0 ] ) ); + m_xCachedProps->containsAllNames( + aProperties, m_aFailedPropNames ); } + eResourceType = DAV; } - catch ( DAVException const& e) + catch ( DAVException const & e ) { rResAccess->resetUri(); - if (e.getStatus() == SC_METHOD_NOT_ALLOWED) + if ( e.getStatus() == SC_METHOD_NOT_ALLOWED ) { // Status SC_METHOD_NOT_ALLOWED is a safe indicator that the // resource is NON_DAV @@ -3213,7 +3237,6 @@ const Content::ResourceType & Content::getResourceType( } } m_eResourceType = eResourceType; - } return m_eResourceType; } diff --git a/ucb/source/ucp/webdav/webdavcontent.hxx b/ucb/source/ucp/webdav/webdavcontent.hxx index 861e48bdfcee..caf6ec9677a9 100644 --- a/ucb/source/ucp/webdav/webdavcontent.hxx +++ b/ucb/source/ucp/webdav/webdavcontent.hxx @@ -88,7 +88,7 @@ class Content : public ::ucbhelper::ContentImplHelper, rtl::OUString m_aEscapedTitle; ResourceType m_eResourceType; ContentProvider* m_pProvider; // No need for a ref, base class holds object - bool m_bTransient; + bool m_bTransient; bool m_bCollection; bool m_bDidGetOrHead; std::vector< rtl::OUString > m_aFailedPropNames; @@ -96,81 +96,91 @@ class Content : public ::ucbhelper::ContentImplHelper, private: virtual com::sun::star::uno::Sequence< com::sun::star::beans::Property > getProperties( const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv ); + com::sun::star::ucb::XCommandEnvironment > & xEnv ); virtual com::sun::star::uno::Sequence< com::sun::star::ucb::CommandInfo > getCommands( const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv ); - virtual ::rtl::OUString getParentURL(); + com::sun::star::ucb::XCommandEnvironment > & xEnv ); + virtual ::rtl::OUString getParentURL(); - sal_Bool isFolder( const ::com::sun::star::uno::Reference< - ::com::sun::star::ucb::XCommandEnvironment >& xEnv ) + sal_Bool isFolder( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv ) throw ( ::com::sun::star::uno::Exception ); - ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > - getPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& rProperties, - const ::com::sun::star::uno::Reference< - ::com::sun::star::ucb::XCommandEnvironment >& xEnv ) + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv ) throw ( ::com::sun::star::uno::Exception ); ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > - setPropertyValues( - const ::com::sun::star::uno::Sequence< - ::com::sun::star::beans::PropertyValue >& rValues, - const ::com::sun::star::uno::Reference< - ::com::sun::star::ucb::XCommandEnvironment >& xEnv ) + setPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue >& rValues, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv ) throw ( ::com::sun::star::uno::Exception ); typedef rtl::Reference< Content > ContentRef; - typedef std::list< ContentRef > ContentRefList; - void queryChildren( ContentRefList& rChildren); + typedef std::list< ContentRef > ContentRefList; + void queryChildren( ContentRefList& rChildren); - sal_Bool exchangeIdentity( - const ::com::sun::star::uno::Reference< - ::com::sun::star::ucb::XContentIdentifier >& xNewId ); + sal_Bool + exchangeIdentity( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& xNewId ); - const rtl::OUString getBaseURI( const std::auto_ptr< DAVResourceAccess > & rResAccess ); + const rtl::OUString + getBaseURI( const std::auto_ptr< DAVResourceAccess > & rResAccess ); - const ResourceType & getResourceType( - const ::com::sun::star::uno::Reference< - ::com::sun::star::ucb::XCommandEnvironment >& xEnv ) + const ResourceType & + getResourceType( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv ) throw ( ::com::sun::star::uno::Exception ); - const ResourceType & getResourceType( - const ::com::sun::star::uno::Reference< - ::com::sun::star::ucb::XCommandEnvironment >& xEnv, - const std::auto_ptr< DAVResourceAccess > & rResAccess ) + const ResourceType & + getResourceType( const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XCommandEnvironment >& xEnv, + const std::auto_ptr< DAVResourceAccess > & rResAccess ) throw ( ::com::sun::star::uno::Exception ); // Command "open" com::sun::star::uno::Any open( const com::sun::star::ucb::OpenCommandArgument2 & rArg, const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv ) + com::sun::star::ucb::XCommandEnvironment > & xEnv ) throw( ::com::sun::star::uno::Exception ); // Command "post" void post( const com::sun::star::ucb::PostCommandArgument2 & rArg, const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment > & xEnv ) + com::sun::star::ucb::XCommandEnvironment > & xEnv ) throw( ::com::sun::star::uno::Exception ); - // Command "insert" - void insert( const ::com::sun::star::uno::Reference< - ::com::sun::star::io::XInputStream > & xInputStream, - sal_Bool bReplaceExisting, - const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment >& Environment ) + // Command "insert" + void insert( const ::com::sun::star::uno::Reference< + ::com::sun::star::io::XInputStream > & xInputStream, + sal_Bool bReplaceExisting, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) throw( ::com::sun::star::uno::Exception ); // Command "transfer" void transfer( const ::com::sun::star::ucb::TransferInfo & rArgs, const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment >& Environment ) + com::sun::star::ucb::XCommandEnvironment >& Environment ) throw( ::com::sun::star::uno::Exception ); // Command "delete" - void destroy( sal_Bool bDeletePhysical ) + void destroy( sal_Bool bDeletePhysical ) + throw( ::com::sun::star::uno::Exception ); + + // Command "lock" + void lock( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) + throw( ::com::sun::star::uno::Exception ); + + // Command "unlock" + void unlock( const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) throw( ::com::sun::star::uno::Exception ); ::com::sun::star::uno::Any MapDAVException( const DAVException & e, @@ -184,57 +194,62 @@ private: static bool shouldAccessNetworkAfterException( const DAVException & e ); + bool supportsExclusiveWriteLock( + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ); + public: - Content( const ::com::sun::star::uno::Reference< - ::com::sun::star::lang::XMultiServiceFactory >& rxSMgr, - ContentProvider* pProvider, - const ::com::sun::star::uno::Reference< - ::com::sun::star::ucb::XContentIdentifier >& Identifier, + Content( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& Identifier, rtl::Reference< DAVSessionFactory > const & rSessionFactory ) throw ( ::com::sun::star::ucb::ContentCreationException ); - Content( const ::com::sun::star::uno::Reference< - ::com::sun::star::lang::XMultiServiceFactory >& rxSMgr, - ContentProvider* pProvider, - const ::com::sun::star::uno::Reference< - ::com::sun::star::ucb::XContentIdentifier >& Identifier, + Content( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rxSMgr, + ContentProvider* pProvider, + const ::com::sun::star::uno::Reference< + ::com::sun::star::ucb::XContentIdentifier >& Identifier, rtl::Reference< DAVSessionFactory > const & rSessionFactory, - sal_Bool isCollection ) + sal_Bool isCollection ) throw ( ::com::sun::star::ucb::ContentCreationException ); - virtual ~Content(); + virtual ~Content(); - // XInterface - XINTERFACE_DECL() + // XInterface + XINTERFACE_DECL() // XTypeProvider XTYPEPROVIDER_DECL() // XServiceInfo virtual ::rtl::OUString SAL_CALL - getImplementationName() + getImplementationName() throw( ::com::sun::star::uno::RuntimeException ); - virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL - getSupportedServiceNames() + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException ); - // XContent - virtual rtl::OUString SAL_CALL - getContentType() + // XContent + virtual rtl::OUString SAL_CALL + getContentType() throw( com::sun::star::uno::RuntimeException ); - // XCommandProcessor - virtual com::sun::star::uno::Any SAL_CALL - execute( const com::sun::star::ucb::Command& aCommand, - sal_Int32 CommandId, - const com::sun::star::uno::Reference< - com::sun::star::ucb::XCommandEnvironment >& Environment ) + // XCommandProcessor + virtual com::sun::star::uno::Any SAL_CALL + execute( const com::sun::star::ucb::Command& aCommand, + sal_Int32 CommandId, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& Environment ) throw( com::sun::star::uno::Exception, - com::sun::star::ucb::CommandAbortedException, - com::sun::star::uno::RuntimeException ); - virtual void SAL_CALL - abort( sal_Int32 CommandId ) + com::sun::star::ucb::CommandAbortedException, + com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL + abort( sal_Int32 CommandId ) throw( com::sun::star::uno::RuntimeException ); - // XPropertyContainer + // XPropertyContainer virtual void SAL_CALL addProperty( const rtl::OUString& Name, sal_Int16 Attributes, @@ -250,36 +265,36 @@ public: com::sun::star::beans::NotRemoveableException, com::sun::star::uno::RuntimeException ); - ////////////////////////////////////////////////////////////////////// - // Additional interfaces - ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + // Additional interfaces + ////////////////////////////////////////////////////////////////////// - // XContentCreator + // XContentCreator virtual com::sun::star::uno::Sequence< com::sun::star::ucb::ContentInfo > SAL_CALL - queryCreatableContentsInfo() + queryCreatableContentsInfo() throw( com::sun::star::uno::RuntimeException ); - virtual com::sun::star::uno::Reference< - com::sun::star::ucb::XContent > SAL_CALL - createNewContent( const com::sun::star::ucb::ContentInfo& Info ) + virtual com::sun::star::uno::Reference< + com::sun::star::ucb::XContent > SAL_CALL + createNewContent( const com::sun::star::ucb::ContentInfo& Info ) throw( com::sun::star::uno::RuntimeException ); - ////////////////////////////////////////////////////////////////////// - // Non-interface methods. - ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + // Non-interface methods. + ////////////////////////////////////////////////////////////////////// DAVResourceAccess & getResourceAccess() { return *m_xResAccess; } - // Called from resultset data supplier. - static ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > - getPropertyValues( const ::com::sun::star::uno::Reference< - ::com::sun::star::lang::XMultiServiceFactory >& rSMgr, + // Called from resultset data supplier. + static ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRow > + getPropertyValues( const ::com::sun::star::uno::Reference< + ::com::sun::star::lang::XMultiServiceFactory >& rSMgr, const ::com::sun::star::uno::Sequence< - ::com::sun::star::beans::Property >& rProperties, - const ContentProperties& rData, + ::com::sun::star::beans::Property >& rProperties, + const ContentProperties& rData, const rtl::Reference< ::ucbhelper::ContentProviderImplHelper >& rProvider, - const ::rtl::OUString& rContentId ); + const ::rtl::OUString& rContentId ); }; } diff --git a/ucb/source/ucp/webdav/webdavcontentcaps.cxx b/ucb/source/ucp/webdav/webdavcontentcaps.cxx index 305d509b4e2c..7f3c20eb0840 100644 --- a/ucb/source/ucp/webdav/webdavcontentcaps.cxx +++ b/ucb/source/ucp/webdav/webdavcontentcaps.cxx @@ -31,7 +31,7 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_ucb.hxx" /************************************************************************** - TODO + TODO ************************************************************************** *************************************************************************/ @@ -41,24 +41,19 @@ #include <com/sun/star/beans/PropertyAttribute.hpp> #include <com/sun/star/beans/PropertyValue.hpp> #include <com/sun/star/ucb/CommandInfo.hpp> +#include <com/sun/star/ucb/ContentInfo.hpp> #include <com/sun/star/ucb/OpenCommandArgument2.hpp> #include <com/sun/star/ucb/InsertCommandArgument.hpp> #include <com/sun/star/ucb/PostCommandArgument2.hpp> #include <com/sun/star/ucb/TransferInfo.hpp> #include <com/sun/star/uno/Sequence.hxx> -#ifndef _COM_SUN_STAR_UTIL_DATETIME_HXX_ #include <com/sun/star/util/DateTime.hpp> -#endif #include <com/sun/star/ucb/Link.hpp> #include <com/sun/star/ucb/Lock.hpp> #include <com/sun/star/ucb/LockEntry.hpp> #include "webdavcontent.hxx" -#ifndef _WEBDAV_UCP_PROVIDFER_HXX #include "webdavprovider.hxx" -#endif -#ifndef _WEBDAV_SESSION_HXX #include "DAVSession.hxx" -#endif #include "ContentProperties.hxx" using namespace com::sun::star; @@ -162,6 +157,16 @@ bool ContentProvider::getProperty( beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); + m_pProps->insert( + beans::Property( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ), + -1, + getCppuType( static_cast< + const uno::Sequence< ucb::ContentInfo > * >( 0 ) ), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::READONLY ) ); + // Standard DAV properties. m_pProps->insert( @@ -221,17 +226,16 @@ bool ContentProvider::getProperty( m_pProps->insert( beans::Property( - DAVProperties::LOCKDISCOVERY, + DAVProperties::LOCKDISCOVERY, -1, getCppuType( static_cast< - const uno::Sequence< - com::sun::star::ucb::Lock > * >( 0 ) ), + const uno::Sequence< ucb::Lock > * >( 0 ) ), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); m_pProps->insert( beans::Property( - DAVProperties::RESOURCETYPE, + DAVProperties::RESOURCETYPE, -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ), beans::PropertyAttribute::BOUND @@ -239,27 +243,25 @@ bool ContentProvider::getProperty( m_pProps->insert( beans::Property( - DAVProperties::SOURCE, + DAVProperties::SOURCE, -1, getCppuType( static_cast< - const uno::Sequence< - com::sun::star::ucb::Link > * >( 0 ) ), + const uno::Sequence< ucb::Link > * >( 0 ) ), beans::PropertyAttribute::BOUND ) ); m_pProps->insert( beans::Property( - DAVProperties::SUPPORTEDLOCK, + DAVProperties::SUPPORTEDLOCK, -1, getCppuType( static_cast< const uno::Sequence< - com::sun::star::ucb::LockEntry > * >( - 0 ) ), + ucb::LockEntry > * >( 0 ) ), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ) ); m_pProps->insert( beans::Property( - DAVProperties::EXECUTABLE, + DAVProperties::EXECUTABLE, -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ), beans::PropertyAttribute::BOUND ) ); @@ -301,7 +303,7 @@ bool ContentProvider::getProperty( // virtual uno::Sequence< beans::Property > Content::getProperties( - const uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv ) + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) { sal_Bool bTransient; std::auto_ptr< DAVResourceAccess > xResAccess; @@ -314,7 +316,8 @@ uno::Sequence< beans::Property > Content::getProperties( bTransient = m_bTransient; xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) ); if ( m_xCachedProps.get() ) - xCachedProps.reset( new ContentProperties( *m_xCachedProps.get() ) ); + xCachedProps.reset( + new ContentProperties( *m_xCachedProps.get() ) ); xProvider.set( m_pProvider ); } @@ -356,6 +359,7 @@ uno::Sequence< beans::Property > Content::getProperties( sal_Bool bHasDateModified = sal_False; sal_Bool bHasMediaType = sal_False; sal_Bool bHasSize = sal_False; + sal_Bool bHasCreatableInfos = sal_False; { std::set< rtl::OUString >::const_iterator it = aPropSet.begin(); @@ -436,7 +440,13 @@ uno::Sequence< beans::Property > Content::getProperties( { bHasSize = sal_True; } - + else if ( !bHasCreatableInfos && + (*it).equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "CreatableContentsInfo" ) ) ) + { + bHasCreatableInfos = sal_True; + } it++; } } @@ -486,6 +496,11 @@ uno::Sequence< beans::Property > Content::getProperties( aPropSet.insert( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Size" ) ) ); + if ( !bHasCreatableInfos ) + aPropSet.insert( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "CreatableContentsInfo" ) ) ); + // Add cached properties, if present and still missing. if ( xCachedProps.get() ) { @@ -525,236 +540,136 @@ uno::Sequence< beans::Property > Content::getProperties( //========================================================================= // virtual -uno::Sequence< com::sun::star::ucb::CommandInfo > Content::getCommands( - const uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv ) +uno::Sequence< ucb::CommandInfo > Content::getCommands( + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) { osl::Guard< osl::Mutex > aGuard( m_aMutex ); - sal_Bool bFolder = sal_False; - - try - { - bFolder = isFolder( xEnv ); - } - catch ( uno::Exception const & ) - { - static com::sun::star::ucb::CommandInfo aDefaultCommandInfoTable[] = - { - /////////////////////////////////////////////////////////////// - // Just mandatory commands avail. - /////////////////////////////////////////////////////////////// - - com::sun::star::ucb::CommandInfo( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), - -1, - getCppuVoidType() - ), - com::sun::star::ucb::CommandInfo( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), - -1, - getCppuVoidType() - ), - com::sun::star::ucb::CommandInfo( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), - -1, - getCppuType( static_cast< - uno::Sequence< beans::Property > * >( 0 ) ) - ), - com::sun::star::ucb::CommandInfo( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), - -1, - getCppuType( static_cast< - uno::Sequence< beans::PropertyValue > * >( 0 ) ) - ) - }; - return uno::Sequence< com::sun::star::ucb::CommandInfo >( - aDefaultCommandInfoTable, 4 ); - } - - if ( bFolder ) - { - //================================================================= - // - // Folder: Supported commands - // - //================================================================= + uno::Sequence< ucb::CommandInfo > aCmdInfo( 8 ); - static com::sun::star::ucb::CommandInfo aFolderCommandInfoTable[] = - { - /////////////////////////////////////////////////////////////// - // Required commands - /////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////// + // Mandatory commands + /////////////////////////////////////////////////////////////// - com::sun::star::ucb::CommandInfo( + aCmdInfo[ 0 ] = + ucb::CommandInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), -1, - getCppuVoidType() - ), - com::sun::star::ucb::CommandInfo( + getCppuVoidType() ); + aCmdInfo[ 1 ] = + ucb::CommandInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), -1, - getCppuVoidType() - ), - com::sun::star::ucb::CommandInfo( + getCppuVoidType() ); + aCmdInfo[ 2 ] = + ucb::CommandInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), -1, getCppuType( static_cast< - uno::Sequence< beans::Property > * >( 0 ) ) - ), - com::sun::star::ucb::CommandInfo( + uno::Sequence< beans::Property > * >( 0 ) ) ); + aCmdInfo[ 3 ] = + ucb::CommandInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), -1, getCppuType( static_cast< - uno::Sequence< beans::PropertyValue > * >( 0 ) ) - ), + uno::Sequence< beans::PropertyValue > * >( 0 ) ) ); - /////////////////////////////////////////////////////////////// - // Optional standard commands - /////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////////// - com::sun::star::ucb::CommandInfo( + aCmdInfo[ 4 ] = + ucb::CommandInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), -1, - getCppuBooleanType() - ), - com::sun::star::ucb::CommandInfo( + getCppuBooleanType() ); + aCmdInfo[ 5 ] = + ucb::CommandInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), -1, getCppuType( static_cast< - com::sun::star::ucb::InsertCommandArgument * >( 0 ) ) - ), - com::sun::star::ucb::CommandInfo( + ucb::InsertCommandArgument * >( 0 ) ) ); + aCmdInfo[ 6 ] = + ucb::CommandInfo( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), -1, getCppuType( static_cast< - com::sun::star::ucb::OpenCommandArgument2 * >( 0 ) ) - ), - com::sun::star::ucb::CommandInfo( - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), - -1, - getCppuType( static_cast< - com::sun::star::ucb::TransferInfo * >( 0 ) ) - ) + ucb::OpenCommandArgument2 * >( 0 ) ) ); - /////////////////////////////////////////////////////////////// - // New commands - /////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////// + // New commands + /////////////////////////////////////////////////////////////// - /* - com::sun::star::ucb::CommandInfo( - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "COPY" ) ), - -1, - getCppuType( static_cast< const rtl::OUString * >( 0 ) ), - ), - com::sun::star::ucb::CommandInfo( - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MOVE" ) ), + aCmdInfo[ 7 ] = + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "post" ) ), -1, - getCppuType( static_cast< const rtl::OUString * >( 0 ) ), - ) - */ - }; + getCppuType( static_cast< + ucb::PostCommandArgument2 * >( 0 ) ) ); + + sal_Bool bFolder = sal_False; - return uno::Sequence< com::sun::star::ucb::CommandInfo >( - aFolderCommandInfoTable, 8 ); + try + { + bFolder = isFolder( xEnv ); } - else + catch ( uno::Exception const & ) { - //================================================================= - // - // Document: Supported commands - // - //================================================================= + return aCmdInfo; + } - static com::sun::star::ucb::CommandInfo aDocumentCommandInfoTable[] = - { - /////////////////////////////////////////////////////////////// - // Required commands - /////////////////////////////////////////////////////////////// + sal_Bool bSupportsLocking = supportsExclusiveWriteLock( xEnv ); - com::sun::star::ucb::CommandInfo( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ), - -1, - getCppuVoidType() - ), - com::sun::star::ucb::CommandInfo( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ), - -1, - getCppuVoidType() - ), - com::sun::star::ucb::CommandInfo( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ), - -1, - getCppuType( static_cast< - uno::Sequence< beans::Property > * >( 0 ) ) - ), - com::sun::star::ucb::CommandInfo( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ), - -1, - getCppuType( static_cast< - uno::Sequence< beans::PropertyValue > * >( 0 ) ) - ), + sal_Int32 nPos = aCmdInfo.getLength(); + sal_Int32 nMoreCmds = ( bFolder ? 2 : 0 ) + ( bSupportsLocking ? 2 : 0 ); + if ( nMoreCmds ) + aCmdInfo.realloc( nPos + nMoreCmds ); + else + return aCmdInfo; - /////////////////////////////////////////////////////////////// - // Optional standard commands - /////////////////////////////////////////////////////////////// + if ( bFolder ) + { + /////////////////////////////////////////////////////////////// + // Optional standard commands + /////////////////////////////////////////////////////////////// - com::sun::star::ucb::CommandInfo( - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ), - -1, - getCppuBooleanType() - ), - com::sun::star::ucb::CommandInfo( - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ), + aCmdInfo[ nPos ] = + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), -1, - getCppuType( static_cast< - com::sun::star::ucb::InsertCommandArgument * >( 0 ) ) - ), - com::sun::star::ucb::CommandInfo( - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ), + getCppuType( static_cast< ucb::TransferInfo * >( 0 ) ) ); + nPos++; + aCmdInfo[ nPos ] = + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "createNewContent" ) ), -1, - getCppuType( static_cast< - com::sun::star::ucb::OpenCommandArgument2 * >( 0 ) ) - ), - - /////////////////////////////////////////////////////////////// - // New commands - /////////////////////////////////////////////////////////////// - - com::sun::star::ucb::CommandInfo( - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "post" ) ), - -1, - getCppuType( static_cast< - com::sun::star::ucb::PostCommandArgument2 * >( 0 ) ) - ) + getCppuType( static_cast< ucb::ContentInfo * >( 0 ) ) ); + nPos++; + } + else + { + // no document-only commands at the moment. + } - /* - com::sun::star::ucb::CommandInfo( - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "COPY" ) ), + if ( bSupportsLocking ) + { + aCmdInfo[ nPos ] = + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "lock" ) ), -1, - getCppuType( static_cast< const rtl::OUString * >( 0 ) ), - ), - com::sun::star::ucb::CommandInfo( - rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MOVE" ) ), + getCppuVoidType() ); + nPos++; + aCmdInfo[ nPos ] = + ucb::CommandInfo( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "unlock" ) ), -1, - getCppuType( static_cast< const rtl::OUString * >( 0 ) ), - ) - */ - }; - - return uno::Sequence< com::sun::star::ucb::CommandInfo >( - aDocumentCommandInfoTable, 8 ); + getCppuVoidType() ); + nPos++; } + return aCmdInfo; } - |