blob: 4628bb6b607d192925556d531035e4741b8eb376 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_ucb.hxx"
/**************************************************************************
TODO
**************************************************************************
*************************************************************************/
#include <osl/diagnose.h>
#include <com/sun/star/util/DateTime.hpp>
#include "SerfUri.hxx"
#include "DAVResource.hxx"
#include "DAVProperties.hxx"
#include "DateTimeHelper.hxx"
#include "webdavprovider.hxx"
#include "ContentProperties.hxx"
using namespace com::sun::star;
using namespace http_dav_ucp;
/*
=============================================================================
Property Mapping
=============================================================================
HTTP (entity header) WebDAV (property) UCB (property)
=============================================================================
Allow
Content-Encoding
Content-Language getcontentlanguage
Content-Length getcontentlength Size
Content-Location
Content-MD5
Content-Range
Content-Type getcontenttype MediaType
Expires
Last-Modified getlastmodified DateModified
creationdate DateCreated
resourcetype IsFolder,IsDocument,ContentType
displayname
ETag (actually getetag
a response header )
lockdiscovery
supportedlock
source
Title (always taken from URI)
=============================================================================
Important: HTTP headers will not be mapped to DAV properties; only to UCB
properties. (Content-Length,Content-Type,Last-Modified)
*/
//=========================================================================
//=========================================================================
//
// ContentProperties Implementation.
//
//=========================================================================
//=========================================================================
// static member!
uno::Any ContentProperties::m_aEmptyAny;
ContentProperties::ContentProperties( const DAVResource& rResource )
: m_xProps( new PropertyValueMap ),
m_bTrailingSlash( false )
{
OSL_ENSURE( rResource.uri.getLength(),
"ContentProperties ctor - Empty resource URI!" );
// Title
try
{
SerfUri aURI( rResource.uri );
m_aEscapedTitle = aURI.GetPathBaseName();
(*m_xProps)[ rtl::OUString::createFromAscii( "Title" ) ]
= PropertyValue(
uno::makeAny( aURI.GetPathBaseNameUnescaped() ), true );
}
catch ( DAVException const & )
{
(*m_xProps)[ rtl::OUString::createFromAscii( "Title" ) ]
= PropertyValue(
uno::makeAny(
rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM( "*** unknown ***" ) ) ),
true );
}
std::vector< DAVPropertyValue >::const_iterator it
= rResource.properties.begin();
std::vector< DAVPropertyValue >::const_iterator end
= rResource.properties.end();
while ( it != end )
{
addProperty( (*it) );
++it;
}
if ( rResource.uri.getStr()[ rResource.uri.getLength() - 1 ]
== sal_Unicode( '/' ) )
m_bTrailingSlash = sal_True;
}
//=========================================================================
ContentProperties::ContentProperties(
const rtl::OUString & rTitle, sal_Bool bFolder )
: m_xProps( new PropertyValueMap ),
m_bTrailingSlash( sal_False )
{
(*m_xProps)[ rtl::OUString::createFromAscii( "Title" ) ]
= PropertyValue( uno::makeAny( rTitle ), true );
(*m_xProps)[ rtl::OUString::createFromAscii( "IsFolder" ) ]
= PropertyValue( uno::makeAny( bFolder ), true );
(*m_xProps)[ rtl::OUString::createFromAscii( "IsDocument" ) ]
= PropertyValue( uno::makeAny( sal_Bool( !bFolder ) ), true );
}
//=========================================================================
ContentProperties::ContentProperties( const rtl::OUString & rTitle )
: m_xProps( new PropertyValueMap ),
m_bTrailingSlash( sal_False )
{
(*m_xProps)[ rtl::OUString::createFromAscii( "Title" ) ]
= PropertyValue( uno::makeAny( rTitle ), true );
}
//=========================================================================
ContentProperties::ContentProperties()
: m_xProps( new PropertyValueMap ),
m_bTrailingSlash( sal_False )
{
}
//=========================================================================
ContentProperties::ContentProperties( const ContentProperties & rOther )
: m_aEscapedTitle( rOther.m_aEscapedTitle ),
m_xProps( rOther.m_xProps.get()
? new PropertyValueMap( *rOther.m_xProps )
: new PropertyValueMap ),
m_bTrailingSlash( rOther.m_bTrailingSlash )
{
}
//=========================================================================
bool ContentProperties::contains( const rtl::OUString & rName ) const
{
if ( get( rName ) )
return true;
else
return false;
}
//=========================================================================
const uno::Any & ContentProperties::getValue(
const rtl::OUString & rName ) const
{
const PropertyValue * pProp = get( rName );
if ( pProp )
return pProp->value();
else
return m_aEmptyAny;
}
//=========================================================================
const PropertyValue * ContentProperties::get(
const rtl::OUString & rName ) const
{
PropertyValueMap::const_iterator it = m_xProps->find( rName );
const PropertyValueMap::const_iterator end = m_xProps->end();
if ( it == end )
{
it = m_xProps->begin();
while ( it != end )
{
if ( (*it).first.equalsIgnoreAsciiCase( rName ) )
return &(*it).second;
++it;
}
return 0;
}
else
return &(*it).second;
}
//=========================================================================
// static
void ContentProperties::UCBNamesToDAVNames(
const uno::Sequence< beans::Property > & rProps,
std::vector< rtl::OUString > & propertyNames,
bool bIncludeUnmatched /* = true */ )
{
//////////////////////////////////////////////////////////////
// Assemble list of DAV properties to obtain from server.
// Append DAV properties needed to obtain requested UCB props.
//////////////////////////////////////////////////////////////
// DAV UCB
// creationdate <- DateCreated
// getlastmodified <- DateModified
// getcontenttype <- MediaType
// getcontentlength <- Size
// resourcetype <- IsFolder, IsDocument, ContentType
// (taken from URI) <- Title
sal_Bool bCreationDate = sal_False;
sal_Bool bLastModified = sal_False;
sal_Bool bContentType = sal_False;
sal_Bool bContentLength = sal_False;
sal_Bool bResourceType = sal_False;
sal_Int32 nCount = rProps.getLength();
for ( sal_Int32 n = 0; n < nCount; ++n )
{
const beans::Property & rProp = rProps[ n ];
if ( rProp.Name.equalsAsciiL(
RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
{
// Title is always obtained from resource's URI.
continue;
}
else if ( rProp.Name.equalsAsciiL(
RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) )
||
( rProp.Name == DAVProperties::CREATIONDATE ) )
{
if ( !bCreationDate )
{
propertyNames.push_back( DAVProperties::CREATIONDATE );
bCreationDate = sal_True;
}
}
else if ( rProp.Name.equalsAsciiL(
RTL_CONSTASCII_STRINGPARAM( "DateModified" ) )
||
( rProp.Name == DAVProperties::GETLASTMODIFIED ) )
{
if ( !bLastModified )
{
propertyNames.push_back(
DAVProperties::GETLASTMODIFIED );
bLastModified = sal_True;
}
}
else if ( rProp.Name.equalsAsciiL(
RTL_CONSTASCII_STRINGPARAM( "MediaType" ) )
||
( rProp.Name == DAVProperties::GETCONTENTTYPE ) )
{
if ( !bContentType )
{
propertyNames.push_back(
DAVProperties::GETCONTENTTYPE );
bContentType = sal_True;
}
}
else if ( rProp.Name.equalsAsciiL(
RTL_CONSTASCII_STRINGPARAM( "Size" ) )
||
( rProp.Name == DAVProperties::GETCONTENTLENGTH ) )
{
if ( !bContentLength )
{
propertyNames.push_back(
DAVProperties::GETCONTENTLENGTH );
bContentLength = sal_True;
}
}
else if ( rProp.Name.equalsAsciiL(
RTL_CONSTASCII_STRINGPARAM( "ContentType" ) )
||
rProp.Name.equalsAsciiL(
RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) )
||
rProp.Name.equalsAsciiL(
RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) )
||
( rProp.Name == DAVProperties::RESOURCETYPE ) )
{
if ( !bResourceType )
{
propertyNames.push_back( DAVProperties::RESOURCETYPE );
bResourceType = sal_True;
}
}
else
{
if ( bIncludeUnmatched )
propertyNames.push_back( rProp.Name );
}
}
}
//=========================================================================
// static
void ContentProperties::UCBNamesToHTTPNames(
const uno::Sequence< beans::Property > & rProps,
std::vector< rtl::OUString > & propertyNames,
bool bIncludeUnmatched /* = true */ )
{
//////////////////////////////////////////////////////////////
// Assemble list of HTTP header names to obtain from server.
// Append HTTP headers needed to obtain requested UCB props.
//////////////////////////////////////////////////////////////
// HTTP UCB
// Last-Modified <- DateModified
// Content-Type <- MediaType
// Content-Length <- Size
sal_Int32 nCount = rProps.getLength();
for ( sal_Int32 n = 0; n < nCount; ++n )
{
const beans::Property & rProp = rProps[ n ];
if ( rProp.Name.equalsAsciiL(
RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) )
{
propertyNames.push_back(
rtl::OUString::createFromAscii( "Last-Modified" ) );
}
else if ( rProp.Name.equalsAsciiL(
RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) )
{
propertyNames.push_back(
rtl::OUString::createFromAscii( "Content-Type" ) );
}
else if ( rProp.Name.equalsAsciiL(
RTL_CONSTASCII_STRINGPARAM( "Size" ) ) )
{
propertyNames.push_back(
rtl::OUString::createFromAscii( "Content-Length" ) );
}
else
{
if ( bIncludeUnmatched )
propertyNames.push_back( rProp.Name );
}
}
}
//=========================================================================
bool ContentProperties::containsAllNames(
const uno::Sequence< beans::Property >& rProps,
std::vector< rtl::OUString > & rNamesNotContained ) const
{
rNamesNotContained.clear();
sal_Int32 nCount = rProps.getLength();
for ( sal_Int32 n = 0; n < nCount; ++n )
{
const rtl::OUString & rName = rProps[ n ].Name;
if ( !contains( rName ) )
{
// Not found.
rNamesNotContained.push_back( rName );
}
}
return ( rNamesNotContained.size() == 0 );
}
//=========================================================================
void ContentProperties::addProperties(
const std::vector< rtl::OUString > & rProps,
const ContentProperties & rContentProps )
{
std::vector< rtl::OUString >::const_iterator it = rProps.begin();
std::vector< rtl::OUString >::const_iterator end = rProps.end();
while ( it != end )
{
const rtl::OUString & rName = (*it);
if ( !contains( rName ) ) // ignore duplicates
{
const PropertyValue * pProp = rContentProps.get( rName );
if ( pProp )
{
// Add it.
addProperty( rName, pProp->value(), pProp->isCaseSensitive() );
}
else
{
addProperty( rName, uno::Any(), false );
}
}
++it;
}
}
//=========================================================================
void ContentProperties::addProperties( const ContentProperties & rProps )
{
PropertyValueMap::const_iterator it = rProps.m_xProps->begin();
const PropertyValueMap::const_iterator end = rProps.m_xProps->end();
while ( it != end )
{
addProperty(
(*it).first, (*it).second.value(), (*it).second.isCaseSensitive() );
++it;
}
}
//=========================================================================
void ContentProperties::addProperties(
const std::vector< DAVPropertyValue > & rProps )
{
std::vector< DAVPropertyValue >::const_iterator it = rProps.begin();
const std::vector< DAVPropertyValue >::const_iterator end = rProps.end();
while ( it != end )
{
addProperty( (*it) );
++it;
}
}
//=========================================================================
void ContentProperties::addProperty( const DAVPropertyValue & rProp )
{
addProperty( rProp.Name, rProp.Value, rProp.IsCaseSensitive );
}
//=========================================================================
void ContentProperties::addProperty( const rtl::OUString & rName,
const com::sun::star::uno::Any & rValue,
bool bIsCaseSensitive )
{
if ( rName.equals( DAVProperties::CREATIONDATE ) )
{
// Map DAV:creationdate to UCP:DateCreated
rtl::OUString aValue;
rValue >>= aValue;
util::DateTime aDate;
DateTimeHelper::convert( aValue, aDate );
(*m_xProps)[ rtl::OUString::createFromAscii( "DateCreated" ) ]
= PropertyValue( uno::makeAny( aDate ), true );
}
// else if ( rName.equals( DAVProperties::DISPLAYNAME ) )
// {
// }
// else if ( rName.equals( DAVProperties::GETCONTENTLANGUAGE ) )
// {
// }
else if ( rName.equals( DAVProperties::GETCONTENTLENGTH ) )
{
// Map DAV:getcontentlength to UCP:Size
rtl::OUString aValue;
rValue >>= aValue;
(*m_xProps)[ rtl::OUString::createFromAscii( "Size" ) ]
= PropertyValue( uno::makeAny( aValue.toInt64() ), true );
}
else if ( rName.equalsAsciiL(
RTL_CONSTASCII_STRINGPARAM( "Content-Length" ) ) )
{
// Do NOT map Content-Lenght entity header to DAV:getcontentlength!
// Only DAV resources have this property.
// Map Content-Length entity header to UCP:Size
rtl::OUString aValue;
rValue >>= aValue;
(*m_xProps)[ rtl::OUString::createFromAscii( "Size" ) ]
= PropertyValue( uno::makeAny( aValue.toInt64() ), true );
}
else if ( rName.equals( DAVProperties::GETCONTENTTYPE ) )
{
// Map DAV:getcontenttype to UCP:MediaType (1:1)
(*m_xProps)[ rtl::OUString::createFromAscii( "MediaType" ) ]
= PropertyValue( rValue, true );
}
else if ( rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Content-Type" ) ) )
{
// Do NOT map Content-Type entity header to DAV:getcontenttype!
// Only DAV resources have this property.
// Map DAV:getcontenttype to UCP:MediaType (1:1)
(*m_xProps)[ rtl::OUString::createFromAscii( "MediaType" ) ]
= PropertyValue( rValue, true );
}
// else if ( rName.equals( DAVProperties::GETETAG ) )
// {
// }
else if ( rName.equals( DAVProperties::GETLASTMODIFIED ) )
{
// Map the DAV:getlastmodified entity header to UCP:DateModified
rtl::OUString aValue;
rValue >>= aValue;
util::DateTime aDate;
DateTimeHelper::convert( aValue, aDate );
(*m_xProps)[ rtl::OUString::createFromAscii( "DateModified" ) ]
= PropertyValue( uno::makeAny( aDate ), true );
}
else if ( rName.equalsAsciiL(
RTL_CONSTASCII_STRINGPARAM( "Last-Modified" ) ) )
{
// Do not map Last-Modified entity header to DAV:getlastmodified!
// Only DAV resources have this property.
// Map the Last-Modified entity header to UCP:DateModified
rtl::OUString aValue;
rValue >>= aValue;
util::DateTime aDate;
DateTimeHelper::convert( aValue, aDate );
(*m_xProps)[ rtl::OUString::createFromAscii( "DateModified" ) ]
= PropertyValue( uno::makeAny( aDate ), true );
}
// else if ( rName.equals( DAVProperties::LOCKDISCOVERY ) )
// {
// }
else if ( rName.equals( DAVProperties::RESOURCETYPE ) )
{
rtl::OUString aValue;
rValue >>= aValue;
// Map DAV:resourceype to UCP:IsFolder, UCP:IsDocument, UCP:ContentType
sal_Bool bFolder =
aValue.equalsIgnoreAsciiCaseAsciiL(
RTL_CONSTASCII_STRINGPARAM( "collection" ) );
(*m_xProps)[ rtl::OUString::createFromAscii( "IsFolder" ) ]
= PropertyValue( uno::makeAny( bFolder ), true );
(*m_xProps)[ rtl::OUString::createFromAscii( "IsDocument" ) ]
= PropertyValue( uno::makeAny( sal_Bool( !bFolder ) ), true );
(*m_xProps)[ rtl::OUString::createFromAscii( "ContentType" ) ]
= PropertyValue( uno::makeAny( bFolder
? rtl::OUString::createFromAscii( WEBDAV_COLLECTION_TYPE )
: rtl::OUString::createFromAscii( WEBDAV_CONTENT_TYPE ) ), true );
}
// else if ( rName.equals( DAVProperties::SUPPORTEDLOCK ) )
// {
// }
// Save property.
(*m_xProps)[ rName ] = PropertyValue( rValue, bIsCaseSensitive );
}
//=========================================================================
//=========================================================================
//
// CachableContentProperties Implementation.
//
//=========================================================================
//=========================================================================
namespace
{
bool isCachable( rtl::OUString const & rName,
bool isCaseSensitive )
{
static rtl::OUString aNonCachableProps [] =
{
DAVProperties::LOCKDISCOVERY,
DAVProperties::GETETAG,
rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ETag" ) ),
rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateModified" ) ),
rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Last-Modified" ) ),
DAVProperties::GETLASTMODIFIED,
rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Size" ) ),
rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Content-Length" ) ),
DAVProperties::GETCONTENTLENGTH,
rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Date" ) )
};
for ( sal_uInt32 n = 0;
n < ( sizeof( aNonCachableProps )
/ sizeof( aNonCachableProps[ 0 ] ) );
++n )
{
if ( isCaseSensitive )
{
if ( rName.equals( aNonCachableProps[ n ] ) )
return false;
}
else
if ( rName.equalsIgnoreAsciiCase( aNonCachableProps[ n ] ) )
return false;
}
return true;
}
} // namespace
//=========================================================================
CachableContentProperties::CachableContentProperties(
const ContentProperties & rProps )
{
addProperties( rProps );
}
//=========================================================================
void CachableContentProperties::addProperties(
const ContentProperties & rProps )
{
const std::auto_ptr< PropertyValueMap > & props = rProps.getProperties();
PropertyValueMap::const_iterator it = props->begin();
const PropertyValueMap::const_iterator end = props->end();
while ( it != end )
{
if ( isCachable( (*it).first, (*it).second.isCaseSensitive() ) )
m_aProps.addProperty( (*it).first,
(*it).second.value(),
(*it).second.isCaseSensitive() );
++it;
}
}
//=========================================================================
void CachableContentProperties::addProperties(
const std::vector< DAVPropertyValue > & rProps )
{
std::vector< DAVPropertyValue >::const_iterator it = rProps.begin();
const std::vector< DAVPropertyValue >::const_iterator end = rProps.end();
while ( it != end )
{
if ( isCachable( (*it).Name, (*it).IsCaseSensitive ) )
m_aProps.addProperty( (*it) );
++it;
}
}