office-gobmx/ucb/source/ucp/webdav/NeonPropFindRequest.cxx
2011-02-26 22:39:23 +01:00

360 lines
13 KiB
C++

/* -*- 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.
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_ucb.hxx"
#include "osl/diagnose.h"
#include "rtl/strbuf.hxx"
#include "NeonTypes.hxx"
#include "DAVException.hxx"
#include "DAVProperties.hxx"
#include "NeonPropFindRequest.hxx"
#include "LinkSequence.hxx"
#include "LockSequence.hxx"
#include "LockEntrySequence.hxx"
#include "UCBDeadPropertyValue.hxx"
using namespace com::sun::star::uno;
using namespace com::sun::star::ucb;
using namespace std;
using namespace webdav_ucp;
using ::rtl::OUString;
using ::rtl::OString;
using ::rtl::OStringToOUString;
// -------------------------------------------------------------------
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,
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;
OSL_ENSURE( pname->nspace, "NPFR_propfind_iter - No 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 ) )
{
OSL_ENSURE( thePropertyValue.Value.hasValue(),
"NPFR_propfind_iter - No value!" );
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.getLength() )
{
aValue = stripDavNamespace( aValue ).toAsciiLowerCase();
if ( aValue.compareTo(
RTL_CONSTASCII_STRINGPARAM( "<collection" ) ) == 0 )
{
thePropertyValue.Value
<<= OUString(RTL_CONSTASCII_USTRINGPARAM("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.
}
// -------------------------------------------------------------------
extern "C" void NPFR_propfind_results( void* userdata,
#if NEON_VERSION >= 0x0260
const ne_uri* uri,
#else
const char* href,
#endif
const NeonPropFindResultSet* set )
{
// @@@ href is not the uri! DAVResource ctor wants uri!
#if NEON_VERSION >= 0x0260
DAVResource theResource(
OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) );
#else
DAVResource theResource(
OStringToOUString( href, RTL_TEXTENCODING_UTF8 ) );
#endif
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 );
}
// -------------------------------------------------------------------
extern "C" 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;
}
// -------------------------------------------------------------------
extern "C" void NPFR_propnames_results( void* userdata,
#if NEON_VERSION >= 0x0260
const ne_uri* uri,
#else
const char* href,
#endif
const NeonPropFindResultSet* results )
{
// @@@ href is not the uri! DAVResourceInfo ctor wants uri!
// Create entry for the resource.
#if NEON_VERSION >= 0x0260
DAVResourceInfo theResource(
OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) );
#else
DAVResourceInfo theResource(
OStringToOUString( href, RTL_TEXTENCODING_UTF8 ) );
#endif
// 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 );
}
extern osl::Mutex aGlobalNeonMutex;
// -------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------
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 )
{
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 = NULL;
thePropNames[ theIndex ].name = NULL;
{
osl::Guard< osl::Mutex > theGlobalGuard( aGlobalNeonMutex );
nError = ne_simple_propfind( inSession,
inPath,
inDepth,
thePropNames,
NPFR_propfind_results,
&ioResources );
}
for ( theIndex = 0; theIndex < thePropCount; theIndex ++ )
free( (void *)thePropNames[ theIndex ].name );
delete [] thePropNames;
}
else
{
// ALLPROP
osl::Guard< osl::Mutex > theGlobalGuard( aGlobalNeonMutex );
nError = ne_simple_propfind( inSession,
inPath,
inDepth,
NULL, // 0 == allprop
NPFR_propfind_results,
&ioResources );
}
// #87585# - Sometimes neon lies (because some servers lie).
if ( ( nError == NE_OK ) && ioResources.empty() )
nError = NE_ERROR;
}
// -------------------------------------------------------------------
// Constructor
// - obtains property names
// -------------------------------------------------------------------
NeonPropFindRequest::NeonPropFindRequest(
HttpSession* inSession,
const char* inPath,
const Depth inDepth,
std::vector< DAVResourceInfo > & ioResInfo,
int & nError )
{
{
osl::Guard< osl::Mutex > theGlobalGuard( aGlobalNeonMutex );
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;
}
// -------------------------------------------------------------------
// Destructor
// -------------------------------------------------------------------
NeonPropFindRequest::~NeonPropFindRequest( )
{
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */