summaryrefslogtreecommitdiffstats
path: root/ucb/source/ucp/webdav-neon/NeonPropFindRequest.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
commit940b4d1848e8c70ab7642901a68594e8016caffc (patch)
treeeb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /ucb/source/ucp/webdav-neon/NeonPropFindRequest.cxx
parentInitial commit. (diff)
downloadlibreoffice-upstream.tar.xz
libreoffice-upstream.zip
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ucb/source/ucp/webdav-neon/NeonPropFindRequest.cxx')
-rw-r--r--ucb/source/ucp/webdav-neon/NeonPropFindRequest.cxx321
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: */