diff options
Diffstat (limited to 'ucb/source/ucp/webdav-neon/NeonPropFindRequest.cxx')
-rw-r--r-- | ucb/source/ucp/webdav-neon/NeonPropFindRequest.cxx | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/ucb/source/ucp/webdav-neon/NeonPropFindRequest.cxx b/ucb/source/ucp/webdav-neon/NeonPropFindRequest.cxx new file mode 100644 index 000000000..cf03274c5 --- /dev/null +++ b/ucb/source/ucp/webdav-neon/NeonPropFindRequest.cxx @@ -0,0 +1,321 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + + +#include <osl/mutex.hxx> +#include <rtl/strbuf.hxx> +#include <sal/log.hxx> +#include "NeonSession.hxx" +#include "NeonTypes.hxx" +#include "DAVProperties.hxx" +#include "NeonPropFindRequest.hxx" +#include "LinkSequence.hxx" +#include "LockSequence.hxx" +#include "LockEntrySequence.hxx" +#include "UCBDeadPropertyValue.hxx" +#include <memory> + +using namespace com::sun::star::uno; +using namespace com::sun::star::ucb; +using namespace std; +using namespace webdav_ucp; + + +namespace +{ + // strip "DAV:" namespace from XML snippets to avoid + // parser error (undeclared namespace) later on. + OString stripDavNamespace( const OString & in ) + { + const OString inXML( in.toAsciiLowerCase() ); + + 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 buf.makeStringAndClear(); + } +} + +extern "C" { + +static int NPFR_propfind_iter( void* userdata, + const NeonPropName* pname, + const char* value, + const HttpStatus* status ) +{ + /* + HTTP Response Status Classes: + + - 1: Informational - Request received, continuing process + + - 2: Success - The action was successfully received, + understood, and accepted + + - 3: Redirection - Further action must be taken in order to + complete the request + + - 4: Client Error - The request contains bad syntax or cannot + be fulfilled + + - 5: Server Error - The server failed to fulfill an apparently + valid request + */ + + if ( status->klass > 2 ) + return 0; // Error getting this property. Go on. + + // Create & set the PropertyValue + DAVPropertyValue thePropertyValue; + thePropertyValue.IsCaseSensitive = true; + + SAL_WARN_IF( !pname->nspace, "ucb.ucp.webdav", "NPFR_propfind_iter - No XML namespace!" ); + + DAVProperties::createUCBPropName( pname->nspace, + pname->name, + thePropertyValue.Name ); + bool bHasValue = false; + if ( DAVProperties::isUCBDeadProperty( *pname ) ) + { + // DAV dead property added by WebDAV UCP? + if ( UCBDeadPropertyValue::createFromXML( + value, thePropertyValue.Value ) ) + { + SAL_WARN_IF( !thePropertyValue.Value.hasValue(), + "ucb.ucp.webdav", "NPFR_propfind_iter - No value for UCBDeadProperty!" ); + bHasValue = true; + } + } + + if ( !bHasValue ) + { + if ( rtl_str_compareIgnoreAsciiCase( + pname->name, "resourcetype" ) == 0 ) + { + OString aValue( value ); + aValue = aValue.trim(); // #107358# remove leading/trailing spaces + if ( !aValue.isEmpty() ) + { + aValue = stripDavNamespace( aValue ).toAsciiLowerCase(); + if ( aValue.startsWith("<collection") ) + { + thePropertyValue.Value + <<= OUString("collection"); + } + } + + if ( !thePropertyValue.Value.hasValue() ) + { + // Take over the value exactly as supplied by the server. + thePropertyValue.Value <<= OUString::createFromAscii( value ); + } + } + else if ( rtl_str_compareIgnoreAsciiCase( + pname->name, "supportedlock" ) == 0 ) + { + Sequence< LockEntry > aEntries; + LockEntrySequence::createFromXML( + stripDavNamespace( value ), aEntries ); + thePropertyValue.Value <<= aEntries; + } + else if ( rtl_str_compareIgnoreAsciiCase( + pname->name, "lockdiscovery" ) == 0 ) + { + Sequence< Lock > aLocks; + LockSequence::createFromXML( + stripDavNamespace( value ), aLocks ); + thePropertyValue.Value <<= aLocks; + } + else if ( rtl_str_compareIgnoreAsciiCase( pname->name, "source" ) == 0 ) + { + Sequence< Link > aLinks; + LinkSequence::createFromXML( + stripDavNamespace( value ), aLinks ); + thePropertyValue.Value <<= aLinks; + } + else + { + thePropertyValue.Value + <<= OStringToOUString( value, RTL_TEXTENCODING_UTF8 ); + } + } + + // Add the newly created PropertyValue + DAVResource* theResource = static_cast< DAVResource * >( userdata ); + theResource->properties.push_back( thePropertyValue ); + + return 0; // Go on. +} + +static void NPFR_propfind_results( void* userdata, + const ne_uri* uri, + const NeonPropFindResultSet* set ) +{ + // @@@ href is not the uri! DAVResource ctor wants uri! + + DAVResource theResource( + OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) ); + + ne_propset_iterate( set, NPFR_propfind_iter, &theResource ); + + // Add entry to resources list. + vector< DAVResource > * theResources + = static_cast< vector< DAVResource > * >( userdata ); + theResources->push_back( theResource ); +} + +static int NPFR_propnames_iter( void* userdata, + const NeonPropName* pname, + const char* /*value*/, + const HttpStatus* /*status*/ ) +{ + OUString aFullName; + DAVProperties::createUCBPropName( pname->nspace, + pname->name, + aFullName ); + + DAVResourceInfo* theResource = static_cast< DAVResourceInfo * >( userdata ); + theResource->properties.push_back( aFullName ); + return 0; +} + +static void NPFR_propnames_results( void* userdata, + const ne_uri* /*uri*/, + const NeonPropFindResultSet* results ) +{ + // @@@ href is not the uri! DAVResourceInfo ctor wants uri! + // Create entry for the resource. + DAVResourceInfo theResource; + + // Fill entry. + ne_propset_iterate( results, NPFR_propnames_iter, &theResource ); + + // Add entry to resources list. + vector< DAVResourceInfo > * theResources + = static_cast< vector< DAVResourceInfo > * >( userdata ); + theResources->push_back( theResource ); +} + +} + +NeonPropFindRequest::NeonPropFindRequest( HttpSession* inSession, + const char* inPath, + const Depth inDepth, + const vector< OUString >& inPropNames, + vector< DAVResource >& ioResources, + int & nError ) +{ + // Generate the list of properties we're looking for + int thePropCount = inPropNames.size(); + if ( thePropCount > 0 ) + { + std::unique_ptr<NeonPropName[]> thePropNames(new NeonPropName[ thePropCount + 1 ]); + int theIndex; + + for ( theIndex = 0; theIndex < thePropCount; theIndex ++ ) + { + // Split fullname into namespace and name! + DAVProperties::createNeonPropName( + inPropNames[ theIndex ], thePropNames[ theIndex ] ); + } + thePropNames[ theIndex ].nspace = nullptr; + thePropNames[ theIndex ].name = nullptr; + + { + osl::Guard< osl::Mutex > theGlobalGuard(getGlobalNeonMutex()); + nError = ne_simple_propfind( inSession, + inPath, + inDepth, + thePropNames.get(), + NPFR_propfind_results, + &ioResources ); + } + + for ( theIndex = 0; theIndex < thePropCount; theIndex ++ ) + free( const_cast<char *>(thePropNames[ theIndex ].name) ); + } + else + { + // ALLPROP + osl::Guard< osl::Mutex > theGlobalGuard(getGlobalNeonMutex()); + nError = ne_simple_propfind( inSession, + inPath, + inDepth, + nullptr, // 0 == allprop + NPFR_propfind_results, + &ioResources ); + } + + // #87585# - Sometimes neon lies (because some servers lie). + if ( ( nError == NE_OK ) && ioResources.empty() ) + nError = NE_ERROR; +} + +NeonPropFindRequest::NeonPropFindRequest( + HttpSession* inSession, + const char* inPath, + const Depth inDepth, + std::vector< DAVResourceInfo > & ioResInfo, + int & nError ) +{ + { + osl::Guard< osl::Mutex > theGlobalGuard(getGlobalNeonMutex()); + nError = ne_propnames( inSession, + inPath, + inDepth, + NPFR_propnames_results, + &ioResInfo ); + } + + // #87585# - Sometimes neon lies (because some servers lie). + if ( ( nError == NE_OK ) && ioResInfo.empty() ) + nError = NE_ERROR; +} + +NeonPropFindRequest::~NeonPropFindRequest( ) +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |